[Scummvm-git-logs] scummvm master -> 4fd00b7aa3a38df90bcdc0f743ec89faecca8328

Scorpeg noreply at scummvm.org
Thu Oct 22 10:06:36 UTC 2026


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .

Summary:
4fd00b7aa3 VIDEO: Add WMV3/VC-1 support and extract shared MSMPEG4 code


Commit: 4fd00b7aa3a38df90bcdc0f743ec89faecca8328
    https://github.com/scummvm/scummvm/commit/4fd00b7aa3a38df90bcdc0f743ec89faecca8328
Author: Scorp (scorp at mrs.mn)
Date: 2026-10-22T13:04:53+03:00

Commit Message:
VIDEO: Add WMV3/VC-1 support and extract shared MSMPEG4 code

Changed paths:
  A image/codecs/msmpeg4_vc1.cpp
  A image/codecs/msmpeg4_vc1.h
  A image/codecs/vc1.cpp
  A image/codecs/vc1.h
    configure
    engines/testbed/configure.engine
    image/codecs/codec.cpp
    image/codecs/msmpeg4.cpp
    image/module.mk


diff --git a/configure b/configure
index ff45575dde9..1eea0444a49 100755
--- a/configure
+++ b/configure
@@ -315,6 +315,7 @@ _fmtowns_pc98_audio=auto
 _sid_audio=auto
 _svq1=auto
 _truemotion1=auto
+_vc1=auto
 _unp64=auto
 _vgmtrans_audio=auto
 _xan=auto
@@ -368,6 +369,7 @@ add_component tinygl "TinyGL" "_tinygl" "USE_TINYGL"
 add_component truemotion1 "TrueMotion 1" "_truemotion1" "USE_TRUEMOTION1"
 add_component universaltracker "External Tracker Libraries" "_universaltracker" "USE_UNIVERSALTRACKER"
 add_component unp64 "UNP64" "_unp64" "USE_UNP64"
+add_component vc1 "VC-1 / WMV3" "_vc1" "USE_VC1"
 add_component vgmtrans_audio "VGMTrans Soundfont audio" "_vgmtrans_audio" "USE_VGMTRANS_AUDIO"
 add_component xan "XAN" "_xan" "USE_XAN"
 
diff --git a/engines/testbed/configure.engine b/engines/testbed/configure.engine
index de7f7a95619..fe21f935748 100644
--- a/engines/testbed/configure.engine
+++ b/engines/testbed/configure.engine
@@ -1,3 +1,3 @@
 # This file is included from the main "configure" script
 # add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] [components]
-add_engine testbed "TestBed: the Testing framework" no "" "" "" "imgui midi universaltracker cdtoons indeo3 indeo45 vpx mpc hnm jyv1 mpeg2 msmpeg4 qdm2 svq1 truemotion1 xan tinygl"
+add_engine testbed "TestBed: the Testing framework" no "" "" "" "imgui midi universaltracker cdtoons indeo3 indeo45 vpx mpc hnm jyv1 mpeg2 msmpeg4 qdm2 svq1 truemotion1 vc1 xan tinygl"
diff --git a/image/codecs/codec.cpp b/image/codecs/codec.cpp
index 3447e6dce4e..6a7b69acc46 100644
--- a/image/codecs/codec.cpp
+++ b/image/codecs/codec.cpp
@@ -43,6 +43,9 @@
 #include "image/codecs/svq1.h"
 #include "image/codecs/truemotion1.h"
 #include "image/codecs/xan.h"
+#ifdef USE_VC1
+#include "image/codecs/vc1.h"
+#endif
 
 #include "common/endian.h"
 #include "common/system.h"
@@ -99,6 +102,24 @@ Codec *createBitmapCodec(uint32 tag, uint32 streamTag, int width, int height, in
 		break;
 #endif
 
+	case MKTAG('W', 'M', 'V', '3'):
+	case MKTAG('w', 'm', 'v', '3'):
+#ifdef USE_VC1
+		return new WMV3Decoder(width, height);
+#else
+		missingCodec = "WMV3";
+		break;
+#endif
+	case MKTAG('W', 'V', 'C', '1'):
+	case MKTAG('w', 'v', 'c', '1'):
+	case MKTAG('W', 'M', 'V', 'A'):
+#ifdef USE_VC1
+		return new WMV3Decoder(width, height, true);
+#else
+		missingCodec = "VC-1";
+		break;
+#endif
+
 	case MKTAG('I','V','3','2'):
 #ifdef USE_INDEO3
 		return new Indeo3Decoder(width, height, bitsPerPixel);
@@ -212,6 +233,24 @@ Codec *createQuickTimeCodec(uint32 tag, int width, int height, int bitsPerPixel)
 	case MKTAG('r','a','w',' '):
 		// Used my L-Zone-mac (Director game)
 		return new BitmapRawDecoder(width, height, bitsPerPixel, true, true);
+	case MKTAG('W', 'M', 'V', '3'):
+	case MKTAG('w', 'm', 'v', '3'):
+#ifdef USE_VC1
+		return new WMV3Decoder(width, height);
+#else
+		missingCodec = "WMV3";
+		break;
+#endif
+	case MKTAG('W', 'V', 'C', '1'):
+	case MKTAG('w', 'v', 'c', '1'):
+	case MKTAG('W', 'M', 'V', 'A'):
+#ifdef USE_VC1
+		return new WMV3Decoder(width, height, true);
+#else
+		missingCodec = "VC-1";
+		break;
+#endif
+
 	case MKTAG('I','V','3','2'):
 #ifdef USE_INDEO3
 		// Indeo 3: Used by Team Xtreme: Operation Weather Disaster (Spanish)
diff --git a/image/codecs/msmpeg4.cpp b/image/codecs/msmpeg4.cpp
index bf68b045134..a7c19575338 100644
--- a/image/codecs/msmpeg4.cpp
+++ b/image/codecs/msmpeg4.cpp
@@ -33,6 +33,7 @@
  */
 
 #include "image/codecs/msmpeg4.h"
+#include "image/codecs/msmpeg4_vc1.h"
 
 #include "common/endian.h"
 #include "common/memstream.h"
@@ -422,27 +423,6 @@ const INT8 intra_run[102] = {
  15, 16, 17, 18, 19, 20,
 };
 
-
-/* intra picture macro block coded block pattern */
-const UINT16 table_mb_intra[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 },
-};
-
 /* non intra picture macro block coded block pattern + mb type */
 const UINT32 table_mb_non_intra[128][2] = {
 { 0x40, 7 },{ 0x13c9, 13 },{ 0x9fd, 12 },{ 0x1fc, 15 },
@@ -479,142 +459,6 @@ const UINT32 table_mb_non_intra[128][2] = {
 { 0x5, 5 },{ 0xb, 10 },{ 0x9c, 8 },{ 0xe, 10 },
 };
 
-/* dc table 0 */
-
-static const UINT32 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 },
-};
-
-static const UINT32 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 },
-};
-
-/* dc table 1 */
-
-const UINT32 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 },
-};
-
-const UINT32 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 },
-};
-
 /* vlc table 0, for intra luma */
 
 static const UINT16 table0_vlc[133][2] = {
@@ -3323,12 +3167,12 @@ static void initMsmpeg4Tables() {
 		MVTable *mv = &mv_tables[i];
 		initVlc(&mv->vlc, 9, mv->n + 1, mv->table_mv_bits, 1, 1, mv->table_mv_code, 2, 2);
 	}
-	initVlc(&gDcLumVlc[0], 9, 120, &table0_dc_lum[0][1], 8, 4, &table0_dc_lum[0][0], 8, 4);
-	initVlc(&gDcChromaVlc[0], 9, 120, &table0_dc_chroma[0][1], 8, 4, &table0_dc_chroma[0][0], 8, 4);
-	initVlc(&gDcLumVlc[1], 9, 120, &table1_dc_lum[0][1], 8, 4, &table1_dc_lum[0][0], 8, 4);
-	initVlc(&gDcChromaVlc[1], 9, 120, &table1_dc_chroma[0][1], 8, 4, &table1_dc_chroma[0][0], 8, 4);
+	initVlc(&gDcLumVlc[0], 9, 120, &MSMPEG4VC1::ff_msmp4_dc_tables[0][0][0][1], 8, 4, &MSMPEG4VC1::ff_msmp4_dc_tables[0][0][0][0], 8, 4);
+	initVlc(&gDcChromaVlc[0], 9, 120, &MSMPEG4VC1::ff_msmp4_dc_tables[0][1][0][1], 8, 4, &MSMPEG4VC1::ff_msmp4_dc_tables[0][1][0][0], 8, 4);
+	initVlc(&gDcLumVlc[1], 9, 120, &MSMPEG4VC1::ff_msmp4_dc_tables[1][0][0][1], 8, 4, &MSMPEG4VC1::ff_msmp4_dc_tables[1][0][0][0], 8, 4);
+	initVlc(&gDcChromaVlc[1], 9, 120, &MSMPEG4VC1::ff_msmp4_dc_tables[1][1][0][1], 8, 4, &MSMPEG4VC1::ff_msmp4_dc_tables[1][1][0][0], 8, 4);
 	initVlc(&gMbNonIntraVlc, 9, 128, &table_mb_non_intra[0][1], 8, 4, &table_mb_non_intra[0][0], 8, 4);
-	initVlc(&gMbIntraVlc, 9, 64, &table_mb_intra[0][1], 4, 2, &table_mb_intra[0][0], 4, 2);
+	initVlc(&gMbIntraVlc, 9, 64, &MSMPEG4VC1::ff_msmp4_mb_i_table[0][1], 4, 2, &MSMPEG4VC1::ff_msmp4_mb_i_table[0][0], 4, 2);
 }
 
 } // End of namespace
@@ -3931,22 +3775,7 @@ void MSMPEG4Decoder::frameEnd() {
 }
 
 static void putPixels(byte *dst, const byte *src, int pitch, int h, int mode, bool noRounding) {
-	for (int y = 0; y < h; ++y) {
-		for (int x = 0; x < 8; ++x) {
-			int value;
-			if (mode == 0)
-				value = src[x];
-			else if (mode == 1)
-				value = noRounding ? ((src[x] + src[x + 1]) >> 1) : ((src[x] + src[x + 1] + 1) >> 1);
-			else if (mode == 2)
-				value = noRounding ? ((src[x] + src[x + pitch]) >> 1) : ((src[x] + src[x + pitch] + 1) >> 1);
-			else
-				value = noRounding ? ((src[x] + src[x + 1] + src[x + pitch] + src[x + pitch + 1] + 1) >> 2) : ((src[x] + src[x + 1] + src[x + pitch] + src[x + pitch + 1] + 2) >> 2);
-			dst[x] = value;
-		}
-		dst += pitch;
-		src += pitch;
-	}
+	putHalfPixels<8>(dst, src, pitch, h, mode, noRounding);
 }
 
 static void motionCompensatePlane(byte *dst, const byte *ref, int dstPitch, int refPitch, int dstX, int dstY,
diff --git a/image/codecs/msmpeg4_vc1.cpp b/image/codecs/msmpeg4_vc1.cpp
new file mode 100644
index 00000000000..623aa8096d1
--- /dev/null
+++ b/image/codecs/msmpeg4_vc1.cpp
@@ -0,0 +1,137 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program 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 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*
+ * Shared Microsoft MPEG-4 and VC-1 decoding tables.
+ *
+ * These tables are a ScummVM port of libavcodec/msmpeg4_vc1_data.c
+ * from FFmpeg revision c23123630e6a7e645c199599b8ade3fe7e9ab3db:
+ * https://git.ffmpeg.org/gitweb/ffmpeg.git/commit/c23123630e6a7e645c199599b8ade3fe7e9ab3db
+ * The original code was Copyright (c) 2001 Fabrice Bellard and
+ * (c) 2002-2004 Michael Niedermayer <michaelni at gmx.at>, distributed under
+ * the GNU LGPL version 2.1 or later. The shared tables contain the DC
+ * differential codes and intra-picture macroblock coded block patterns.
+ */
+
+#include "image/codecs/msmpeg4_vc1.h"
+
+namespace Image {
+namespace MSMPEG4VC1 {
+
+/* intra picture macro block coded block pattern */
+const uint16 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},
+};
+const uint32 ff_msmp4_dc_tables[2][2][120][2] = {
+	/* dc table 0 */
+	{ {
+		 {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},
+	 },
+	 {
+		 {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 */
+	{ {
+		 {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},
+	 },
+	 {
+		 {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},
+	 }}};
+
+} // namespace MSMPEG4VC1
+} // namespace Image
diff --git a/image/codecs/msmpeg4_vc1.h b/image/codecs/msmpeg4_vc1.h
new file mode 100644
index 00000000000..7f7582320d0
--- /dev/null
+++ b/image/codecs/msmpeg4_vc1.h
@@ -0,0 +1,63 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program 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 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef IMAGE_CODECS_MSMPEG4_VC1_H
+#define IMAGE_CODECS_MSMPEG4_VC1_H
+
+#include "common/scummsys.h"
+
+namespace Image {
+namespace MSMPEG4VC1 {
+
+extern const uint16 ff_msmp4_mb_i_table[64][2];
+extern const uint32 ff_msmp4_dc_tables[2][2][120][2];
+
+} // namespace MSMPEG4VC1
+/**
+ * Half-pixel interpolation shared by the MSMPEG4 and VC-1 decoders.
+ * Extracted from the MSMPEG4 port of FFmpeg revision 2cb1773ddc
+ * (Copyright (c) 2000, 2001 Gerard Lantau, GPL version 2 or later).
+ * mode selects copy (0), horizontal (1), vertical (2), or both (3).
+ * When averaging, interpolation rounding and destination rounding are separate:
+ * the destination average always rounds up, including noRounding interpolation.
+ */
+template<int width>
+inline void putHalfPixels(byte *dst, const byte *src, ptrdiff_t pitch, int height,
+                          int mode, bool noRounding, bool average = false) {
+	for (int y = 0; y < height; ++y) {
+		for (int x = 0; x < width; ++x) {
+			int value = src[x];
+			if (mode == 1)
+				value = (src[x] + src[x + 1] + !noRounding) >> 1;
+			else if (mode == 2)
+				value = (src[x] + src[x + pitch] + !noRounding) >> 1;
+			else if (mode == 3)
+				value = (src[x] + src[x + 1] + src[x + pitch] + src[x + pitch + 1] + (noRounding ? 1 : 2)) >> 2;
+			dst[x] = average ? (dst[x] + value + 1) >> 1 : value;
+		}
+		dst += pitch;
+		src += pitch;
+	}
+}
+
+} // namespace Image
+
+#endif
diff --git a/image/codecs/vc1.cpp b/image/codecs/vc1.cpp
new file mode 100644
index 00000000000..d447d7bbaea
--- /dev/null
+++ b/image/codecs/vc1.cpp
@@ -0,0 +1,15103 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program 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 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*
+ * WMV3 and VC-1 software video decoder.
+ *
+ * This decoder is a ScummVM port of the FFmpeg WMV3/VC-1 decoder path
+ * used by libavcodec revision c23123630e6a7e645c199599b8ade3fe7e9ab3db:
+ * https://git.ffmpeg.org/gitweb/ffmpeg.git/commit/c23123630e6a7e645c199599b8ade3fe7e9ab3db
+ * The original code was Copyright
+ * (c) 2005 Anonymous, Alex Beregszaszi and Michael Niedermayer,
+ * (c) 2006-2007 Konstantin Shishkov,
+ * (c) 2011 Mashiat Sarker Shakkhar,
+ * (c) 2000-2002 Fabrice Bellard,
+ * (c) 2001-2003 BERO <bero at geocities.co.jp>,
+ * (c) 2001-2012 Michael Niedermayer <michaelni at gmx.at> et al,
+ * (c) 2010 Loren Merritt,
+ * (c) 2011 Oskar Arvidsson and
+ * (c) 2012 Ronald S. Bultje and distributed under the GNU LGPL
+ * version 2.1 or later. The migrated path includes sequence and picture
+ * headers, bitplanes, VLC tables, prediction, motion compensation, inverse
+ * transforms, overlap and loop filtering, IntraX8, error concealment,
+ * reference-frame ordering, and YUV420 output.
+ */
+
+#include "image/codecs/vc1.h"
+#include "common/array.h"
+#include "common/endian.h"
+#include "common/memstream.h"
+#include "common/ptr.h"
+#include "common/rational.h"
+#include "common/stream.h"
+#include "common/textconsole.h"
+#include "common/util.h"
+#include "graphics/yuv_to_rgb.h"
+#include "image/codecs/msmpeg4_vc1.h"
+#include <limits.h>
+
+namespace Image {
+
+typedef void (*ChromaFunc)(uint8 *dst, const uint8 *src, ptrdiff_t stride, int height, int x, int y);
+
+typedef void (*vc1op_pixels_func)(uint8 *block /*align width (8 or 16)*/, const uint8 *pixels /*align 1*/,
+								  ptrdiff_t line_size, int round);
+
+typedef struct WMV3DSP {
+	/* vc1 functions */
+	void (*vc1_inv_trans_8x8)(int16 *b);
+	void (*vc1_inv_trans_8x4)(uint8 *dest, ptrdiff_t stride, int16 *block);
+	void (*vc1_inv_trans_4x8)(uint8 *dest, ptrdiff_t stride, int16 *block);
+	void (*vc1_inv_trans_4x4)(uint8 *dest, ptrdiff_t stride, int16 *block);
+	void (*vc1_inv_trans_8x8_dc)(uint8 *dest, ptrdiff_t stride, int16 *block);
+	void (*vc1_inv_trans_8x4_dc)(uint8 *dest, ptrdiff_t stride, int16 *block);
+	void (*vc1_inv_trans_4x8_dc)(uint8 *dest, ptrdiff_t stride, int16 *block);
+	void (*vc1_inv_trans_4x4_dc)(uint8 *dest, ptrdiff_t stride, int16 *block);
+	void (*vc1_v_overlap)(uint8 *src, ptrdiff_t stride);
+	void (*vc1_h_overlap)(uint8 *src, ptrdiff_t stride);
+	void (*vc1_v_s_overlap)(int16 *top, int16 *bottom);
+	void (*vc1_h_s_overlap)(int16 *left, int16 *right, ptrdiff_t left_stride, ptrdiff_t right_stride, int flags);
+	void (*vc1_v_loop_filter4)(uint8 *src, ptrdiff_t stride, int pq);
+	void (*vc1_h_loop_filter4)(uint8 *src, ptrdiff_t stride, int pq);
+	void (*vc1_v_loop_filter8)(uint8 *src, ptrdiff_t stride, int pq);
+	void (*vc1_h_loop_filter8)(uint8 *src, ptrdiff_t stride, int pq);
+	void (*vc1_v_loop_filter16)(uint8 *src, ptrdiff_t stride, int pq);
+	void (*vc1_h_loop_filter16)(uint8 *src, ptrdiff_t stride, int pq);
+
+	/* put 8x8 block with bicubic interpolation and quarterpel precision
+	 * last argument is actually round value instead of height
+	 */
+	vc1op_pixels_func put_vc1_mspel_pixels_tab[2][16];
+	vc1op_pixels_func avg_vc1_mspel_pixels_tab[2][16];
+
+	/* This is really one func used in VC-1 decoding */
+	ChromaFunc put_no_rnd_vc1_chroma_pixels_tab[3];
+	ChromaFunc avg_no_rnd_vc1_chroma_pixels_tab[3];
+
+} WMV3DSP;
+
+void initWMV3DSP(WMV3DSP *dsp);
+
+namespace VC1 {
+// Bitstream and VLC support
+
+struct Bits {
+	Common::BitStream8MSB *stream;
+	int size_in_bits;
+};
+inline unsigned get_bits(Bits *b, int n) {
+	return b->stream->getBits(n);
+}
+inline unsigned get_bits1(Bits *b) {
+	return b->stream->getBit();
+}
+inline int get_bits_count(const Bits *b) {
+	return b->stream->pos();
+}
+inline int get_bits_left(const Bits *b) {
+	return b->size_in_bits - get_bits_count(b);
+}
+inline void skip_bits(Bits *b, int n) {
+	b->stream->skip(n);
+}
+inline int get_unary(Bits *b, int stop, int max) {
+	int i = 0;
+	while (i < max && get_bits1(b) != (unsigned)stop)
+		++i;
+	return i;
+}
+
+inline int decode012(Bits *b) {
+	return get_bits1(b) ? 1 + get_bits1(b) : 0;
+}
+inline int decode210(Bits *b) {
+	return get_bits1(b) ? 0 : 2 - get_bits1(b);
+}
+struct VLC {
+	struct Node {
+		int child[2];
+		int symbol;
+		Node() : child{-1, -1}, symbol(-1) {}
+	};
+	Common::Array<Node> nodes;
+};
+const VLC *makeVLC(int count, const void *lengths, int lengthStride, int lengthSize, const void *codes, int codeStride,
+				   int codeSize);
+int get_vlc2(Bits *b, const VLC *table);
+void initTables();
+inline int av_clip(int a, int low, int high) {
+	return CLIP(a, low, high);
+}
+inline int av_clip_uint8(int a) {
+	return CLIP(a, 0, 255);
+}
+inline int av_clip_uintp2(int a, int p) {
+	return CLIP(a, 0, (1 << p) - 1);
+}
+struct Crop {
+	uint8 operator[](int x) const { return av_clip_uint8(x); }
+};
+inline int mid_pred(int a, int b, int c) {
+	if (a > b)
+		SWAP(a, b);
+	return MAX(a, MIN(b, c));
+}
+#define FFALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
+enum PictureType { AV_PICTURE_TYPE_I = 1, AV_PICTURE_TYPE_P = 2, AV_PICTURE_TYPE_B = 3, AV_PICTURE_TYPE_BI = 7 };
+
+enum Profile { PROFILE_SIMPLE = 0, PROFILE_MAIN = 1, PROFILE_ADVANCED = 3 };
+
+enum MacroblockType { MB_TYPE_INTRA = 1, MB_TYPE_16x16 = 8, MB_TYPE_SKIP = 131072 };
+
+enum ErrorStatus { ER_MB_ERROR = 14, ER_MB_END = 112 };
+
+static const int CONFIG_GRAY = 0;
+static const int AV_CODEC_FLAG_GRAY = 8192;
+static const int AVDISCARD_NONKEY = 32;
+
+// Decoder state and picture storage
+
+struct Settings {
+	int error_concealment = 3;
+	int flags;
+	int skip_loop_filter;
+	int coded_width;
+	int coded_height;
+};
+struct Planes {
+	uint8 *data[3];
+	int linesize[3];
+	int pict_type;
+	int width;
+	int height;
+	int format;
+	int decode_error_flags;
+};
+struct Picture {
+	Planes *f;
+	uint8 *data[3];
+	int linesize[3];
+	int16 (*motion_val[2])[2];
+	int8 *ref_index[2];
+	uint32 *mb_type;
+	int8 *qscale_table;
+	Picture *ptr;
+	int field_picture;
+	int interlaced;
+};
+typedef void (*PixelOp)(uint8 *, const uint8 *, ptrdiff_t, int);
+typedef void (*QpelOp)(uint8 *, const uint8 *, ptrdiff_t);
+struct QpelDSP {
+	QpelOp put_qpel_pixels_tab[2][16], put_no_rnd_qpel_pixels_tab[2][16], avg_qpel_pixels_tab[2][16];
+};
+void initQpel(QpelDSP *);
+struct HalfDSP {
+	PixelOp put_pixels_tab[2][4], put_no_rnd_pixels_tab[2][4], avg_pixels_tab[2][4], avg_no_rnd_pixels_tab[4];
+};
+struct ChromaDSP {
+	ChromaFunc put_h264_chroma_pixels_tab[3], avg_h264_chroma_pixels_tab[3];
+};
+struct BlockDSP {
+	void (*clear_block)(int16 *);
+	void (*clear_blocks)(int16 *);
+};
+struct ClampDSP {
+	void (*put_pixels_clamped)(const int16 *, uint8 *, ptrdiff_t);
+	void (*put_signed_pixels_clamped)(const int16 *, uint8 *, ptrdiff_t);
+	void (*add_pixels_clamped)(const int16 *, uint8 *, ptrdiff_t);
+};
+struct EdgeDSP {
+	void (*emulated_edge_mc)(uint8 *, const uint8 *, ptrdiff_t, ptrdiff_t, int, int, int, int, int, int);
+};
+inline int median4(int a, int b, int c, int d) {
+	if (a < b) {
+		if (c < d)
+			return (MIN(b, d) + MAX(a, c)) / 2;
+		return (MIN(b, c) + MAX(a, d)) / 2;
+	}
+	if (c < d)
+		return (MIN(a, d) + MAX(b, c)) / 2;
+	return (MIN(a, c) + MAX(b, d)) / 2;
+}
+
+typedef struct ERContext {
+	Settings *avctx;
+
+	int (*sad)(void *unused, const uint8 *blk1, const uint8 *blk2, ptrdiff_t stride, int h);
+
+	int *mb_index2xy;
+	int mb_num;
+	int mb_width, mb_height;
+	ptrdiff_t mb_stride;
+	ptrdiff_t b8_stride;
+
+	int error_count;
+	int error_occurred;
+	uint8 *error_status_table;
+	uint8 *er_temp_buffer;
+	int16 *dc_val[3];
+	uint8 *mbskip_table;
+	uint8 *mbintra_table;
+	int mv[2][4][2];
+
+	Picture cur_pic;
+	Picture last_pic;
+	Picture next_pic;
+
+	int8 *ref_index[2];
+	int16 (*motion_val_base[2])[2];
+
+	uint16 pp_time;
+	uint16 pb_time;
+	int quarter_sample;
+	int partitioned_frame;
+
+	void (*decode_mb)(void *opaque, int ref, int mv_dir, int mv_type, int (*mv)[2][4][2], int mb_x, int mb_y,
+					  int mb_intra, int mb_skipped);
+	void *opaque;
+} ERContext;
+
+void ff_er_add_slice(ERContext *, int, int, int, int, int);
+void ff_er_frame_start(ERContext *);
+void ff_er_frame_end(ERContext *, int *);
+struct PictureState;
+void initializeER(PictureState *);
+struct PictureState {
+	Settings *avctx;
+	int ac_pred;
+	int b8_stride;
+	int chroma_x_shift;
+	int end_mb_y;
+	int first_slice_line;
+	int h_edge_pos;
+	int height;
+	int width;
+	int low_delay;
+	int linesize;
+	int mb_height;
+	int mb_intra;
+	int mb_stride;
+	int mb_width;
+	int mb_x;
+	int mb_y;
+	int mspel;
+	int pict_type;
+	int quarter_sample;
+	int start_mb_y;
+	int uvlinesize;
+	int v_edge_pos;
+	int y_dc_scale;
+	int16 (*ac_val)[16];
+	int16 *dc_val;
+	uint8 *coded_block;
+	uint8 *mbskip_table;
+	int block_index[6];
+	int block_wrap[6];
+	int mv[2][4][2];
+	uint8 *dest[3];
+	Picture cur_pic;
+	Picture last_pic;
+	Picture next_pic;
+	BlockDSP bdsp;
+	ClampDSP idsp;
+	HalfDSP hdsp;
+	QpelDSP qdsp;
+	EdgeDSP vdsp;
+	struct {
+		uint8 *edge_emu_buffer;
+	} sc;
+	ERContext er;
+};
+struct IntraX8Context;
+int ff_intrax8_decode_picture(IntraX8Context *, Picture *, Bits *, int *, int *, int, int, int, int);
+void ff_init_block_index(PictureState *s);
+void ff_update_block_index(PictureState *s, int bits, int lowres, int chroma);
+#define B_FRACTION_DEN 256
+#define AC_VLC_BITS 9
+
+/** Sequence quantizer mode */
+//@{
+enum QuantMode {
+	QUANT_FRAME_IMPLICIT, ///< Implicitly specified at frame level
+	QUANT_FRAME_EXPLICIT, ///< Explicitly specified at frame level
+	QUANT_NON_UNIFORM,    ///< Non-uniform quant used for all frames
+	QUANT_UNIFORM         ///< Uniform quant used for all frames
+};
+//@}
+
+/** Where quant can be changed */
+//@{
+enum DQProfile { DQPROFILE_FOUR_EDGES, DQPROFILE_DOUBLE_EDGES, DQPROFILE_SINGLE_EDGE, DQPROFILE_ALL_MBS };
+//@}
+
+/** @name Where quant can be changed
+ */
+//@{
+enum DQSingleEdge { DQSINGLE_BEDGE_LEFT, DQSINGLE_BEDGE_TOP, DQSINGLE_BEDGE_RIGHT, DQSINGLE_BEDGE_BOTTOM };
+//@}
+
+/** Which pair of edges is quantized with ALTPQUANT */
+//@{
+enum DQDoubleEdge {
+	DQDOUBLE_BEDGE_TOPLEFT,
+	DQDOUBLE_BEDGE_TOPRIGHT,
+	DQDOUBLE_BEDGE_BOTTOMRIGHT,
+	DQDOUBLE_BEDGE_BOTTOMLEFT
+};
+//@}
+
+/** MV modes for P-frames */
+//@{
+enum MVModes { MV_PMODE_1MV_HPEL_BILIN, MV_PMODE_1MV, MV_PMODE_1MV_HPEL, MV_PMODE_MIXED_MV, MV_PMODE_INTENSITY_COMP };
+//@}
+
+/** MBMODE for interlaced frame P-picture */
+//@{
+enum MBModesIntfr {
+	MV_PMODE_INTFR_1MV,
+	MV_PMODE_INTFR_2MV_FIELD,
+	MV_PMODE_INTFR_2MV,
+	MV_PMODE_INTFR_4MV_FIELD,
+	MV_PMODE_INTFR_4MV,
+	MV_PMODE_INTFR_INTRA,
+};
+//@}
+
+/** @name MV types for B-frames */
+//@{
+enum BMVTypes { BMV_TYPE_BACKWARD, BMV_TYPE_FORWARD, BMV_TYPE_INTERPOLATED, BMV_TYPE_DIRECT };
+//@}
+
+/** @name Block types for P/B-frames */
+//@{
+enum TransformTypes {
+	TT_8X8,
+	TT_8X4_BOTTOM,
+	TT_8X4_TOP,
+	TT_8X4, // both halves
+	TT_4X8_RIGHT,
+	TT_4X8_LEFT,
+	TT_4X8, // both halves
+	TT_4X4
+};
+//@}
+
+enum CodingSet {
+	CS_HIGH_MOT_INTRA = 0,
+	CS_HIGH_MOT_INTER,
+	CS_LOW_MOT_INTRA,
+	CS_LOW_MOT_INTER,
+	CS_MID_RATE_INTRA,
+	CS_MID_RATE_INTER,
+	CS_HIGH_RATE_INTRA,
+	CS_HIGH_RATE_INTER
+};
+
+/** @name Overlap conditions for Advanced Profile */
+//@{
+enum COTypes { CONDOVER_NONE = 0, CONDOVER_ALL, CONDOVER_SELECT };
+//@}
+
+/**
+ * FCM Frame Coding Mode
+ * @note some content might be marked interlaced
+ * but have fcm set to 0 as well (e.g. HD-DVD)
+ */
+enum FrameCodingMode {
+	PROGRESSIVE = 0, ///<  in the bitstream is reported as 00b
+	ILACE_FRAME,     ///<  in the bitstream is reported as 10b
+	ILACE_FIELD      ///<  in the bitstream is reported as 11b
+};
+
+/**
+ * Imode types
+ * @{
+ */
+enum Imode { IMODE_RAW, IMODE_NORM2, IMODE_DIFF2, IMODE_NORM6, IMODE_DIFF6, IMODE_ROWSKIP, IMODE_COLSKIP };
+/** @} */ // imode defines
+
+/** The VC1 Context
+ * @todo Change size wherever another size is more efficient
+ * Many members are only used for Advanced Profile
+ */
+// VC-1 picture context
+
+struct VC1Context : VC1Header {
+	PictureState s;
+	Bits gb;
+	IntraX8Context *x8;
+	ChromaDSP h264chroma;
+	WMV3DSP vc1dsp;
+
+	/** Simple/Main Profile sequence header */
+	//@{
+	///< at frame level
+	int reserved; ///< reserved
+	//@}
+
+	/** Advanced Profile */
+	//@{
+	///< Decoder parameters
+	//@}
+
+	/** Sequence header data for all Profiles
+	 * TODO: choose between ints, uint8_ts and monobit flags
+	 */
+	//@{
+	//@}
+
+	/** Frame decoding info for all profiles */
+	//@{
+	uint8 mv_mode;               ///< MV coding mode
+	uint8 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
+	uint8 pq, altpq;             ///< Current/alternate frame quantizer scale
+	uint8 zz_8x8[4][64];         ///< Zigzag table for TT_8x8, permuted for IDCT
+	int left_blk_sh, top_blk_sh; ///< Either 3 or 0, positions of l/t in blk[]
+	/** pquant parameters */
+	//@{
+	uint8 dquantfrm;
+	uint8 dqprofile;
+	uint8 dqsbedge;
+	uint8 dqbilevel;
+	//@}
+	int dc_table_index;
+	/** AC coding set indexes
+	 * @see 8.1.1.10, p(1)10
+	 */
+	//@{
+	int c_ac_table_index; ///< Chroma index from ACFRM element
+	int y_ac_table_index; ///< Luma index from AC2FRM element
+	//@}
+	int esc3_level_length;
+	int esc3_run_length;
+	int ttfrm;               ///< Transform type info present at frame level
+	uint8 ttmbf;             ///< Transform type flag
+	int *ttblk_base, *ttblk; ///< Transform type at the block level
+	int codingset;           ///< index of current table set from 11.8 to use for luma block decoding
+	int codingset2;          ///< index of current table set from 11.8 to use for chroma block decoding
+	int pqindex;             ///< raw pqindex used in coding set selection
+	int a_avail, c_avail;
+	uint8 *mb_type_base, *mb_type;
+
+	/** Luma compensation parameters */
+	//@{
+	uint8 lumscale;
+	uint8 lumshift;
+	//@}
+	int16 bfraction;     ///< Relative position % anchors=> how to scale MVs
+	uint8 halfpq;        ///< Uniform quant over image and qp+.5
+	uint8 respic;        ///< Frame-level flag for resized images
+	int buffer_fullness; ///< HRD info
+	/** Ranges:
+	 * -# 0 -> [-64n 63.f] x [-32, 31.f]
+	 * -# 1 -> [-128, 127.f] x [-64, 63.f]
+	 * -# 2 -> [-512, 511.f] x [-128, 127.f]
+	 * -# 3 -> [-1024, 1023.f] x [-256, 255.f]
+	 */
+	uint8 mvrange;        ///< Extended MV range flag
+	uint8 pquantizer;     ///< Uniform (over sequence) quantizer in use
+	const VLC *cbpcy_vlc; ///< CBPCY VLC table
+	int tt_index;         ///< Index for Transform Type tables (to decode TTMB)
+	int mv_table_index;
+	uint8 *mv_type_mb_plane;                     ///< bitplane for mv_type == (4MV)
+	uint8 *direct_mb_plane;                      ///< bitplane for "direct" MBs
+	uint8 *forward_mb_plane;                     ///< bitplane for "forward" MBs
+	int mv_type_is_raw;                          ///< mv type mb plane is not coded
+	int dmb_is_raw;                              ///< direct mb plane is raw
+	int fmb_is_raw;                              ///< forward mb plane is raw
+	int skip_is_raw;                             ///< skip mb plane is not coded
+	uint8 last_luty[2][256], last_lutuv[2][256]; ///< lookup tables used for intensity compensation
+	uint8 aux_luty[2][256], aux_lutuv[2][256];   ///< lookup tables used for intensity compensation
+	uint8 next_luty[2][256], next_lutuv[2][256]; ///< lookup tables used for intensity compensation
+	uint8 (*curr_luty)[256], (*curr_lutuv)[256];
+	int last_use_ic, *curr_use_ic, next_use_ic, aux_use_ic;
+	int last_interlaced, next_interlaced; ///< whether last_pic, next_pic is interlaced
+	int rnd;                              ///< rounding control
+	int cbptab;
+
+	/** Frame decoding info for S/M profiles only */
+	//@{
+	uint8 rangeredfrm; ///< out_sample = CLIP((in_sample-128)*2+128)
+	uint8 interpfrm;
+	//@}
+
+	/** Frame decoding info for Advanced profile */
+	//@{
+	int fcm;
+	uint8 numpanscanwin;
+	uint8 tfcntr;
+	uint8 rptfrm, tff, rff;
+	uint8 uvsamp;
+	uint8 postproc;
+	uint8 bit_rate_exponent;
+	uint8 buffer_size_exponent;
+	uint8 *acpred_plane; ///< AC prediction flags bitplane
+	int acpred_is_raw;
+	uint8 *over_flags_plane; ///< Overflags bitplane
+	int overflg_is_raw;
+	uint8 condover;
+	//@}
+
+	/** Frame decoding info for interlaced picture */
+	uint8 dmvrange; ///< Extended differential MV range flag
+	int fourmvswitch;
+	int intcomp;
+	uint8 lumscale2; ///< for interlaced field P picture
+	uint8 lumshift2;
+	const VLC *mbmode_vlc;
+	const VLC *imv_vlc;
+	const VLC *twomvbp_vlc;
+	const VLC *fourmvbp_vlc;
+	uint8 twomvbp;
+	uint8 fourmvbp;
+	uint8 *fieldtx_plane;
+	int fieldtx_is_raw;
+	uint8 zzi_8x8[64];
+	uint8 *blk_mv_type_base, *blk_mv_type; ///< 0: frame MV, 1: field MV (interlaced frame)
+	uint8 *mv_f_base, *mv_f[2];            ///< 0: MV obtained from same field, 1: opposite field
+	uint8 *mv_f_next_base, *mv_f_next[2];
+	int field_mode; ///< 1 for interlaced field pictures
+	int fptype;
+	int second_field;
+	int refdist;           ///< distance of the current picture from reference
+	int numref;            ///< number of past field pictures used as reference
+						   // 0 corresponds to 1 and 1 corresponds to 2 references
+	int reffield;          ///< if numref = 0 (1 reference) then reffield decides which
+						   // field to use among the two fields from previous frame
+	int intcompfield;      ///< which of the two fields to be intensity compensated
+						   // 0: both fields, 1: bottom field, 2: top field
+	int cur_field_type;    ///< 0: top, 1: bottom
+	int ref_field_type[2]; ///< forward and backward reference field type (top or bottom)
+	int blocks_off, mb_off;
+	int bmvtype;
+	int frfd, brfd; ///< reference frame distance (forward or backward)
+	int first_pic_header_flag;
+	int pic_header_flag;
+	int mbmodetab;
+	int icbptab;
+	int imvtab;
+	int twomvbptab;
+	int fourmvbptab;
+
+	int new_sprite, two_sprites;
+	int p_frame_skipped;
+	int bi_type;
+	int x8_type;
+
+	int16 (*block)[6][64];
+	int n_allocated_blks, cur_blk_idx, left_blk_idx, topleft_blk_idx, top_blk_idx;
+	uint32 *cbp_base, *cbp;
+	uint8 *is_intra_base, *is_intra;
+	int16 (*luma_mv_base)[2], (*luma_mv)[2];
+	uint8 bfraction_lut_index; ///< Index for BFRACTION value (see Table 40, reproduced into ff_vc1_bfraction_lut[])
+
+	int end_mb_x; ///< Horizontal macroblock limit (used only by mss2)
+
+	int parse_only; ///< Context is used within parser
+
+	int16 blocks[6][64];
+};
+
+void ff_vc1_decode_blocks(VC1Context *v);
+
+void ff_vc1_i_overlap_filter(VC1Context *v);
+void ff_vc1_p_overlap_filter(VC1Context *v);
+void ff_vc1_i_loop_filter(VC1Context *v);
+void ff_vc1_p_loop_filter(VC1Context *v);
+void ff_vc1_p_intfr_loop_filter(VC1Context *v);
+void ff_vc1_b_intfi_loop_filter(VC1Context *v);
+
+void ff_vc1_mc_1mv(VC1Context *v, int dir);
+void ff_vc1_mc_4mv_luma(VC1Context *v, int n, int dir, int avg);
+void ff_vc1_mc_4mv_chroma(VC1Context *v, int dir);
+void ff_vc1_mc_4mv_chroma4(VC1Context *v, int dir, int dir2, int avg);
+
+void ff_vc1_interp_mc(VC1Context *v);
+
+void ff_vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y, int mv1, int r_x, int r_y, uint8 *is_intra,
+					int pred_flag, int dir);
+void ff_vc1_pred_mv_intfr(VC1Context *v, int n, int dmv_x, int dmv_y, int mvn, int r_x, int r_y, int dir);
+void ff_vc1_pred_b_mv(VC1Context *v, int dmv_x[2], int dmv_y[2], int direct, int mvtype);
+void ff_vc1_pred_b_mv_intfi(VC1Context *v, int n, int *dmv_x, int *dmv_y, int mv1, int *pred_flag);
+
+static inline int scale_mv(int value, int bfrac, int inv, int qs) {
+	int n = bfrac;
+
+#if B_FRACTION_DEN == 256
+	if (inv)
+		n -= 256;
+	if (!qs)
+		return 2 * ((value * n + 255) >> 9);
+	return (value * n + 128) >> 8;
+#else
+	if (inv)
+		n -= B_FRACTION_DEN;
+	if (!qs)
+		return 2 * ((value * n + B_FRACTION_DEN - 1) / (2 * B_FRACTION_DEN));
+	return (value * n + B_FRACTION_DEN / 2) / B_FRACTION_DEN;
+#endif
+}
+
+int ff_vc1_parse_frame_header(VC1Context *, Bits *);
+int ff_vc1_parse_frame_header_adv(VC1Context *, Bits *);
+void ff_simple_idct_int16_8bit(int16 *);
+void ff_simple_idct_add_int16_8bit(uint8 *, ptrdiff_t, int16 *);
+void ff_simple_idct84_add(uint8 *, ptrdiff_t, int16 *);
+void ff_simple_idct48_add(uint8 *, ptrdiff_t, int16 *);
+void ff_simple_idct44_add(uint8 *, ptrdiff_t, int16 *);
+void initSupport(PictureState *, ChromaDSP *);
+
+/** Table for conversion between TTBLK and TTMB */
+extern const int ff_vc1_ttblk_to_tt[3][8];
+
+extern const int ff_vc1_ttfrm_to_tt[4];
+
+/** MV P mode - the 5th element is only used for mode 1 */
+extern const uint8 ff_vc1_mv_pmode_table[2][5];
+extern const uint8 ff_vc1_mv_pmode_table2[2][4];
+
+extern const int ff_vc1_fps_nr[7], ff_vc1_fps_dr[2];
+extern const uint8 ff_vc1_pquant_table[3][32];
+
+/* MBMODE table for interlaced frame P-picture */
+extern const uint8 ff_vc1_mbmode_intfrp[2][15][4];
+
+/** @name VC-1 VLC tables
+ *  @todo TODO move this into the context
+ */
+//@{
+extern const VLC *ff_vc1_imode_vlc;
+extern const VLC *ff_vc1_norm2_vlc;
+extern const VLC *ff_vc1_norm6_vlc;
+extern const VLC *ff_vc1_ttmb_vlc[3];
+extern const VLC *ff_vc1_mv_diff_vlc[4];
+extern const VLC *ff_vc1_cbpcy_p_vlc[4];
+extern const VLC *ff_vc1_icbpcy_vlc[8];
+extern const VLC *ff_vc1_4mv_block_pattern_vlc[4];
+extern const VLC *ff_vc1_2mv_block_pattern_vlc[4];
+extern const VLC *ff_vc1_ttblk_vlc[3];
+extern const VLC *ff_vc1_subblkpat_vlc[3];
+extern const VLC *ff_vc1_intfr_4mv_mbmode_vlc[4];
+extern const VLC *ff_vc1_intfr_non4mv_mbmode_vlc[4];
+extern const VLC *ff_vc1_if_mmv_mbmode_vlc[8];
+extern const VLC *ff_vc1_if_1mv_mbmode_vlc[8];
+extern const VLC *ff_vc1_1ref_mvdata_vlc[4];
+extern const VLC *ff_vc1_2ref_mvdata_vlc[8];
+
+extern const VLC *ff_vc1_ac_coeff_table[8];
+
+//@}
+
+/* pre-computed scales for all bfractions and base=256 */
+extern const int16 ff_vc1_bfraction_lut[23];
+
+// Same as H.264
+extern const VC1Ratio ff_vc1_pixel_aspect[16];
+
+extern const uint8 ff_wmv3_dc_scale_table[32];
+
+/* DC differentials low+hi-mo, p217 are the same as in msmpeg4data .h */
+
+/* Scantables/ZZ scan are at 11.9 (p262) and 8.1.1.12 (p10) */
+extern const uint8 ff_vc1_simple_progressive_4x4_zz[16];
+extern const uint8 ff_vc1_adv_progressive_8x4_zz[32];
+extern const uint8 ff_vc1_adv_progressive_4x8_zz[32];
+extern const uint8 ff_vc1_adv_interlaced_8x8_zz[64];
+extern const uint8 ff_vc1_adv_interlaced_8x4_zz[32];
+extern const uint8 ff_vc1_adv_interlaced_4x8_zz[32];
+extern const uint8 ff_vc1_adv_interlaced_4x4_zz[16];
+
+/* DQScale as specified in 8.1.3.9 - almost identical to 0x40000/i */
+extern const int32 ff_vc1_dqscale[63];
+
+/* P Interlaced field picture MV predictor scaling values (Table 114) */
+extern const uint16 ff_vc1_field_mvpred_scales[2][7][4];
+/* B Interlaced field picture backward MV predictor scaling values for first field (Table 115) */
+extern const uint16 ff_vc1_b_field_mvpred_scales[7][4];
+
+#define AC_MODES 8
+
+extern const int ff_vc1_ac_sizes[AC_MODES];
+extern const VLC *ff_msmp4_mb_i_vlc;
+extern const VLC *ff_msmp4_dc_vlc[2 /* dc_table_index */][2 /* 0: luma, 1: chroma */];
+
+/* intra picture macroblock coded block pattern */
+using MSMPEG4VC1::ff_msmp4_mb_i_table;
+
+#define WMV1_SCANTABLE_COUNT 4
+
+extern const uint8 ff_wmv1_scantable[WMV1_SCANTABLE_COUNT][64];
+
+using MSMPEG4VC1::ff_msmp4_dc_tables;
+
+struct X8IDCT {
+	void (*idct_add)(uint8 *, ptrdiff_t, int16 *);
+};
+typedef struct IntraX8DSPContext {
+	void (*v_loop_filter)(uint8 *src, ptrdiff_t stride, int qscale);
+	void (*h_loop_filter)(uint8 *src, ptrdiff_t stride, int qscale);
+
+	void (*spatial_compensation[12])(const uint8 *src, uint8 *dst, ptrdiff_t stride);
+	void (*setup_spatial_compensation)(const uint8 *src, uint8 *dst, ptrdiff_t stride, int *range, int *sum, int edges);
+} IntraX8DSPContext;
+
+void ff_intrax8dsp_init(IntraX8DSPContext *dsp);
+
+typedef struct IntraX8Context {
+	const VLC *j_ac_vlc_table[4]; // they point to the static j_mb_vlc.table
+	const VLC *j_orient_vlc_table;
+	const VLC *j_dc_vlc_table[3];
+
+	int use_quant_matrix;
+
+	// set by ff_intrax8_common_init
+	uint8 *prediction_table; // 2 * (mb_w * 2)
+	uint8 permutated_scantable[3][64];
+	X8IDCT idsp;
+	Settings *avctx;
+	int16 *block;
+
+	// set by the caller codec
+	IntraX8DSPContext dsp;
+	BlockDSP bdsp;
+	int quant;
+	int dquant;
+	int qsum;
+	int loopfilter;
+	Planes *frame;
+	Bits *gb;
+
+	// calculated per frame
+	int quant_dc_chroma;
+	int divide_quant_dc_luma;
+	int divide_quant_dc_chroma;
+	uint8 *dest[3];
+	uint8 scratchpad[42]; // size of the block is fixed (8x8 plus padding)
+
+	// changed per block
+	int edges;
+	int flat_dc;
+	int predicted_dc;
+	int raw_orient;
+	int chroma_orient;
+	int orient;
+	int est_run;
+
+	// block props
+	int mb_x, mb_y;
+	int mb_width, mb_height;
+} IntraX8Context;
+
+int initX8(IntraX8Context *, int16 *, int, int);
+void endX8(IntraX8Context *);
+
+// Packet decoder lifecycle
+
+class Decoder {
+public:
+	Decoder(int width, int height, bool advanced);
+	~Decoder();
+	bool initialize(const uint8 *data, uint32 size);
+	const Picture *decode(const uint8 *data, uint32 size);
+	const Picture *drain();
+	bool failed() const { return _failed; }
+	int width() const { return _v->width; }
+	int height() const { return _v->height; }
+
+private:
+	VC1Context *_v;
+	Settings _settings;
+	Common::Array<uint8 *> _allocations;
+	Picture _pictures[3];
+	Planes _planes[3];
+	bool _advanced, _ready, _failed, _pending;
+	template<class T> T *allocate(uint32 n) {
+		uint8 *p = new uint8[sizeof(T) * n]();
+		_allocations.push_back(p);
+		return reinterpret_cast<T *>(p);
+	}
+	void allocatePictures();
+	void initializePictureLayout();
+	void allocatePredictors();
+	void allocateReferencePictures();
+	void initializeConcealment();
+	void initializeTransforms();
+
+	void clearPictures();
+	bool readHeader(const uint8 *, uint32, bool);
+	bool decodePacket(const uint8 *, uint32, const Picture *&);
+};
+
+/* which indexes point to last=1 entries in tables */
+static const int vc1_last_decode_table[AC_MODES] = {119, 99, 85, 81, 67, 58, 126, 109};
+
+static const uint8 vc1_index_decode_table[AC_MODES][185][2] = {
+	{{0, 1},  {0, 2},  {0, 3},  {0, 4},  {0, 5},  {0, 6},  {0, 7},  {0, 8},  {0, 9},  {0, 10}, {0, 11}, {0, 12},
+	 {0, 13}, {0, 14}, {0, 15}, {0, 16}, {0, 17}, {0, 18}, {0, 19}, {1, 1},  {1, 2},  {1, 3},  {1, 4},  {1, 5},
+	 {1, 6},  {1, 7},  {1, 8},  {1, 9},  {1, 10}, {1, 11}, {1, 12}, {1, 13}, {1, 14}, {1, 15}, {2, 1},  {2, 2},
+	 {2, 3},  {2, 4},  {2, 5},  {2, 6},  {2, 7},  {2, 8},  {2, 9},  {2, 10}, {2, 11}, {2, 12}, {3, 1},  {3, 2},
+	 {3, 3},  {3, 4},  {3, 5},  {3, 6},  {3, 7},  {3, 8},  {3, 9},  {3, 10}, {3, 11}, {4, 1},  {4, 2},  {4, 3},
+	 {4, 4},  {4, 5},  {4, 6},  {5, 1},  {5, 2},  {5, 3},  {5, 4},  {5, 5},  {6, 1},  {6, 2},  {6, 3},  {6, 4},
+	 {7, 1},  {7, 2},  {7, 3},  {7, 4},  {8, 1},  {8, 2},  {8, 3},  {8, 4},  {9, 1},  {9, 2},  {9, 3},  {9, 4},
+	 {10, 1}, {10, 2}, {10, 3}, {11, 1}, {11, 2}, {11, 3}, {12, 1}, {12, 2}, {12, 3}, {13, 1}, {13, 2}, {13, 3},
+	 {14, 1}, {14, 2}, {14, 3}, {15, 1}, {15, 2}, {15, 3}, {16, 1}, {16, 2}, {17, 1}, {17, 2}, {18, 1}, {19, 1},
+	 {20, 1}, {21, 1}, {22, 1}, {23, 1}, {24, 1}, {25, 1}, {26, 1}, {27, 1}, {28, 1}, {29, 1}, {30, 1}, {0, 1},
+	 {0, 2},  {0, 3},  {0, 4},  {0, 5},  {0, 6},  {1, 1},  {1, 2},  {1, 3},  {1, 4},  {1, 5},  {2, 1},  {2, 2},
+	 {2, 3},  {2, 4},  {3, 1},  {3, 2},  {3, 3},  {3, 4},  {4, 1},  {4, 2},  {4, 3},  {5, 1},  {5, 2},  {6, 1},
+	 {6, 2},  {7, 1},  {7, 2},  {8, 1},  {8, 2},  {9, 1},  {9, 2},  {10, 1}, {10, 2}, {11, 1}, {11, 2}, {12, 1},
+	 {12, 2}, {13, 1}, {13, 2}, {14, 1}, {14, 2}, {15, 1}, {15, 2}, {16, 1}, {17, 1}, {18, 1}, {19, 1}, {20, 1},
+	 {21, 1}, {22, 1}, {23, 1}, {24, 1}, {25, 1}, {26, 1}, {27, 1}, {28, 1}, {29, 1}, {30, 1}, {31, 1}, {32, 1},
+	 {33, 1}, {34, 1}, {35, 1}, {36, 1}, {37, 1}},
+	{{0, 1},  {0, 2},  {0, 3},  {0, 4},  {0, 5},  {0, 6},  {0, 7},  {0, 8},  {0, 9},  {0, 10}, {0, 11}, {0, 12},
+	 {0, 13}, {0, 14}, {0, 15}, {0, 16}, {0, 17}, {0, 18}, {0, 19}, {0, 20}, {0, 21}, {0, 22}, {0, 23}, {1, 1},
+	 {1, 2},  {1, 3},  {1, 4},  {1, 5},  {1, 6},  {1, 7},  {1, 8},  {1, 9},  {1, 10}, {1, 11}, {2, 1},  {2, 2},
+	 {2, 3},  {2, 4},  {2, 5},  {2, 6},  {2, 7},  {2, 8},  {3, 1},  {3, 2},  {3, 3},  {3, 4},  {3, 5},  {3, 6},
+	 {3, 7},  {4, 1},  {4, 2},  {4, 3},  {4, 4},  {4, 5},  {5, 1},  {5, 2},  {5, 3},  {5, 4},  {5, 5},  {6, 1},
+	 {6, 2},  {6, 3},  {6, 4},  {7, 1},  {7, 2},  {7, 3},  {7, 4},  {8, 1},  {8, 2},  {8, 3},  {9, 1},  {9, 2},
+	 {9, 3},  {10, 1}, {10, 2}, {10, 3}, {11, 1}, {11, 2}, {11, 3}, {12, 1}, {12, 2}, {13, 1}, {13, 2}, {14, 1},
+	 {14, 2}, {15, 1}, {15, 2}, {16, 1}, {16, 2}, {17, 1}, {18, 1}, {19, 1}, {20, 1}, {21, 1}, {22, 1}, {23, 1},
+	 {24, 1}, {25, 1}, {26, 1}, {0, 1},  {0, 2},  {0, 3},  {0, 4},  {0, 5},  {0, 6},  {0, 7},  {0, 8},  {0, 9},
+	 {1, 1},  {1, 2},  {1, 3},  {1, 4},  {1, 5},  {2, 1},  {2, 2},  {2, 3},  {2, 4},  {3, 1},  {3, 2},  {3, 3},
+	 {3, 4},  {4, 1},  {4, 2},  {4, 3},  {5, 1},  {5, 2},  {5, 3},  {6, 1},  {6, 2},  {6, 3},  {7, 1},  {7, 2},
+	 {8, 1},  {8, 2},  {9, 1},  {9, 2},  {10, 1}, {10, 2}, {11, 1}, {11, 2}, {12, 1}, {12, 2}, {13, 1}, {13, 2},
+	 {14, 1}, {14, 2}, {15, 1}, {16, 1}, {17, 1}, {18, 1}, {19, 1}, {20, 1}, {21, 1}, {22, 1}, {23, 1}, {24, 1},
+	 {25, 1}, {26, 1}, {27, 1}, {28, 1}, {29, 1}, {30, 1}, {31, 1}, {32, 1}, {33, 1}, {34, 1}, {35, 1}, {36, 1}},
+	{{0, 1},  {0, 2},  {0, 3},  {0, 4},  {0, 5},  {0, 6},  {0, 7},  {0, 8},  {0, 9},  {0, 10}, {0, 11}, {0, 12},
+	 {0, 13}, {0, 14}, {0, 15}, {0, 16}, {1, 1},  {1, 2},  {1, 3},  {1, 4},  {1, 5},  {1, 6},  {1, 7},  {1, 8},
+	 {1, 9},  {1, 10}, {1, 11}, {2, 1},  {2, 2},  {2, 3},  {2, 4},  {2, 5},  {2, 6},  {2, 7},  {2, 8},  {3, 1},
+	 {3, 2},  {3, 3},  {3, 4},  {3, 5},  {3, 6},  {3, 7},  {4, 1},  {4, 2},  {4, 3},  {4, 4},  {4, 5},  {5, 1},
+	 {5, 2},  {5, 3},  {5, 4},  {6, 1},  {6, 2},  {6, 3},  {6, 4},  {7, 1},  {7, 2},  {7, 3},  {8, 1},  {8, 2},
+	 {8, 3},  {9, 1},  {9, 2},  {9, 3},  {10, 1}, {10, 2}, {10, 3}, {11, 1}, {11, 2}, {11, 3}, {12, 1}, {12, 2},
+	 {12, 3}, {13, 1}, {13, 2}, {13, 3}, {14, 1}, {14, 2}, {15, 1}, {15, 2}, {16, 1}, {17, 1}, {18, 1}, {19, 1},
+	 {20, 1}, {0, 1},  {0, 2},  {0, 3},  {0, 4},  {1, 1},  {1, 2},  {1, 3},  {1, 4},  {2, 1},  {2, 2},  {2, 3},
+	 {3, 1},  {3, 2},  {3, 3},  {4, 1},  {4, 2},  {5, 1},  {5, 2},  {6, 1},  {6, 2},  {7, 1},  {7, 2},  {8, 1},
+	 {8, 2},  {9, 1},  {9, 2},  {10, 1}, {10, 2}, {11, 1}, {11, 2}, {12, 1}, {12, 2}, {13, 1}, {13, 2}, {14, 1},
+	 {15, 1}, {16, 1}, {17, 1}, {18, 1}, {19, 1}, {20, 1}, {21, 1}, {22, 1}, {23, 1}, {24, 1}, {25, 1}, {26, 1}},
+	{{0, 1},  {0, 2},  {0, 3},  {0, 4},  {0, 5},  {0, 6},  {0, 7},  {0, 8},  {0, 9},  {0, 10}, {0, 11}, {0, 12},
+	 {0, 13}, {0, 14}, {1, 1},  {1, 2},  {1, 3},  {1, 4},  {1, 5},  {1, 6},  {1, 7},  {1, 8},  {1, 9},  {2, 1},
+	 {2, 2},  {2, 3},  {2, 4},  {2, 5},  {3, 1},  {3, 2},  {3, 3},  {3, 4},  {4, 1},  {4, 2},  {4, 3},  {4, 4},
+	 {5, 1},  {5, 2},  {5, 3},  {5, 4},  {6, 1},  {6, 2},  {6, 3},  {7, 1},  {7, 2},  {7, 3},  {8, 1},  {8, 2},
+	 {8, 3},  {9, 1},  {9, 2},  {9, 3},  {10, 1}, {10, 2}, {10, 3}, {11, 1}, {11, 2}, {11, 3}, {12, 1}, {12, 2},
+	 {12, 3}, {13, 1}, {13, 2}, {14, 1}, {14, 2}, {15, 1}, {15, 2}, {16, 1}, {17, 1}, {18, 1}, {19, 1}, {20, 1},
+	 {21, 1}, {22, 1}, {23, 1}, {24, 1}, {25, 1}, {26, 1}, {27, 1}, {28, 1}, {29, 1}, {0, 1},  {0, 2},  {0, 3},
+	 {0, 4},  {0, 5},  {1, 1},  {1, 2},  {1, 3},  {1, 4},  {2, 1},  {2, 2},  {2, 3},  {3, 1},  {3, 2},  {3, 3},
+	 {4, 1},  {4, 2},  {5, 1},  {5, 2},  {6, 1},  {6, 2},  {7, 1},  {7, 2},  {8, 1},  {8, 2},  {9, 1},  {9, 2},
+	 {10, 1}, {10, 2}, {11, 1}, {11, 2}, {12, 1}, {12, 2}, {13, 1}, {13, 2}, {14, 1}, {14, 2}, {15, 1}, {15, 2},
+	 {16, 1}, {17, 1}, {18, 1}, {19, 1}, {20, 1}, {21, 1}, {22, 1}, {23, 1}, {24, 1}, {25, 1}, {26, 1}, {27, 1},
+	 {28, 1}, {29, 1}, {30, 1}, {31, 1}, {32, 1}, {33, 1}, {34, 1}, {35, 1}, {36, 1}, {37, 1}, {38, 1}, {39, 1},
+	 {40, 1}, {41, 1}, {42, 1}, {43, 1}},
+	{{0, 1},  {0, 2},  {0, 3},  {0, 4},  {0, 5},  {0, 6},  {0, 7},  {0, 8},  {0, 9},  {0, 10}, {0, 11}, {0, 12},
+	 {0, 13}, {0, 14}, {0, 15}, {0, 16}, {0, 17}, {0, 18}, {0, 19}, {0, 20}, {0, 21}, {0, 22}, {0, 23}, {0, 24},
+	 {0, 25}, {0, 26}, {0, 27}, {1, 1},  {1, 2},  {1, 3},  {1, 4},  {1, 5},  {1, 6},  {1, 7},  {1, 8},  {1, 9},
+	 {1, 10}, {2, 1},  {2, 2},  {2, 3},  {2, 4},  {2, 5},  {3, 1},  {3, 2},  {3, 3},  {3, 4},  {4, 1},  {4, 2},
+	 {4, 3},  {5, 1},  {5, 2},  {5, 3},  {6, 1},  {6, 2},  {6, 3},  {7, 1},  {7, 2},  {7, 3},  {8, 1},  {8, 2},
+	 {9, 1},  {9, 2},  {10, 1}, {11, 1}, {12, 1}, {13, 1}, {14, 1}, {0, 1},  {0, 2},  {0, 3},  {0, 4},  {0, 5},
+	 {0, 6},  {0, 7},  {0, 8},  {1, 1},  {1, 2},  {1, 3},  {2, 1},  {2, 2},  {3, 1},  {3, 2},  {4, 1},  {4, 2},
+	 {5, 1},  {5, 2},  {6, 1},  {6, 2},  {7, 1},  {8, 1},  {9, 1},  {10, 1}, {11, 1}, {12, 1}, {13, 1}, {14, 1},
+	 {15, 1}, {16, 1}, {17, 1}, {18, 1}, {19, 1}, {20, 1}},
+	{{0, 1},  {0, 2},  {0, 3},  {0, 4},  {0, 5},  {0, 6},  {0, 7},  {0, 8},  {0, 9},  {0, 10}, {0, 11}, {0, 12},
+	 {1, 1},  {1, 2},  {1, 3},  {1, 4},  {1, 5},  {1, 6},  {2, 1},  {2, 2},  {2, 3},  {2, 4},  {3, 1},  {3, 2},
+	 {3, 3},  {4, 1},  {4, 2},  {4, 3},  {5, 1},  {5, 2},  {5, 3},  {6, 1},  {6, 2},  {6, 3},  {7, 1},  {7, 2},
+	 {8, 1},  {8, 2},  {9, 1},  {9, 2},  {10, 1}, {10, 2}, {11, 1}, {12, 1}, {13, 1}, {14, 1}, {15, 1}, {16, 1},
+	 {17, 1}, {18, 1}, {19, 1}, {20, 1}, {21, 1}, {22, 1}, {23, 1}, {24, 1}, {25, 1}, {26, 1}, {0, 1},  {0, 2},
+	 {0, 3},  {1, 1},  {1, 2},  {2, 1},  {3, 1},  {4, 1},  {5, 1},  {6, 1},  {7, 1},  {8, 1},  {9, 1},  {10, 1},
+	 {11, 1}, {12, 1}, {13, 1}, {14, 1}, {15, 1}, {16, 1}, {17, 1}, {18, 1}, {19, 1}, {20, 1}, {21, 1}, {22, 1},
+	 {23, 1}, {24, 1}, {25, 1}, {26, 1}, {27, 1}, {28, 1}, {29, 1}, {30, 1}, {31, 1}, {32, 1}, {33, 1}, {34, 1},
+	 {35, 1}, {36, 1}, {37, 1}, {38, 1}, {39, 1}, {40, 1}},
+	{{0, 1},  {0, 2},  {0, 3},  {0, 4},  {0, 5},  {0, 6},  {0, 7},  {0, 8},  {0, 9},  {0, 10}, {0, 11}, {0, 12},
+	 {0, 13}, {0, 14}, {0, 15}, {0, 16}, {0, 17}, {0, 18}, {0, 19}, {0, 20}, {0, 21}, {0, 22}, {0, 23}, {0, 24},
+	 {0, 25}, {0, 26}, {0, 27}, {0, 28}, {0, 29}, {0, 30}, {0, 31}, {0, 32}, {0, 33}, {0, 34}, {0, 35}, {0, 36},
+	 {0, 37}, {0, 38}, {0, 39}, {0, 40}, {0, 41}, {0, 42}, {0, 43}, {0, 44}, {0, 45}, {0, 46}, {0, 47}, {0, 48},
+	 {0, 49}, {0, 50}, {0, 51}, {0, 52}, {0, 53}, {0, 54}, {0, 55}, {0, 56}, {1, 1},  {1, 2},  {1, 3},  {1, 4},
+	 {1, 5},  {1, 6},  {1, 7},  {1, 8},  {1, 9},  {1, 10}, {1, 11}, {1, 12}, {1, 13}, {1, 14}, {1, 15}, {1, 16},
+	 {1, 17}, {1, 18}, {1, 19}, {1, 20}, {2, 1},  {2, 2},  {2, 3},  {2, 4},  {2, 5},  {2, 6},  {2, 7},  {2, 8},
+	 {2, 9},  {2, 10}, {3, 1},  {3, 2},  {3, 3},  {3, 4},  {3, 5},  {3, 6},  {3, 7},  {4, 1},  {4, 2},  {4, 3},
+	 {4, 4},  {4, 5},  {4, 6},  {5, 1},  {5, 2},  {5, 3},  {5, 4},  {5, 5},  {6, 1},  {6, 2},  {6, 3},  {6, 4},
+	 {7, 1},  {7, 2},  {7, 3},  {8, 1},  {8, 2},  {8, 3},  {9, 1},  {9, 2},  {9, 3},  {10, 1}, {10, 2}, {11, 1},
+	 {11, 2}, {12, 1}, {12, 2}, {13, 1}, {13, 2}, {14, 1}, {0, 1},  {0, 2},  {0, 3},  {0, 4},  {1, 1},  {1, 2},
+	 {1, 3},  {2, 1},  {2, 2},  {2, 3},  {3, 1},  {3, 2},  {4, 1},  {4, 2},  {5, 1},  {5, 2},  {6, 1},  {6, 2},
+	 {7, 1},  {7, 2},  {8, 1},  {8, 2},  {9, 1},  {9, 2},  {10, 1}, {10, 2}, {11, 1}, {11, 2}, {12, 1}, {12, 2},
+	 {13, 1}, {13, 2}, {14, 1}, {14, 2}, {15, 1}, {16, 1}},
+	{{0, 1},  {0, 2},  {0, 3},  {0, 4},  {0, 5},  {0, 6},  {0, 7},  {0, 8},  {0, 9},  {0, 10}, {0, 11}, {0, 12},
+	 {0, 13}, {0, 14}, {0, 15}, {0, 16}, {0, 17}, {0, 18}, {0, 19}, {0, 20}, {0, 21}, {0, 22}, {0, 23}, {0, 24},
+	 {0, 25}, {0, 26}, {0, 27}, {0, 28}, {0, 29}, {0, 30}, {0, 31}, {0, 32}, {1, 1},  {1, 2},  {1, 3},  {1, 4},
+	 {1, 5},  {1, 6},  {1, 7},  {1, 8},  {1, 9},  {1, 10}, {1, 11}, {1, 12}, {1, 13}, {2, 1},  {2, 2},  {2, 3},
+	 {2, 4},  {2, 5},  {2, 6},  {2, 7},  {2, 8},  {3, 1},  {3, 2},  {3, 3},  {3, 4},  {3, 5},  {3, 6},  {4, 1},
+	 {4, 2},  {4, 3},  {4, 4},  {4, 5},  {5, 1},  {5, 2},  {5, 3},  {5, 4},  {6, 1},  {6, 2},  {6, 3},  {6, 4},
+	 {7, 1},  {7, 2},  {7, 3},  {8, 1},  {8, 2},  {8, 3},  {9, 1},  {9, 2},  {9, 3},  {10, 1}, {10, 2}, {11, 1},
+	 {11, 2}, {12, 1}, {12, 2}, {13, 1}, {13, 2}, {14, 1}, {14, 2}, {15, 1}, {15, 2}, {16, 1}, {16, 2}, {17, 1},
+	 {17, 2}, {18, 1}, {18, 2}, {19, 1}, {19, 2}, {20, 1}, {20, 2}, {21, 1}, {21, 2}, {22, 1}, {22, 2}, {23, 1},
+	 {24, 1}, {0, 1},  {0, 2},  {0, 3},  {0, 4},  {1, 1},  {1, 2},  {1, 3},  {2, 1},  {2, 2},  {2, 3},  {3, 1},
+	 {3, 2},  {3, 3},  {4, 1},  {4, 2},  {5, 1},  {5, 2},  {6, 1},  {6, 2},  {7, 1},  {7, 2},  {8, 1},  {8, 2},
+	 {9, 1},  {9, 2},  {10, 1}, {10, 2}, {11, 1}, {11, 2}, {12, 1}, {12, 2}, {13, 1}, {13, 2}, {14, 1}, {14, 2},
+	 {15, 1}, {15, 2}, {16, 1}, {16, 2}, {17, 1}, {17, 2}, {18, 1}, {18, 2}, {19, 1}, {19, 2}, {20, 1}, {20, 2},
+	 {21, 1}, {21, 2}, {22, 1}, {22, 2}, {23, 1}, {23, 2}, {24, 1}, {24, 2}, {25, 1}, {25, 2}, {26, 1}, {26, 2},
+	 {27, 1}, {27, 2}, {28, 1}, {28, 2}, {29, 1}, {30, 1}}};
+
+static const uint8 vc1_delta_level_table[AC_MODES][31] = {
+	{19, 15, 12, 11, 6, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+	{23, 11, 8, 7, 5, 5, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+	{16, 11, 8, 7, 5, 4, 4, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 1},
+	{14, 9, 5, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+	{27, 10, 5, 4, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 1},
+	{12, 6, 4, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+	{56, 20, 10, 7, 6, 5, 4, 3, 3, 3, 2, 2, 2, 2, 1},
+	{32, 13, 8, 6, 5, 4, 4, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1}};
+
+static const uint8 vc1_last_delta_level_table[AC_MODES][44] = {
+	{6, 5, 4, 4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+	{9, 5, 4, 4, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+	{4, 4, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+	{5, 4, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 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},
+	{8, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+	{3, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+	{4, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1},
+	{4, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1}};
+
+static const uint8 vc1_delta_run_table[AC_MODES][57] = {
+	{255, 30, 17, 15, 9, 5, 4, 3, 3, 3, 3, 3, 2, 1, 1, 1, 0, 0, 0, 0},
+	{255, 26, 16, 11, 7, 5, 3, 3, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{255, 20, 15, 13, 6, 4, 3, 3, 2, 1, 1, 1, 0, 0, 0, 0, 0},
+	{255, 29, 15, 12, 5, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0},
+	{255, 14, 9, 7, 3, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	{255, 26, 10, 6, 2, 1, 1, 0, 0, 0, 0, 0, 0},
+	{255, 14, 13, 9, 6, 5, 4, 3, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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, 0, 0, 0, 0},
+	{255, 24, 22, 9, 6, 4, 3, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
+
+static const uint8 vc1_last_delta_run_table[AC_MODES][10] = {{255, 37, 15, 4, 3, 1, 0},
+															 {255, 36, 14, 6, 3, 1, 0, 0, 0, 0},
+															 {255, 26, 13, 3, 1},
+															 {255, 43, 15, 3, 1, 0},
+															 {255, 20, 6, 1, 0, 0, 0, 0, 0},
+															 {255, 40, 1, 0},
+															 {255, 16, 14, 2, 0},
+															 {255, 30, 28, 3, 0}};
+
+/* BitPlane IMODE - such a small table... */
+// Static coding tables
+
+static const uint8 vc1_imode_codes[7] = {0, 2, 1, 3, 1, 2, 3};
+static const uint8 vc1_imode_bits[7] = {4, 2, 3, 2, 4, 3, 3};
+
+/* Normal-2 imode */
+static const uint8 vc1_norm2_codes[4] = {0, 4, 5, 3};
+static const uint8 vc1_norm2_bits[4] = {1, 3, 3, 2};
+
+static const uint16 vc1_norm6_codes[64] = {
+	0x001, 0x002, 0x003, 0x000, 0x004, 0x001, 0x002, 0x047, 0x005, 0x003, 0x004, 0x04B, 0x005, 0x04D, 0x04E, 0x30E,
+	0x006, 0x006, 0x007, 0x053, 0x008, 0x055, 0x056, 0x30D, 0x009, 0x059, 0x05A, 0x30C, 0x05C, 0x30B, 0x30A, 0x037,
+	0x007, 0x00A, 0x00B, 0x043, 0x00C, 0x045, 0x046, 0x309, 0x00D, 0x049, 0x04A, 0x308, 0x04C, 0x307, 0x306, 0x036,
+	0x00E, 0x051, 0x052, 0x305, 0x054, 0x304, 0x303, 0x035, 0x058, 0x302, 0x301, 0x034, 0x300, 0x033, 0x032, 0x007,
+};
+
+static const uint8 vc1_norm6_bits[64] = {
+	1,  4,  4,  8,  4,  8,  8,  10, 4,  8,  8,  10, 8,  10, 10, 13, 4,  8,  8, 10, 8,  10,
+	10, 13, 8,  10, 10, 13, 10, 13, 13, 9,  4,  8,  8,  10, 8,  10, 10, 13, 8, 10, 10, 13,
+	10, 13, 13, 9,  8,  10, 10, 13, 10, 13, 13, 9,  10, 13, 13, 9,  13, 9,  9, 6,
+};
+
+/* 4MV Block pattern VLC tables */
+static const uint8 vc1_4mv_block_pattern_codes[4][16] = {{14, 58, 59, 25, 12, 26, 15, 15, 13, 24, 27, 0, 28, 1, 2, 2},
+														 {8, 18, 19, 4, 20, 5, 30, 11, 21, 31, 6, 12, 7, 13, 14, 0},
+														 {15, 6, 7, 2, 8, 3, 28, 9, 10, 29, 4, 11, 5, 12, 13, 0},
+														 {0, 11, 12, 4, 13, 5, 30, 16, 14, 31, 6, 17, 7, 18, 19, 10}};
+static const uint8 vc1_4mv_block_pattern_bits[4][16] = {{5, 6, 6, 5, 5, 5, 5, 4, 5, 5, 5, 3, 5, 3, 3, 2},
+														{4, 5, 5, 4, 5, 4, 5, 4, 5, 5, 4, 4, 4, 4, 4, 2},
+														{4, 4, 4, 4, 4, 4, 5, 4, 4, 5, 4, 4, 4, 4, 4, 3},
+														{2, 4, 4, 4, 4, 4, 5, 5, 4, 5, 4, 5, 4, 5, 5, 4}};
+
+/* 2MV Block pattern VLC tables */
+static const uint8 vc1_2mv_block_pattern_codes[4][4] = {{2, 1, 0, 3}, {1, 0, 2, 3}, {2, 0, 3, 1}, {1, 3, 2, 0}};
+
+static const uint8 vc1_2mv_block_pattern_bits[4][4] = {{2, 2, 2, 2}, {1, 2, 3, 3}, {3, 2, 3, 1}, {1, 3, 3, 2}};
+
+/* Interlaced frame picture 4MV MBMODE VLC tables (p. 246, p. 360) */
+static const uint16 vc1_intfr_4mv_mbmode_codes[4][15] = {
+	{22, 17, 0, 47, 32, 10, 1, 3, 67, 133, 132, 92, 19, 93, 18},
+	{3, 45, 0, 7, 23, 6, 1, 2, 10, 39, 44, 8, 18, 77, 76},
+	{15, 6, 28, 9, 41, 6, 2, 15, 14, 8, 40, 29, 0, 21, 11},
+	{7, 198, 1, 2, 193, 13, 25, 0, 97, 1599, 98, 398, 798, 192, 1598}};
+
+static const uint8 vc1_intfr_4mv_mbmode_bits[4][15] = {{5, 5, 2, 6, 6, 4, 2, 2, 7, 8, 8, 7, 5, 7, 5},
+													   {3, 6, 3, 3, 5, 3, 3, 3, 4, 6, 6, 4, 5, 7, 7},
+													   {4, 3, 5, 5, 7, 4, 2, 5, 5, 5, 7, 5, 2, 6, 5},
+													   {4, 9, 1, 3, 9, 5, 6, 2, 8, 12, 8, 10, 11, 9, 12}};
+
+/* Interlaced frame picture NON-4MV MBMODE VLC tables (p. 363) */
+static const uint8 vc1_intfr_non4mv_mbmode_codes[4][9] = {{9, 22, 0, 17, 16, 10, 1, 3, 23},
+														  {7, 0, 5, 2, 1, 1, 6, 3, 4},
+														  {1, 0, 10, 23, 44, 8, 3, 9, 45},
+														  {7, 97, 1, 2, 49, 13, 25, 0, 96}};
+
+static const uint8 vc1_intfr_non4mv_mbmode_bits[4][9] = {
+	{4, 5, 2, 5, 5, 4, 2, 2, 5}, {3, 4, 6, 2, 3, 2, 3, 5, 6}, {2, 2, 4, 5, 6, 4, 2, 4, 6}, {4, 8, 1, 3, 7, 5, 6, 2, 8}};
+
+/* Interlaced field picture MBMODE VLC tables (p. 356 - 11.4.1, 11.4.2) */
+/* mixed-MV */
+static const uint8 vc1_if_mmv_mbmode_codes[8][8] = {{16, 17, 3, 3, 0, 5, 9, 2},     {8, 9, 3, 6, 7, 0, 5, 2},
+													{16, 17, 5, 3, 0, 3, 9, 2},     {56, 57, 15, 4, 5, 6, 29, 0},
+													{52, 53, 27, 14, 15, 2, 12, 0}, {56, 57, 29, 5, 6, 0, 15, 4},
+													{16, 17, 6, 7, 0, 1, 9, 5},     {56, 57, 0, 5, 6, 29, 4, 15}};
+static const uint8 vc1_if_mmv_mbmode_bits[8][8] = {
+	{6, 6, 2, 3, 2, 4, 5, 2}, {5, 5, 3, 3, 3, 2, 4, 2}, {6, 6, 4, 3, 2, 2, 5, 2}, {6, 6, 4, 3, 3, 3, 5, 1},
+	{6, 6, 5, 4, 4, 2, 4, 1}, {6, 6, 5, 3, 3, 1, 4, 3}, {5, 5, 3, 3, 2, 2, 4, 3}, {6, 6, 1, 3, 3, 5, 3, 4}};
+
+/* 1MV */
+static const uint8 vc1_if_1mv_mbmode_codes[8][6] = {{0, 1, 1, 1, 1, 1},    {0, 1, 1, 1, 1, 1},  {16, 17, 3, 0, 9, 5},
+													{20, 21, 3, 11, 0, 4}, {4, 5, 2, 3, 3, 0},  {4, 5, 3, 2, 0, 3},
+													{0, 1, 1, 1, 1, 1},    {16, 17, 9, 5, 3, 0}};
+static const uint8 vc1_if_1mv_mbmode_bits[8][6] = {{5, 5, 1, 3, 2, 4}, {5, 5, 1, 2, 3, 4}, {5, 5, 2, 1, 4, 3},
+												   {5, 5, 2, 4, 1, 3}, {4, 4, 2, 3, 2, 2}, {4, 4, 3, 2, 2, 2},
+												   {5, 5, 3, 4, 1, 2}, {5, 5, 4, 3, 2, 1}};
+
+/* Interlaced frame/field picture MVDATA VLC tables */
+
+/* 1-reference tables */
+static const uint32 vc1_1ref_mvdata_codes[4][72] =
+	{/* uint32 may be too big */
+	 {0x00005, 0x0000C, 0x0001E, 0x00012, 0x0000C, 0x00034, 0x00075, 0x00070, 0x00000, 0x00008, 0x0001B, 0x00008,
+	  0x0001D, 0x0007C, 0x000D6, 0x001DE, 0x001AF, 0x00005, 0x0001B, 0x00026, 0x0001E, 0x00012, 0x00076, 0x0004D,
+	  0x001F6, 0x001F4, 0x00039, 0x0007F, 0x00027, 0x0006A, 0x00071, 0x00035, 0x00071, 0x00068, 0x001DC, 0x00027,
+	  0x00073, 0x000FF, 0x000E8, 0x000E9, 0x0007E, 0x001F9, 0x001F5, 0x001FD, 0x0003E, 0x001CA, 0x003F9, 0x0004C,
+	  0x00069, 0x001FA, 0x001DF, 0x001F7, 0x00070, 0x001DD, 0x00E4D, 0x00727, 0x00392, 0x001C8, 0x001CB, 0x003F8,
+	  0x001AE, 0x001F8, 0x001FB, 0x0E4CE, 0x0E4CF, 0x07260, 0x07261, 0x07262, 0x07263, 0x07264, 0x07265, 0x07266},
+	 {0x00007, 0x00001, 0x00007, 0x00016, 0x00001, 0x00045, 0x00018, 0x002B6, 0x00006, 0x00004, 0x00017, 0x00010,
+	  0x00029, 0x0002C, 0x0015A, 0x00066, 0x0019E, 0x00009, 0x00028, 0x00017, 0x00000, 0x0002A, 0x00004, 0x0005B,
+	  0x000B5, 0x000CE, 0x00006, 0x00044, 0x0000F, 0x00046, 0x0000E, 0x000AC, 0x00032, 0x00037, 0x011EB, 0x0000A,
+	  0x0001A, 0x0011F, 0x00016, 0x00014, 0x0002B, 0x00168, 0x00055, 0x023D5, 0x00057, 0x0002F, 0x00036, 0x0002E,
+	  0x00169, 0x00054, 0x0047B, 0x0019F, 0x02B7D, 0x0008E, 0x00ADE, 0x00479, 0x0056E, 0x008F4, 0x015BF, 0x00478,
+	  0x023D4, 0x0ADF1, 0x056F9, 0xADF0E, 0xADF0F, 0x56F80, 0x56F81, 0x56F82, 0x56F83, 0x56F84, 0x56F85, 0x56F86},
+	 {0x00002, 0x00006, 0x00007, 0x0000D, 0x00007, 0x00030, 0x000FF, 0x001F0, 0x00002, 0x00000, 0x00005, 0x00019,
+	  0x0001E, 0x00007, 0x00063, 0x000FD, 0x00023, 0x0000E, 0x0001B, 0x0001A, 0x00006, 0x00009, 0x00018, 0x000C5,
+	  0x00033, 0x001F1, 0x00002, 0x003FB, 0x001F3, 0x00022, 0x001FC, 0x00042, 0x00623, 0x00083, 0x00620, 0x0007D,
+	  0x00040, 0x00043, 0x003E4, 0x003E5, 0x00191, 0x00FE9, 0x00105, 0x00208, 0x000FC, 0x00624, 0x00622, 0x00190,
+	  0x00626, 0x007F5, 0x00C4B, 0x01FD0, 0x0104D, 0x00065, 0x00C42, 0x000C9, 0x00627, 0x00C43, 0x00C4A, 0x0104E,
+	  0x01FD1, 0x0104F, 0x00412, 0x104CE, 0x104CF, 0x08260, 0x08261, 0x08262, 0x08263, 0x08264, 0x08265, 0x08266},
+	 {0x0000D, 0x00001, 0x00004, 0x00000, 0x00017, 0x00005, 0x0007F, 0x0004D, 0x00003, 0x00011, 0x0003E, 0x0003B,
+	  0x00017, 0x00067, 0x0004A, 0x000C3, 0x000F2, 0x0000A, 0x0002C, 0x00032, 0x0003D, 0x00015, 0x00028, 0x00093,
+	  0x000CC, 0x00096, 0x00003, 0x00075, 0x00020, 0x0002D, 0x00021, 0x00029, 0x00090, 0x001D0, 0x001FB, 0x0001C,
+	  0x0004C, 0x00060, 0x00009, 0x00008, 0x0002D, 0x0009F, 0x001FA, 0x0013D, 0x00031, 0x000FC, 0x00058, 0x00092,
+	  0x000F0, 0x000F1, 0x000CD, 0x00185, 0x00165, 0x0004E, 0x00091, 0x000E9, 0x00184, 0x001D1, 0x001E6, 0x00097,
+	  0x001E7, 0x000B3, 0x0013C, 0x0164E, 0x0164F, 0x00B20, 0x00B21, 0x00B22, 0x00B23, 0x00B24, 0x00B25, 0x00B26}};
+
+static const uint8 vc1_1ref_mvdata_bits[4][72] = {
+	{3, 4, 5, 5, 5, 6, 7,  7,  2,  4,  5,  5,  6, 7, 8, 9,  9,  4,  6,  6,  6,  6,  7,  8,
+	 9, 9, 6, 8, 7, 7, 7,  7,  8,  8,  9,  6,  8, 8, 8, 8,  8,  9,  9,  9,  7,  10, 10, 8,
+	 8, 9, 9, 9, 8, 9, 13, 12, 11, 10, 10, 10, 9, 9, 9, 17, 17, 16, 16, 16, 16, 16, 16, 16},
+	{3,  3,  4,  5,  5,  7, 8,  10, 3,  4,  5,  5,  6,  7,  9,  10, 12, 4,  6,  6,  5,  6,  6,  8,
+	 9,  11, 4,  7,  7,  7, 7,  8,  9,  9,  13, 5,  8,  9,  8,  8,  9,  10, 10, 14, 7,  9,  9,  9,
+	 10, 10, 11, 12, 14, 8, 12, 11, 11, 12, 13, 11, 14, 16, 15, 20, 20, 19, 19, 19, 19, 19, 19, 19},
+	{3,  4,  4,  4,  5,  6, 8,  9,  2,  4,  5,  5,  5,  6,  7,  8,  8,  4,  7,  7,  6,  6,  7,  8,
+	 8,  9,  5,  10, 9,  8, 9,  9,  11, 10, 11, 7,  9,  9,  10, 10, 11, 12, 11, 12, 8,  11, 11, 11,
+	 11, 11, 12, 13, 15, 9, 12, 10, 11, 12, 12, 15, 13, 15, 13, 19, 19, 18, 18, 18, 18, 18, 18, 18},
+	{4, 4, 4, 4, 5,  5, 7, 7, 3, 5, 6, 6, 6, 7, 7, 8,  8,  4,  6,  6,  6,  6,  7,  8,
+	 8, 8, 4, 7, 6,  6, 6, 7, 8, 9, 9, 5, 7, 7, 6, 6,  7,  8,  9,  9,  6,  8,  8,  8,
+	 8, 8, 8, 9, 10, 7, 8, 8, 9, 9, 9, 8, 9, 9, 9, 14, 14, 13, 13, 13, 13, 13, 13, 13}};
+
+/* 2-reference tables */
+static const uint32 vc1_2ref_mvdata_codes[8][126] =
+	{/* table 132 - table 139 */
+	 {0x0000C, 0x0001C, 0x0000B, 0x00000, 0x0000E, 0x0002A, 0x00050, 0x00368, 0x00002, 0x0001A, 0x00004, 0x0003A,
+	  0x0001D, 0x0006C, 0x000EF, 0x001BC, 0x0015F, 0x0000F, 0x00003, 0x0001C, 0x0000D, 0x0000B, 0x0003E, 0x000A7,
+	  0x00146, 0x00199, 0x00006, 0x0001F, 0x00004, 0x0003C, 0x00007, 0x001BE, 0x0008B, 0x0002C, 0x007B3, 0x00005,
+	  0x000DB, 0x00056, 0x000EC, 0x00052, 0x001BD, 0x00078, 0x000CF, 0x00573, 0x00009, 0x00023, 0x000ED, 0x00018,
+	  0x00006, 0x00044, 0x000F5, 0x00079, 0x006D2, 0x0006E, 0x0002B, 0x0015D, 0x00017, 0x0037F, 0x00144, 0x000CE,
+	  0x00028, 0x000AB, 0x00010, 0x001B5, 0x000F7, 0x000A6, 0x0007B, 0x00028, 0x001ED, 0x001E9, 0x006FD, 0x00004,
+	  0x000F5, 0x00029, 0x0028A, 0x0028B, 0x0028F, 0x00DF9, 0x00335, 0x01E85, 0x000EE, 0x002BD, 0x0002B, 0x003D8,
+	  0x003D1, 0x00198, 0x001E9, 0x0051D, 0x000B4, 0x0003F, 0x00455, 0x0022B, 0x00229, 0x00451, 0x00578, 0x007B2,
+	  0x00570, 0x00155, 0x00032, 0x003D0, 0x00054, 0x006D3, 0x00571, 0x00454, 0x00334, 0x01BF1, 0x000B7, 0x00029,
+	  0x01E84, 0x0016C, 0x0019B, 0x01BF0, 0x00579, 0x00F43, 0x000B5, 0x008A1, 0x0002A, 0x0016D, 0x008A0, 0x007A0,
+	  0x003D1, 0x00AE5, 0x00154, 0x00AE4, 0x00A39, 0x00A38},
+	 {0x00003, 0x00009, 0x00016, 0x00010, 0x000D7, 0x00335, 0x00574, 0x00555, 0x00000, 0x0001D, 0x00009, 0x00017,
+	  0x0002C, 0x000AD, 0x00374, 0x006B3, 0x00577, 0x0000F, 0x00018, 0x0000A, 0x0002E, 0x00022, 0x0017C, 0x00E7B,
+	  0x01B89, 0x015D8, 0x00008, 0x00034, 0x0006D, 0x00023, 0x001C2, 0x00376, 0x002D3, 0x01C4A, 0x0330A, 0x00014,
+	  0x0006A, 0x00072, 0x0006C, 0x000E3, 0x0019B, 0x0073F, 0x01CF0, 0x00B41, 0x00032, 0x000E6, 0x000E0, 0x000CF,
+	  0x000AB, 0x0019C, 0x002AB, 0x00E2B, 0x015D9, 0x0006F, 0x001C3, 0x000AF, 0x000BF, 0x000AC, 0x0017D, 0x006E3,
+	  0x00E29, 0x01984, 0x00054, 0x000B5, 0x0017A, 0x001AD, 0x00199, 0x00178, 0x00358, 0x002D2, 0x01C4B, 0x0005B,
+	  0x002A8, 0x00331, 0x00388, 0x0038B, 0x00370, 0x00713, 0x00CC3, 0x01CF1, 0x001B9, 0x005EF, 0x00738, 0x002F2,
+	  0x0033B, 0x002B9, 0x006EB, 0x00570, 0x00E24, 0x0039D, 0x005A2, 0x005A3, 0x00E7D, 0x005EE, 0x00739, 0x00554,
+	  0x00AA5, 0x00AA4, 0x00377, 0x01CF5, 0x00BCE, 0x00E79, 0x00660, 0x00674, 0x006EA, 0x00E7C, 0x00D65, 0x002F6,
+	  0x015DA, 0x01B88, 0x005A1, 0x01CF4, 0x005E6, 0x00E28, 0x00575, 0x00D64, 0x00334, 0x0330B, 0x015DB, 0x00B40,
+	  0x00BCF, 0x00DC5, 0x00E2A, 0x00675, 0x00571, 0x00553},
+	 {0x00004, 0x00002, 0x00010, 0x00003, 0x00017, 0x00045, 0x0003E, 0x0007E, 0x00003, 0x00002, 0x00028, 0x0001E,
+	  0x00015, 0x00047, 0x00002, 0x0014D, 0x00060, 0x0000B, 0x00026, 0x00024, 0x00014, 0x00032, 0x0006F, 0x000C3,
+	  0x00531, 0x006E5, 0x00015, 0x0003F, 0x0002D, 0x00001, 0x0013E, 0x000DD, 0x000F6, 0x00305, 0x00331, 0x0000E,
+	  0x00003, 0x00034, 0x00033, 0x0001A, 0x0014A, 0x000C5, 0x000F4, 0x006E4, 0x00001, 0x0003C, 0x0007D, 0x0008D,
+	  0x0009D, 0x00031, 0x0006E, 0x00296, 0x000CD, 0x00025, 0x00149, 0x00032, 0x00089, 0x00036, 0x00088, 0x0006F,
+	  0x00003, 0x0031D, 0x0000E, 0x001AA, 0x0027E, 0x00061, 0x0014E, 0x0014F, 0x00067, 0x000FF, 0x00183, 0x00036,
+	  0x00357, 0x000F5, 0x000C6, 0x000C2, 0x00299, 0x00119, 0x00231, 0x00350, 0x0002C, 0x0018F, 0x00530, 0x00297,
+	  0x00004, 0x001B8, 0x000C0, 0x0027A, 0x00311, 0x0009C, 0x00621, 0x00199, 0x0031C, 0x000F7, 0x003E3, 0x00356,
+	  0x00189, 0x00005, 0x0006B, 0x008C2, 0x00330, 0x004FF, 0x004F0, 0x00351, 0x004F2, 0x001F2, 0x00373, 0x00000,
+	  0x00C41, 0x008C3, 0x009EC, 0x003E2, 0x00304, 0x004F7, 0x004F1, 0x001F0, 0x00148, 0x00C40, 0x009ED, 0x008C0,
+	  0x008C1, 0x004F3, 0x004FE, 0x000FE, 0x001F3, 0x001A9},
+	 {0x00000, 0x00004, 0x0002F, 0x00052, 0x00010, 0x000AD, 0x0050B, 0x00190, 0x00003, 0x00016, 0x00007, 0x0000D,
+	  0x000BB, 0x00173, 0x000C9, 0x0050F, 0x0172C, 0x00003, 0x00011, 0x00005, 0x00043, 0x00023, 0x0004B, 0x0032E,
+	  0x02E5B, 0x00482, 0x00009, 0x0002A, 0x00014, 0x0002A, 0x00108, 0x005CA, 0x0065A, 0x02136, 0x02132, 0x0000B,
+	  0x00013, 0x00041, 0x000B8, 0x00174, 0x00100, 0x014DA, 0x0404E, 0x01437, 0x0002B, 0x00085, 0x000A7, 0x000A0,
+	  0x0014C, 0x0029A, 0x0032C, 0x02133, 0x0142A, 0x00051, 0x00284, 0x000AC, 0x00102, 0x00045, 0x00044, 0x0081B,
+	  0x0065E, 0x00CB7, 0x00018, 0x0050C, 0x00212, 0x002E4, 0x00203, 0x00094, 0x00122, 0x0081A, 0x00655, 0x00033,
+	  0x002BA, 0x00246, 0x00242, 0x00A6E, 0x0040C, 0x00808, 0x02134, 0x0404F, 0x00175, 0x00405, 0x00247, 0x0012A,
+	  0x00A14, 0x002BB, 0x00191, 0x0084F, 0x01438, 0x000AF, 0x00B97, 0x00483, 0x0143B, 0x0032B, 0x00243, 0x0142B,
+	  0x00958, 0x029BF, 0x00049, 0x00A6C, 0x014DB, 0x004AD, 0x014DE, 0x0084E, 0x01434, 0x00257, 0x02E5A, 0x00207,
+	  0x01435, 0x01439, 0x00CB6, 0x0143A, 0x00194, 0x00654, 0x02135, 0x0537C, 0x0015C, 0x00240, 0x01012, 0x0537D,
+	  0x00959, 0x01098, 0x01436, 0x0065F, 0x02026, 0x02137},
+	 {0x00005, 0x00019, 0x00016, 0x00011, 0x0003E, 0x0005E, 0x000EF, 0x000E2, 0x00000, 0x00039, 0x0002B, 0x00026,
+	  0x00028, 0x00012, 0x000C2, 0x000ED, 0x0011D, 0x0000D, 0x00031, 0x0002A, 0x00025, 0x00020, 0x0005C, 0x001ED,
+	  0x0024D, 0x00770, 0x00006, 0x0007A, 0x00060, 0x0004F, 0x00048, 0x00039, 0x00186, 0x00213, 0x00EC6, 0x0000F,
+	  0x00026, 0x0005F, 0x00075, 0x00070, 0x00027, 0x001DB, 0x003C6, 0x0078F, 0x0003F, 0x000A6, 0x000F0, 0x0003A,
+	  0x00052, 0x0004E, 0x000E3, 0x001D9, 0x0030F, 0x00010, 0x001DD, 0x000A7, 0x000F7, 0x00022, 0x00092, 0x003C4,
+	  0x002EF, 0x00762, 0x00079, 0x0008F, 0x001DA, 0x00087, 0x000E8, 0x000BA, 0x00176, 0x000EE, 0x003B0, 0x00085,
+	  0x00119, 0x0030E, 0x00108, 0x001D2, 0x0010C, 0x00773, 0x00424, 0x00434, 0x00071, 0x005DD, 0x001C1, 0x003A7,
+	  0x00127, 0x0008D, 0x0021B, 0x007B2, 0x001DF, 0x003D8, 0x00764, 0x00EE4, 0x003B3, 0x0074D, 0x001D8, 0x005DC,
+	  0x0084A, 0x00499, 0x003C5, 0x01D8E, 0x00765, 0x00435, 0x00771, 0x001C2, 0x00118, 0x003BC, 0x00381, 0x00387,
+	  0x07B33, 0x01097, 0x01096, 0x01ECD, 0x00E99, 0x00F1C, 0x00F1D, 0x00EE5, 0x0011C, 0x07B32, 0x03D98, 0x01D8F,
+	  0x00E98, 0x00F67, 0x003BD, 0x00380, 0x00498, 0x00386},
+	 {0x0000D, 0x00010, 0x0002E, 0x00039, 0x0000D, 0x00074, 0x000ED, 0x000B6, 0x00001, 0x00002, 0x00000, 0x00030,
+	  0x00029, 0x00070, 0x000F3, 0x0008C, 0x00166, 0x00009, 0x00033, 0x00078, 0x00006, 0x000C4, 0x0000B, 0x00163,
+	  0x000CC, 0x005BE, 0x0001F, 0x0002F, 0x00064, 0x00018, 0x000C6, 0x0000A, 0x00162, 0x002C0, 0x00EF3, 0x00007,
+	  0x0000F, 0x000E3, 0x000CA, 0x000B2, 0x0018F, 0x003AE, 0x0075F, 0x00C51, 0x00015, 0x00047, 0x000EE, 0x000E2,
+	  0x000EA, 0x00009, 0x0016A, 0x002C3, 0x0059D, 0x0003D, 0x00008, 0x001D9, 0x00032, 0x0000E, 0x0016E, 0x0032C,
+	  0x0065B, 0x0196B, 0x00002, 0x0000F, 0x001D8, 0x0008D, 0x000B4, 0x001E4, 0x00067, 0x00317, 0x00794, 0x00022,
+	  0x003BE, 0x00315, 0x00034, 0x00037, 0x002DE, 0x0006C, 0x00EFE, 0x0066C, 0x00028, 0x003CB, 0x003AC, 0x00035,
+	  0x0016B, 0x003BD, 0x002C1, 0x0062C, 0x01DFE, 0x0000E, 0x0059E, 0x005BF, 0x000DA, 0x00629, 0x00584, 0x00EB7,
+	  0x00B0A, 0x0066D, 0x0000C, 0x0077E, 0x0059C, 0x00778, 0x0075E, 0x0075A, 0x0062D, 0x00337, 0x00334, 0x00197,
+	  0x01E57, 0x01DE4, 0x0196A, 0x01E56, 0x00C50, 0x00B3F, 0x01E54, 0x00B0B, 0x0018E, 0x001B6, 0x01E55, 0x00CB4,
+	  0x00B3E, 0x00EB6, 0x01DE5, 0x01DFF, 0x00335, 0x001B7},
+	 {0x00001, 0x0000B, 0x00019, 0x0006F, 0x0002A, 0x00075, 0x007EB, 0x00163, 0x00001, 0x0000E, 0x0001A, 0x0003E,
+	  0x0001C, 0x0002D, 0x00164, 0x007EC, 0x00165, 0x00004, 0x00006, 0x00036, 0x0007F, 0x000AE, 0x00158, 0x0015C,
+	  0x0056D, 0xFD510, 0x00000, 0x00004, 0x0007B, 0x000F3, 0x0003B, 0x007ED, 0x002B3, 0x002CC, 0x0056E, 0x00018,
+	  0x0003E, 0x00017, 0x0001E, 0x000AF, 0x003F7, 0x0056F, 0x002CD, 0xFD511, 0x00014, 0x000AD, 0x000AA, 0x00014,
+	  0x000A8, 0x00153, 0x000E8, 0x001FE, 0x00DCF, 0x00078, 0x001B8, 0x00152, 0x000FE, 0x002B1, 0x0015D, 0x00160,
+	  0xFD512, 0xFD513, 0x0007A, 0x002B0, 0x001E5, 0x000E9, 0x000FC, 0x006E6, 0x00DC8, 0x00584, 0xFD514, 0x000AB,
+	  0x00DDE, 0x00159, 0x003F4, 0x00DC9, 0x00DCA, 0x001FA, 0xFD515, 0xFD516, 0x000FC, 0x001FF, 0x001E4, 0x000AF,
+	  0x0015A, 0x00167, 0x00DCB, 0x00585, 0xFD517, 0x003F7, 0x03F55, 0xFD518, 0x00DDC, 0x00586, 0x03F56, 0xFD519,
+	  0x03F57, 0xFD51A, 0x001BA, 0x00587, 0x00588, 0x00DDF, 0x002B2, 0xFD51B, 0x00DCE, 0x003F6, 0xFD51C, 0x00FD4,
+	  0xFD51D, 0xFD51E, 0xFD51F, 0x7EA80, 0x7EA81, 0x0056C, 0x7EA82, 0x7EA83, 0x00376, 0x00589, 0x0058A, 0x7EA84,
+	  0x7EA85, 0x00DDD, 0x7EA86, 0x7EA87, 0x0058B, 0x07EA9},
+	 {0x00003, 0x0000E, 0x0000F, 0x0007E, 0x00062, 0x000C6, 0x00CD9, 0x0063E, 0x00002, 0x00002, 0x00000, 0x00018,
+	  0x0000C, 0x00069, 0x00039, 0x00707, 0x00C7E, 0x00002, 0x0000D, 0x0001B, 0x0000F, 0x0019A, 0x00647, 0x01A37,
+	  0x346C4, 0x0346D, 0x00001, 0x0001E, 0x0007F, 0x0000A, 0x000E1, 0x00661, 0x00CE4, 0x346C5, 0x346C6, 0x0001D,
+	  0x00030, 0x0000D, 0x000CB, 0x00199, 0x00320, 0x0008E, 0x0652E, 0x346C7, 0x0003E, 0x00039, 0x00035, 0x00033,
+	  0x0019F, 0x001C0, 0x00CDA, 0x346C8, 0x346C9, 0x0000B, 0x000D0, 0x0019E, 0x00022, 0x00038, 0x0018E, 0x0031E,
+	  0x03294, 0x0023C, 0x00032, 0x00012, 0x00013, 0x00071, 0x0019D, 0x00020, 0x00C87, 0x00CC0, 0x346CA, 0x00338,
+	  0x00653, 0x001A2, 0x0032A, 0x00322, 0x00CE7, 0x00084, 0x0011F, 0x346CB, 0x00325, 0x00649, 0x0032B, 0x00077,
+	  0x00648, 0x00642, 0x00C86, 0x00C8C, 0x346CC, 0x0003A, 0x019B7, 0x00043, 0x00327, 0x0008C, 0x0008D, 0x00C8D,
+	  0x346CD, 0x346CE, 0x00337, 0x00CE5, 0x00085, 0x00326, 0x00347, 0x00CA4, 0x00C7F, 0x00D1A, 0x346CF, 0x00328,
+	  0x1A360, 0x1A361, 0x00CD8, 0x0068C, 0x03295, 0x03296, 0x0652F, 0x066D8, 0x00331, 0x00706, 0x0023D, 0x00076,
+	  0x00CC1, 0x00382, 0x00CE6, 0x066D9, 0x066DA, 0x066DB}};
+
+static const uint8 vc1_2ref_mvdata_bits[8][126] = {
+	{4,  5,  5,  5,  6,  7,  8,  10, 2,  5,  5,  6,  6,  7,  8,  9,  10, 4,  5,  6,  6,  7,  8,  9,  10, 11,
+	 4,  6,  6,  7,  7,  9,  9,  10, 12, 5,  8,  8,  8,  8,  9,  9,  10, 12, 5,  7,  8,  7,  7,  8,  9,  9,
+	 11, 7,  9,  10, 9,  10, 10, 10, 10, 12, 6,  9,  9,  9,  9,  9,  10, 10, 11, 7,  10, 10, 11, 11, 11, 12,
+	 12, 14, 8,  11, 10, 11, 11, 11, 11, 12, 12, 8,  12, 11, 11, 12, 12, 12, 12, 13, 8,  12, 11, 11, 12, 12,
+	 12, 13, 12, 9,  14, 13, 11, 13, 12, 13, 12, 13, 9,  13, 13, 12, 12, 13, 13, 13, 13, 13},
+	{3,  4,  5,  6,  8,  10, 11, 11, 2,  5,  5,  6,  7,  8,  10, 11, 11, 4,  5,  5,  6,  7,  9,  12, 13, 13,
+	 4,  6,  7,  7,  9,  10, 11, 13, 14, 5,  7,  7,  7,  8,  9,  11, 13, 13, 6,  8,  8,  8,  8,  9,  10, 12,
+	 13, 7,  9,  8,  8,  8,  9,  11, 12, 13, 7,  9,  9,  9,  9,  9,  10, 11, 13, 8,  10, 10, 10, 10, 10, 11,
+	 12, 13, 9,  11, 11, 10, 10, 10, 11, 11, 12, 10, 12, 12, 12, 11, 11, 11, 12, 12, 10, 13, 12, 12, 11, 11,
+	 11, 12, 12, 10, 13, 13, 12, 13, 11, 12, 11, 12, 10, 14, 13, 13, 12, 12, 12, 11, 11, 11},
+	{4,  4,  5,  5,  6,  7,  8,  9,  2,  5,  6,  6,  6,  7,  7,  9,  9,  4,  6,  6,  6,  7,  8,  9,  11, 12,
+	 5,  7,  7,  7,  9,  9,  10, 11, 12, 5,  7,  7,  7,  7,  9,  9,  10, 12, 5,  8,  8,  8,  8,  8,  9,  10,
+	 10, 6,  9,  8,  8,  8,  8,  9,  9,  11, 6,  10, 10, 9,  9,  9,  9,  10, 10, 7,  11, 10, 9,  9,  10, 9,
+	 10, 11, 7,  10, 11, 10, 10, 10, 9,  10, 11, 8,  12, 11, 11, 10, 11, 11, 10, 10, 8,  12, 12, 11, 11, 11,
+	 11, 10, 11, 8,  13, 12, 12, 11, 11, 11, 11, 10, 9,  13, 12, 12, 12, 11, 11, 10, 10, 10},
+	{3,  4,  6,  7,  7,  9,  11, 11, 2,  5,  5,  6,  8,  9,  10, 11, 13, 3,  5,  5,  7,  8,  9,  12, 14, 13,
+	 4,  6,  6,  7,  9,  11, 13, 14, 14, 5,  7,  7,  8,  9,  9,  13, 15, 13, 6,  8,  8,  8,  9,  10, 12, 14,
+	 13, 7,  10, 9,  9,  9,  9,  12, 13, 14, 7,  11, 10, 10, 10, 10, 11, 12, 13, 8,  11, 12, 12, 12, 11, 12,
+	 14, 15, 9,  11, 12, 11, 12, 11, 11, 12, 13, 9,  12, 13, 13, 12, 12, 13, 14, 14, 9,  12, 13, 13, 13, 12,
+	 13, 12, 14, 10, 13, 13, 14, 13, 11, 13, 14, 15, 10, 12, 13, 15, 14, 13, 13, 13, 14, 14},
+	{4,  5,  5,  5,  6,  7,  8,  8,  2,  6,  6,  6,  6,  6,  8,  9,  10, 4,  6,  6,  6,  6,  7,  9,  10, 11,
+	 4,  7,  7,  7,  7,  7,  9,  10, 12, 5,  7,  7,  7,  7,  7,  9,  10, 11, 6,  8,  8,  7,  7,  7,  8,  9,
+	 10, 6,  9,  8,  8,  7,  8,  10, 10, 11, 7,  9,  9,  8,  8,  8,  9,  9,  10, 8,  10, 10, 9,  9,  9,  11,
+	 11, 11, 8,  11, 10, 10, 9,  9,  10, 11, 10, 10, 12, 12, 11, 11, 10, 11, 12, 11, 10, 13, 12, 11, 11, 10,
+	 10, 11, 11, 11, 15, 13, 13, 13, 12, 12, 12, 12, 10, 15, 14, 13, 12, 12, 11, 11, 11, 11},
+	{4,  5,  6,  6,  6,  7,  8,  8,  2,  4,  5,  6,  6,  7,  8,  8,  9,  4,  6,  7,  7,  8,  8,  9,  10, 11,
+	 5,  6,  7,  7,  8,  8,  9,  10, 12, 5,  7,  8,  8,  8,  9,  10, 11, 12, 5,  7,  8,  8,  8,  8,  9,  10,
+	 11, 6,  8,  9,  8,  8,  9,  10, 11, 13, 5,  8,  9,  8,  8,  9,  9,  10, 11, 6,  10, 10, 9,  9,  10, 10,
+	 12, 13, 6,  10, 10, 9,  9,  10, 10, 11, 13, 7,  11, 11, 11, 11, 11, 12, 12, 13, 7,  11, 11, 11, 11, 11,
+	 11, 12, 12, 9,  13, 13, 13, 13, 12, 12, 13, 12, 9,  12, 13, 12, 12, 12, 13, 13, 12, 12},
+	{3,  5,  6,  8,  9,  10, 12, 12, 1,  5,  6,  7,  8,  9,  12, 12, 12, 4,  6,  7,  8,  9,  12, 12, 14, 21,
+	 4,  6,  8,  9,  9,  12, 13, 13, 14, 6,  9,  8,  8,  9,  13, 14, 13, 21, 6,  9,  9,  8,  9,  10, 11, 12,
+	 13, 8,  10, 10, 11, 11, 12, 12, 21, 21, 8,  11, 10, 11, 11, 12, 13, 14, 21, 9,  13, 10, 11, 13, 13, 12,
+	 21, 21, 9,  12, 10, 11, 12, 12, 13, 14, 21, 11, 15, 21, 13, 14, 15, 21, 15, 21, 10, 14, 14, 13, 13, 21,
+	 13, 13, 21, 13, 21, 21, 21, 20, 20, 14, 20, 20, 11, 14, 14, 20, 20, 13, 20, 20, 14, 16},
+	{2,  5,  6,  8,  9,  10, 13, 13, 2,  4,  5,  6,  8,  9,  10, 13, 14, 3,  5,  7,  8,  10, 12, 15, 20, 16,
+	 4,  6,  8,  8,  10, 12, 13, 20, 20, 7,  8,  8,  9,  10, 11, 12, 16, 20, 7,  8,  8,  8,  10, 11, 13, 20,
+	 20, 8,  10, 10, 10, 10, 11, 12, 15, 14, 8,  9,  9,  9,  10, 10, 13, 13, 20, 11, 12, 11, 11, 11, 13, 12,
+	 13, 20, 11, 12, 11, 11, 12, 12, 13, 13, 20, 10, 14, 11, 11, 12, 12, 13, 20, 20, 11, 13, 12, 11, 12, 13,
+	 14, 14, 20, 11, 19, 19, 13, 13, 15, 15, 16, 16, 11, 13, 14, 11, 13, 12, 13, 16, 16, 16}};
+
+/* P-Picture CBPCY VLC tables */
+// Looks like original tables are not conforming to standard at all. Are they used for old WMV?
+static const uint16 vc1_cbpcy_p_codes[4][64] = {
+	{0, 6,  15, 13, 13, 11,  3,  13,  5,  8,  49,  10,  12, 114, 102, 119, 1, 54, 96, 8, 10, 111,
+	 5, 15, 12, 10, 2,  12,  13, 115, 53, 63, 1,   7,   1,  7,   14,  12,  4, 14, 1,  9, 97, 11,
+	 7, 58, 52, 62, 4,  103, 1,  9,   11, 56, 101, 118, 4,  110, 100, 30,  2, 5,  4,  3},
+	{0, 9,  1,  18, 5, 14, 237, 26,  3,   121, 3,   22,  13, 16, 6,   30, 2,  10, 1, 20,  12, 241,
+	 5, 28, 16, 12, 3, 24, 28,  124, 239, 247, 1,   240, 1,  19, 18,  15, 4,  27, 1, 122, 2,  23,
+	 1, 17, 7,  31, 1, 11, 2,   21,  19,  246, 238, 29,  17, 13, 236, 25, 58, 63, 8, 125},
+	{0,  201, 25,  231, 5,  221, 1, 3,   2,   414, 2,  241, 16, 225, 195, 492, 2, 412, 1,  240, 7, 224,
+	 98, 245, 1,   220, 96, 5,   9, 230, 101, 247, 1,  102, 1,  415, 24,  3,   2, 244, 3,  54,  3, 484,
+	 17, 114, 200, 493, 3,  413, 1, 4,   13,  113, 99, 485, 4,  111, 194, 243, 5, 29,  26, 31},
+	{0,  28, 12, 44, 3,  36, 20, 52, 2,  32, 16, 48, 8,  40, 24, 28, 1,  30, 14, 46, 6,  38,
+	 22, 54, 3,  34, 18, 50, 10, 42, 26, 30, 1,  29, 13, 45, 5,  37, 21, 53, 2,  33, 17, 49,
+	 9,  41, 25, 29, 1,  31, 15, 47, 7,  39, 23, 55, 4,  35, 19, 51, 11, 43, 27, 31}};
+
+static const uint8 vc1_cbpcy_p_bits[4][64] = {
+	{13, 13, 7, 13, 7, 13, 13, 12, 6, 13, 7, 12, 6, 8, 8, 8, 5, 7, 8,  12, 6, 8, 13, 12, 7, 13, 13, 12, 6, 8, 7, 7,
+	 6,  13, 8, 12, 7, 13, 13, 12, 7, 13, 8, 12, 5, 7, 7, 7, 6, 8, 13, 12, 6, 7, 8,  8,  5, 8,  8,  6,  3, 3, 3, 2},
+	{14, 13, 8,  13, 3,  13, 8, 13, 3, 7, 8, 13, 4,  13, 13, 13, 3,  13, 13, 13, 4,  8,
+	 13, 13, 5,  13, 13, 13, 5, 7,  8, 8, 3, 8,  14, 13, 5,  13, 13, 13, 4,  7,  13, 13,
+	 6,  13, 13, 13, 5,  13, 8, 13, 5, 8, 8, 13, 5,  13, 8,  13, 6,  6,  13, 7},
+	{13, 8, 6, 8, 4, 8,  13, 12, 4, 9, 8, 8, 5, 8, 8, 9, 5, 9, 10, 8,  4, 8, 7, 8, 6, 8, 7, 13, 4, 8, 7, 8,
+	 5,  7, 8, 9, 6, 13, 13, 8,  4, 6, 8, 9, 5, 7, 8, 9, 5, 9, 9,  13, 5, 7, 7, 9, 4, 7, 8, 8,  3, 5, 5, 5},
+	{9, 9, 9, 9, 2, 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 8, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8,
+	 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8}};
+
+/* Interlaced CBPCY VLC tables (Table 124 - Table 131) */
+static const uint16 vc1_icbpcy_p_codes[8][63] = {
+	{0x2F1A, 0x2F1B, 0x178C, 0x0090, 0x02A8, 0x02A9, 0x0BC7, 0x0091, 0x02AA, 0x02AB, 0x05E0, 0x004A, 0x0096,
+	 0x0097, 0x00BD, 0x0092, 0x02AC, 0x02AD, 0x05E1, 0x0098, 0x0132, 0x0133, 0x0179, 0x0134, 0x026A, 0x026B,
+	 0x02FC, 0x004E, 0x0040, 0x0041, 0x002B, 0x0093, 0x02AE, 0x02AF, 0x05E2, 0x0136, 0x026E, 0x026F, 0x02FD,
+	 0x009E, 0x013E, 0x013F, 0x017F, 0x0050, 0x0042, 0x0043, 0x002C, 0x0051, 0x00A4, 0x00A5, 0x00BE, 0x0053,
+	 0x0044, 0x0045, 0x002D, 0x0054, 0x0046, 0x0047, 0x002E, 0x0003, 0x0000, 0x0001, 0x0001},
+	{0x0041, 0x0042, 0x0100, 0x0043, 0x0088, 0x0089, 0x0101, 0x0045, 0x008C, 0x008D, 0x0102, 0x0010, 0x0022,
+	 0x0023, 0x0024, 0x0047, 0x0010, 0x0011, 0x0103, 0x0025, 0x0058, 0x0059, 0x005A, 0x005B, 0x005A, 0x005B,
+	 0x005C, 0x000C, 0x0030, 0x0031, 0x0019, 0x0009, 0x0014, 0x0015, 0x002C, 0x005C, 0x005D, 0x005E, 0x005F,
+	 0x0026, 0x005D, 0x005E, 0x005F, 0x000D, 0x0034, 0x0035, 0x001B, 0x0014, 0x0027, 0x002A, 0x002B, 0x000E,
+	 0x0038, 0x0039, 0x001D, 0x000F, 0x003C, 0x003D, 0x001F, 0x0005, 0x0009, 0x0000, 0x0003},
+	{0x0032, 0x0033, 0x001A, 0x0026, 0x00E4, 0x00E5, 0x01E6, 0x0027, 0x00E6, 0x00E7, 0x01E7, 0x000E, 0x0063,
+	 0x006C, 0x0077, 0x0028, 0x00E8, 0x00E9, 0x01E8, 0x007B, 0x00DA, 0x00DB, 0x00EC, 0x00F5, 0x01B8, 0x01B9,
+	 0x01DA, 0x0021, 0x004B, 0x0054, 0x002B, 0x0029, 0x00EA, 0x00EB, 0x01E9, 0x004A, 0x01BA, 0x01BB, 0x01DB,
+	 0x0020, 0x00DE, 0x00DF, 0x00F2, 0x0022, 0x0055, 0x0058, 0x002D, 0x000F, 0x0070, 0x0071, 0x0078, 0x0023,
+	 0x0059, 0x005C, 0x002F, 0x0024, 0x005D, 0x0062, 0x0030, 0x0002, 0x001F, 0x0006, 0x0000},
+	{0x0028, 0x0029, 0x009D, 0x0000, 0x01EA, 0x01EB, 0x01EC, 0x0001, 0x01ED, 0x01EE, 0x01EF, 0x0005, 0x00F0,
+	 0x00F1, 0x003B, 0x0002, 0x01F0, 0x01F1, 0x01F2, 0x003F, 0x015C, 0x015D, 0x0099, 0x0010, 0x03D0, 0x03D1,
+	 0x0130, 0x000F, 0x009E, 0x009F, 0x00FB, 0x0003, 0x01F3, 0x01F4, 0x01F5, 0x0011, 0x03D2, 0x03D3, 0x0131,
+	 0x0009, 0x015E, 0x015F, 0x009C, 0x0010, 0x00A8, 0x00A9, 0x0038, 0x0006, 0x00F2, 0x00F3, 0x004D, 0x0011,
+	 0x00AA, 0x00AB, 0x0039, 0x0012, 0x00AC, 0x00AD, 0x003A, 0x0006, 0x0016, 0x0017, 0x000E},
+	{0x003C, 0x003D, 0x001F, 0x000A, 0x0061, 0x0062, 0x0002, 0x000B, 0x0063, 0x0064, 0x0003, 0x0007, 0x0003,
+	 0x0004, 0x000B, 0x000C, 0x0065, 0x0066, 0x0004, 0x0012, 0x000A, 0x000B, 0x0014, 0x001B, 0x0018, 0x0019,
+	 0x0034, 0x002C, 0x0067, 0x0068, 0x0035, 0x000D, 0x0069, 0x006C, 0x0005, 0x0060, 0x001A, 0x001B, 0x0035,
+	 0x0013, 0x000E, 0x000F, 0x0015, 0x002D, 0x006D, 0x006E, 0x0038, 0x0008, 0x0008, 0x0009, 0x000C, 0x002E,
+	 0x006F, 0x0072, 0x003A, 0x002F, 0x0073, 0x0000, 0x003B, 0x0007, 0x0014, 0x0015, 0x0004},
+	{0x0038, 0x0039, 0x009D, 0x000A, 0x0091, 0x0092, 0x0093, 0x000B, 0x0094, 0x0095, 0x0096, 0x0003, 0x00EE,
+	 0x00EF, 0x0036, 0x000C, 0x0097, 0x0098, 0x0099, 0x0008, 0x01E4, 0x01E5, 0x006A, 0x0018, 0x03CC, 0x03CD,
+	 0x00D6, 0x000E, 0x009E, 0x009F, 0x00F5, 0x000D, 0x009A, 0x009B, 0x009C, 0x0019, 0x03CE, 0x03CF, 0x00D7,
+	 0x0009, 0x01E8, 0x01E9, 0x0090, 0x000F, 0x00E8, 0x00E9, 0x00F6, 0x0005, 0x00F0, 0x00F1, 0x0037, 0x0010,
+	 0x00EA, 0x00EB, 0x00F7, 0x0011, 0x00EC, 0x00ED, 0x0034, 0x0000, 0x003E, 0x003F, 0x0002},
+	{0x003C, 0x003D, 0x01CF, 0x0000, 0x00BF, 0x00E0, 0x01FC, 0x0001, 0x00E1, 0x00E2, 0x01FD, 0x0009, 0x01F1,
+	 0x01F2, 0x01F3, 0x0002, 0x00E3, 0x00E4, 0x01FE, 0x0011, 0x03EE, 0x03EF, 0x03F0, 0x0021, 0x07E2, 0x07E3,
+	 0x07E4, 0x0018, 0x03F7, 0x03FE, 0x03FF, 0x0003, 0x00E5, 0x00E6, 0x0080, 0x002E, 0x07E5, 0x07E6, 0x07E7,
+	 0x0016, 0x03F4, 0x03F5, 0x03F6, 0x0019, 0x0102, 0x0103, 0x0104, 0x000A, 0x01F4, 0x01F5, 0x01F6, 0x001A,
+	 0x0105, 0x0106, 0x0107, 0x001B, 0x0178, 0x0179, 0x01CE, 0x001D, 0x00BD, 0x00BE, 0x01F0},
+	{0x0003, 0x0004, 0x01B6, 0x0004, 0x002E, 0x002F, 0x000E, 0x0005, 0x0030, 0x0031, 0x000F, 0x0003, 0x000A,
+	 0x000B, 0x0014, 0x0006, 0x0032, 0x0033, 0x0010, 0x0005, 0x0030, 0x0031, 0x0032, 0x0009, 0x0066, 0x0067,
+	 0x0068, 0x001D, 0x01B7, 0x01B8, 0x01B9, 0x0007, 0x0034, 0x0035, 0x0011, 0x0016, 0x0069, 0x006A, 0x006B,
+	 0x000A, 0x0036, 0x0037, 0x00D8, 0x001E, 0x01BA, 0x01BB, 0x01BC, 0x0004, 0x0015, 0x0016, 0x0017, 0x001F,
+	 0x01BD, 0x01BE, 0x01BF, 0x0000, 0x0010, 0x0011, 0x0012, 0x001C, 0x00D9, 0x00DA, 0x0013}};
+
+static const uint8 vc1_icbpcy_p_bits[8][63] = {
+	{15, 15, 14, 9,  11, 11, 13, 9, 11, 11, 12, 8, 9, 9, 9, 9, 11, 11, 12, 9, 10, 10, 10, 10, 11, 11, 11, 8, 8, 8, 7, 9,
+	 11, 11, 12, 10, 11, 11, 11, 9, 10, 10, 10, 8, 8, 8, 7, 8, 9,  9,  9,  8, 8,  8,  7,  8,  8,  8,  7,  3, 3, 3, 1},
+	{7, 7, 9, 7, 8, 8, 9, 7, 8, 8, 9, 6, 7, 7, 7, 7, 7, 7, 9, 7, 8, 8, 8, 8, 9, 9, 9, 6, 7, 7, 6, 6,
+	 7, 7, 8, 8, 9, 9, 9, 7, 8, 8, 8, 6, 7, 7, 6, 6, 7, 7, 7, 6, 7, 7, 6, 6, 7, 7, 6, 3, 4, 3, 2},
+	{6, 6, 5, 6, 8, 8, 9, 6, 8, 8, 9, 5, 7, 7, 7, 6, 8, 8, 9, 7, 8, 8, 8, 8, 9, 9, 9, 6, 7, 7, 6, 6,
+	 8, 8, 9, 7, 9, 9, 9, 6, 8, 8, 8, 6, 7, 7, 6, 5, 7, 7, 7, 6, 7, 7, 6, 6, 7, 7, 6, 3, 5, 4, 2},
+	{6, 6, 8, 4, 9,  9,  9, 4, 9, 9, 9, 4, 8, 8, 7, 4, 9, 9, 9, 6, 9, 9, 8, 6, 10, 10, 9, 5, 8, 8, 8, 4,
+	 9, 9, 9, 6, 10, 10, 9, 5, 9, 9, 8, 5, 8, 8, 7, 4, 8, 8, 7, 5, 8, 8, 7, 5, 8,  8,  7, 3, 5, 5, 4},
+	{6, 6, 5, 5, 7, 7, 7, 5, 7, 7, 7, 5, 6, 6, 6, 5, 7, 7, 7, 6, 7, 7, 7, 7, 8, 8, 8, 6, 7, 7, 6, 5,
+	 7, 7, 7, 7, 8, 8, 8, 6, 7, 7, 7, 6, 7, 7, 6, 5, 6, 6, 6, 6, 7, 7, 6, 6, 7, 6, 6, 4, 5, 5, 3},
+	{6, 6, 8, 4, 8,  8,  8, 4, 8, 8, 8, 4, 8, 8, 7, 4, 8, 8, 8, 5, 9, 9, 8, 6, 10, 10, 9, 5, 8, 8, 8, 4,
+	 8, 8, 8, 6, 10, 10, 9, 5, 9, 9, 8, 5, 8, 8, 8, 4, 8, 8, 7, 5, 8, 8, 8, 5, 8,  8,  7, 3, 6, 6, 4},
+	{6, 6, 9, 3, 8,  8,  9,  3, 8,  8,  9,  4, 9, 9, 9, 3, 8, 8, 9, 5, 10, 10, 10, 6, 11, 11, 11, 5, 10, 10, 10, 3,
+	 8, 8, 8, 6, 11, 11, 11, 5, 10, 10, 10, 5, 9, 9, 9, 4, 9, 9, 9, 5, 9,  9,  9,  5, 9,  9,  9,  5, 8,  8,  9},
+	{6, 6, 10, 3, 7,  7,  7,  3, 7, 7, 7, 4, 8,  8,  8,  3, 7, 7, 7, 5, 9,  9,  9,  6, 10, 10, 10, 6, 10, 10, 10, 3,
+	 7, 7, 7,  6, 10, 10, 10, 5, 9, 9, 9, 6, 10, 10, 10, 4, 8, 8, 8, 6, 10, 10, 10, 5, 9,  9,  9,  6, 9,  9,  9}};
+
+/* MacroBlock Transform Type: 7.1.3.11, p89
+ * 8x8:B
+ * 8x4:B:btm  8x4:B:top  8x4:B:both,
+ * 4x8:B:right  4x8:B:left  4x8:B:both
+ * 4x4:B  8x8:MB
+ * 8x4:MB:btm  8x4:MB:top  8x4,MB,both
+ * 4x8,MB,right  4x8,MB,left
+ * 4x4,MB                               */
+static const uint16 vc1_ttmb_codes[3][16] = {{0x0003, 0x002E, 0x005F, 0x0000, 0x0016, 0x0015, 0x0001, 0x0004, 0x0014,
+											  0x02F1, 0x0179, 0x017B, 0x0BC0, 0x0BC1, 0x05E1, 0x017A},
+											 {0x0006, 0x0006, 0x0003, 0x0007, 0x000F, 0x000E, 0x0000, 0x0002, 0x0002,
+											  0x0014, 0x0011, 0x000B, 0x0009, 0x0021, 0x0015, 0x0020},
+											 {0x0006, 0x0000, 0x000E, 0x0005, 0x0002, 0x0003, 0x0003, 0x000F, 0x0002,
+											  0x0081, 0x0021, 0x0009, 0x0101, 0x0041, 0x0011, 0x0100}};
+
+static const uint8 vc1_ttmb_bits[3][16] = {{2, 6, 7, 2, 5, 5, 2, 3, 5, 10, 9, 9, 12, 12, 11, 9},
+										   {3, 4, 4, 4, 4, 4, 3, 3, 2, 7, 7, 6, 6, 8, 7, 8},
+										   {3, 3, 4, 5, 3, 3, 4, 4, 2, 10, 8, 6, 11, 9, 7, 11}};
+
+/* TTBLK (Transform Type per Block) tables */
+static const uint8 vc1_ttblk_codes[3][8] = {
+	{0, 1, 3, 5, 16, 17, 18, 19}, {3, 0, 1, 2, 3, 5, 8, 9}, {1, 0, 1, 4, 6, 7, 10, 11}};
+static const uint8 vc1_ttblk_bits[3][8] = {
+	{2, 2, 2, 3, 5, 5, 5, 5}, {2, 3, 3, 3, 3, 3, 4, 4}, {2, 3, 3, 3, 3, 3, 4, 4}};
+
+/* SUBBLKPAT tables, p93-94, reordered */
+static const uint8 vc1_subblkpat_codes[3][15] = {{14, 12, 7, 11, 9, 26, 2, 10, 27, 8, 0, 6, 1, 15, 1},
+												 {14, 0, 8, 15, 10, 4, 23, 13, 5, 9, 25, 3, 24, 22, 1},
+												 {5, 6, 2, 2, 8, 0, 28, 3, 1, 3, 29, 1, 19, 18, 15}};
+static const uint8 vc1_subblkpat_bits[3][15] = {{5, 5, 5, 5, 5, 6, 4, 5, 6, 5, 4, 5, 4, 5, 1},
+												{4, 3, 4, 4, 4, 5, 5, 4, 5, 4, 5, 4, 5, 5, 2},
+												{3, 3, 4, 3, 4, 5, 5, 3, 5, 4, 5, 4, 5, 5, 4}};
+
+/* MV differential tables, p265 */
+static const uint16 vc1_mv_diff_codes[4][73] =
+	{
+		{
+			0,  2,   3,   8,   576, 3,   2,   6,   5,   577, 578, 7,   8,   9,   40,  19,  37,  82, 21,
+			22, 23,  579, 580, 166, 96,  167, 49,  194, 195, 581, 582, 583, 292, 293, 294, 13,  2,  7,
+			24, 50,  102, 295, 13,  7,   8,   18,  50,  103, 38,  20,  21,  22,  39,  204, 103, 23, 24,
+			25, 104, 410, 105, 106, 107, 108, 109, 220, 411, 442, 222, 443, 446, 447, 7 /* 73 elements */
+		},
+		{
+			0,    4,    5,    3,    4,    3,    4,    5,    20,   6,    21,   44,   45,   46,   3008,
+			95,   112,  113,  57,   3009, 3010, 116,  117,  3011, 118,  3012, 3013, 3014, 3015, 3016,
+			3017, 3018, 3019, 3020, 3021, 3022, 1,    4,    15,   160,  161,  41,   6,    11,   42,
+			162,  43,   119,  56,   57,   58,   163,  236,  237,  3023, 119,  120,  242,  122,  486,
+			1512, 487,  246,  494,  1513, 495,  1514, 1515, 1516, 1517, 1518, 1519, 31 /* 73 elements */
+		},
+		{
+			0,   512, 513, 514, 515, 2,   3,   258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269,
+			270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 1,   5,
+			287, 288, 289, 290, 6,   7,   291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303,
+			304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319 /* 73 elements */
+		},
+		{
+			0,  1,   1,   2,  3,   4,  1,  5,  4,   3,   5,   8,   6,   9,   10,  11,  12, 7,  104,
+			14, 105, 4,   10, 15,  11, 6,  14, 8,   106, 107, 108, 15,  109, 9,   55,  10, 1,  2,
+			1,  2,   3,   12, 6,   2,  6,  7,  28,  7,   15,  8,   5,   18,  29,  152, 77, 24, 25,
+			26, 39,  108, 13, 109, 55, 56, 57, 116, 11,  153, 234, 235, 118, 119, 15 /* 73 elements */
+		}};
+static const uint8 vc1_mv_diff_bits[4][73] = {
+	{
+		6,  7, 7,  8,  14, 6,  5,  6,  7,  14, 14, 6, 6, 6, 8, 9, 10, 9, 7, 7, 7, 14, 14, 10, 9,
+		10, 8, 10, 10, 14, 14, 14, 13, 13, 13, 6,  3, 5, 6, 8, 9, 13, 5, 4, 4, 5, 7,  9,  6,  5,
+		5,  5, 6,  9,  8,  5,  5,  5,  7,  10, 7,  7, 7, 7, 7, 8, 10, 9, 8, 9, 9, 9,  3 /* 73 elements */
+	},
+	{
+		5,  7,  7,  6,  6,  5,  5,  6,  7,  5,  7,  8, 8, 8, 14, 9, 9,  9,  8,  14, 14, 9,  9, 14, 9,
+		14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 2, 3, 6, 8,  8, 6,  3,  4,  6,  8,  6,  9, 6,  6,
+		6,  8,  8,  8,  14, 7,  7,  8,  7,  9,  13, 9, 8, 9, 13, 9, 13, 13, 13, 13, 13, 13, 5 /* 73 elements */
+
+	},
+	{
+		3,  12, 12, 12, 12, 3,  4,  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, 1,  5,  11, 11, 11, 11, 4,  4,  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 /* 73 elements */
+	},
+	{
+		15, 11, 15, 15, 15, 15, 12, 15, 12, 11, 12, 12, 15, 12, 12, 12, 12, 15, 15, 12, 15, 10, 11, 12, 11,
+		10, 11, 10, 15, 15, 15, 11, 15, 10, 14, 10, 4,  4,  5,  7,  8,  9,  5,  3,  4,  5,  6,  8,  5,  4,
+		3,  5,  6,  8,  7,  5,  5,  5,  6,  7,  9,  7,  6,  6,  6,  7,  10, 8,  8,  8,  7,  7,  4 /* 73 elements */
+	}};
+
+static const uint32 vc1_ac_tables[AC_MODES][186][2] = {
+	{{0x0001, 2},  {0x0005, 3},  {0x000D, 4},  {0x0012, 5},  {0x000E, 6},  {0x0015, 7},  {0x0013, 8},  {0x003F, 8},
+	 {0x004B, 9},  {0x011F, 9},  {0x00B8, 10}, {0x03E3, 10}, {0x0172, 11}, {0x024D, 12}, {0x03DA, 12}, {0x02DD, 13},
+	 {0x1F55, 13}, {0x05B9, 14}, {0x3EAE, 14}, {0x0000, 4},  {0x0010, 5},  {0x0008, 7},  {0x0020, 8},  {0x0029, 9},
+	 {0x01F4, 9},  {0x0233, 10}, {0x01E0, 11}, {0x012A, 12}, {0x03DD, 12}, {0x050A, 13}, {0x1F29, 13}, {0x0A42, 14},
+	 {0x1272, 15}, {0x1737, 15}, {0x0003, 5},  {0x0011, 7},  {0x00C4, 8},  {0x004B, 10}, {0x00B4, 11}, {0x07D4, 11},
+	 {0x0345, 12}, {0x02D7, 13}, {0x07BF, 13}, {0x0938, 14}, {0x0BBB, 14}, {0x095E, 15}, {0x0013, 5},  {0x0078, 7},
+	 {0x0069, 9},  {0x0232, 10}, {0x0461, 11}, {0x03EC, 12}, {0x0520, 13}, {0x1F2A, 13}, {0x3E50, 14}, {0x3E51, 14},
+	 {0x1486, 15}, {0x000C, 6},  {0x0024, 9},  {0x0094, 11}, {0x08C0, 12}, {0x0F09, 14}, {0x1EF0, 15}, {0x003D, 6},
+	 {0x0053, 9},  {0x01A0, 11}, {0x02D6, 13}, {0x0F08, 14}, {0x0013, 7},  {0x007C, 9},  {0x07C1, 11}, {0x04AC, 14},
+	 {0x001B, 7},  {0x00A0, 10}, {0x0344, 12}, {0x0F79, 14}, {0x0079, 7},  {0x03E1, 10}, {0x02D4, 13}, {0x2306, 14},
+	 {0x0021, 8},  {0x023C, 10}, {0x0FAE, 12}, {0x23DE, 14}, {0x0035, 8},  {0x0175, 11}, {0x07B3, 13}, {0x00C5, 8},
+	 {0x0174, 11}, {0x0785, 13}, {0x0048, 9},  {0x01A3, 11}, {0x049E, 13}, {0x002C, 9},  {0x00FA, 10}, {0x07D6, 11},
+	 {0x0092, 10}, {0x05CC, 13}, {0x1EF1, 15}, {0x00A3, 10}, {0x03ED, 12}, {0x093E, 14}, {0x01E2, 11}, {0x1273, 15},
+	 {0x07C4, 11}, {0x1487, 15}, {0x0291, 12}, {0x0293, 12}, {0x0F8A, 12}, {0x0509, 13}, {0x0508, 13}, {0x078D, 13},
+	 {0x07BE, 13}, {0x078C, 13}, {0x04AE, 14}, {0x0BBA, 14}, {0x2307, 14}, {0x0B9A, 14}, {0x1736, 15}, {0x000E, 4},
+	 {0x0045, 7},  {0x01F3, 9},  {0x047A, 11}, {0x05DC, 13}, {0x23DF, 14}, {0x0019, 5},  {0x0028, 9},  {0x0176, 11},
+	 {0x049D, 13}, {0x23DD, 14}, {0x0030, 6},  {0x00A2, 10}, {0x02EF, 12}, {0x05B8, 14}, {0x003F, 6},  {0x00A5, 10},
+	 {0x03DB, 12}, {0x093F, 14}, {0x0044, 7},  {0x07CB, 11}, {0x095F, 15}, {0x0063, 7},  {0x03C3, 12}, {0x0015, 8},
+	 {0x08F6, 12}, {0x0017, 8},  {0x0498, 13}, {0x002C, 8},  {0x07B2, 13}, {0x002F, 8},  {0x1F54, 13}, {0x008D, 8},
+	 {0x07BD, 13}, {0x008E, 8},  {0x1182, 13}, {0x00FB, 8},  {0x050B, 13}, {0x002D, 8},  {0x07C0, 11}, {0x0079, 9},
+	 {0x1F5F, 13}, {0x007A, 9},  {0x1F56, 13}, {0x0231, 10}, {0x03E4, 10}, {0x01A1, 11}, {0x0143, 11}, {0x01F7, 11},
+	 {0x016F, 12}, {0x0292, 12}, {0x02E7, 12}, {0x016C, 12}, {0x016D, 12}, {0x03DC, 12}, {0x0F8B, 12}, {0x0499, 13},
+	 {0x03D8, 12}, {0x078E, 13}, {0x02D5, 13}, {0x1F5E, 13}, {0x1F2B, 13}, {0x078F, 13}, {0x04AD, 14}, {0x3EAF, 14},
+	 {0x23DC, 14}, {0x004A, 9}},
+	{{0x0000, 3},  {0x0003, 4},  {0x000B, 5},  {0x0014, 6},  {0x003F, 6},  {0x005D, 7},  {0x00A2, 8},  {0x00AC, 9},
+	 {0x016E, 9},  {0x020A, 10}, {0x02E2, 10}, {0x0432, 11}, {0x05C9, 11}, {0x0827, 12}, {0x0B54, 12}, {0x04E6, 13},
+	 {0x105F, 13}, {0x172A, 13}, {0x20B2, 14}, {0x2D4E, 14}, {0x39F0, 14}, {0x4175, 15}, {0x5A9E, 15}, {0x0004, 4},
+	 {0x001E, 5},  {0x0042, 7},  {0x00B6, 8},  {0x0173, 9},  {0x0395, 10}, {0x072E, 11}, {0x0B94, 12}, {0x16A4, 13},
+	 {0x20B3, 14}, {0x2E45, 14}, {0x0005, 5},  {0x0040, 7},  {0x0049, 9},  {0x028F, 10}, {0x05CB, 11}, {0x048A, 13},
+	 {0x09DD, 14}, {0x73E2, 15}, {0x0018, 5},  {0x0025, 8},  {0x008A, 10}, {0x051B, 11}, {0x0E5F, 12}, {0x09C9, 14},
+	 {0x139C, 15}, {0x0029, 6},  {0x004F, 9},  {0x0412, 11}, {0x048D, 13}, {0x2E41, 14}, {0x0038, 6},  {0x010E, 9},
+	 {0x05A8, 11}, {0x105C, 13}, {0x39F2, 14}, {0x0058, 7},  {0x021F, 10}, {0x0E7E, 12}, {0x39FF, 14}, {0x0023, 8},
+	 {0x02E3, 10}, {0x04E5, 13}, {0x2E40, 14}, {0x00A1, 8},  {0x05BE, 11}, {0x09C8, 14}, {0x0083, 8},  {0x013A, 11},
+	 {0x1721, 13}, {0x0044, 9},  {0x0276, 12}, {0x39F6, 14}, {0x008B, 10}, {0x04EF, 13}, {0x5A9B, 15}, {0x0208, 10},
+	 {0x1CFE, 13}, {0x0399, 10}, {0x1CB4, 13}, {0x039E, 10}, {0x39F3, 14}, {0x05AB, 11}, {0x73E3, 15}, {0x0737, 11},
+	 {0x5A9F, 15}, {0x082D, 12}, {0x0E69, 12}, {0x0E68, 12}, {0x0433, 11}, {0x0B7B, 12}, {0x2DF8, 14}, {0x2E56, 14},
+	 {0x2E57, 14}, {0x39F7, 14}, {0x51A5, 15}, {0x0003, 3},  {0x002A, 6},  {0x00E4, 8},  {0x028E, 10}, {0x0735, 11},
+	 {0x1058, 13}, {0x1CFA, 13}, {0x2DF9, 14}, {0x4174, 15}, {0x0009, 4},  {0x0054, 8},  {0x0398, 10}, {0x048B, 13},
+	 {0x139D, 15}, {0x000D, 4},  {0x00AD, 9},  {0x0826, 12}, {0x2D4C, 14}, {0x0011, 5},  {0x016B, 9},  {0x0B7F, 12},
+	 {0x51A4, 15}, {0x0019, 5},  {0x021B, 10}, {0x16FD, 13}, {0x001D, 5},  {0x0394, 10}, {0x28D3, 14}, {0x002B, 6},
+	 {0x05BC, 11}, {0x5A9A, 15}, {0x002F, 6},  {0x0247, 12}, {0x0010, 7},  {0x0A35, 12}, {0x003E, 6},  {0x0B7A, 12},
+	 {0x0059, 7},  {0x105E, 13}, {0x0026, 8},  {0x09CF, 14}, {0x0055, 8},  {0x1CB5, 13}, {0x0057, 8},  {0x0E5B, 12},
+	 {0x00A0, 8},  {0x1468, 13}, {0x0170, 9},  {0x0090, 10}, {0x01CE, 9},  {0x021A, 10}, {0x0218, 10}, {0x0168, 9},
+	 {0x021E, 10}, {0x0244, 12}, {0x0736, 11}, {0x0138, 11}, {0x0519, 11}, {0x0E5E, 12}, {0x072C, 11}, {0x0B55, 12},
+	 {0x09DC, 14}, {0x20BB, 14}, {0x048C, 13}, {0x1723, 13}, {0x2E44, 14}, {0x16A5, 13}, {0x0518, 11}, {0x39FE, 14},
+	 {0x0169, 9}},
+	{{0x0001, 2},  {0x0006, 3},  {0x000F, 4},  {0x0016, 5},  {0x0020, 6},  {0x0018, 7},  {0x0008, 8},  {0x009A, 8},
+	 {0x0056, 9},  {0x013E, 9},  {0x00F0, 10}, {0x03A5, 10}, {0x0077, 11}, {0x01EF, 11}, {0x009A, 12}, {0x005D, 13},
+	 {0x0001, 4},  {0x0011, 5},  {0x0002, 7},  {0x000B, 8},  {0x0012, 9},  {0x01D6, 9},  {0x027E, 10}, {0x0191, 11},
+	 {0x00EA, 12}, {0x03DC, 12}, {0x013B, 13}, {0x0004, 5},  {0x0014, 7},  {0x009E, 8},  {0x0009, 10}, {0x01AC, 11},
+	 {0x01E2, 11}, {0x03CA, 12}, {0x005F, 13}, {0x0017, 5},  {0x004E, 7},  {0x005E, 9},  {0x00F3, 10}, {0x01AD, 11},
+	 {0x00EC, 12}, {0x05F0, 13}, {0x000E, 6},  {0x00E1, 8},  {0x03A4, 10}, {0x009C, 12}, {0x013D, 13}, {0x003B, 6},
+	 {0x001C, 9},  {0x0014, 11}, {0x09BE, 12}, {0x0006, 7},  {0x007A, 9},  {0x0190, 11}, {0x0137, 13}, {0x001B, 7},
+	 {0x0008, 10}, {0x075C, 11}, {0x0071, 7},  {0x00D7, 10}, {0x09BF, 12}, {0x0007, 8},  {0x00AF, 10}, {0x04CC, 11},
+	 {0x0034, 8},  {0x0265, 10}, {0x009F, 12}, {0x00E0, 8},  {0x0016, 11}, {0x0327, 12}, {0x0015, 9},  {0x017D, 11},
+	 {0x0EBB, 12}, {0x0014, 9},  {0x00F6, 10}, {0x01E4, 11}, {0x00CB, 10}, {0x099D, 12}, {0x00CA, 10}, {0x02FC, 12},
+	 {0x017F, 11}, {0x04CD, 11}, {0x02FD, 12}, {0x04FE, 11}, {0x013A, 13}, {0x000A, 4},  {0x0042, 7},  {0x01D3, 9},
+	 {0x04DD, 11}, {0x0012, 5},  {0x00E8, 8},  {0x004C, 11}, {0x0136, 13}, {0x0039, 6},  {0x0264, 10}, {0x0EBA, 12},
+	 {0x0000, 7},  {0x00AE, 10}, {0x099C, 12}, {0x001F, 7},  {0x04DE, 11}, {0x0043, 7},  {0x04DC, 11}, {0x0003, 8},
+	 {0x03CB, 12}, {0x0006, 8},  {0x099E, 12}, {0x002A, 8},  {0x05F1, 13}, {0x000F, 8},  {0x09FE, 12}, {0x0033, 8},
+	 {0x09FF, 12}, {0x0098, 8},  {0x099F, 12}, {0x00EA, 8},  {0x013C, 13}, {0x002E, 8},  {0x0192, 11}, {0x0136, 9},
+	 {0x006A, 9},  {0x0015, 11}, {0x03AF, 10}, {0x01E3, 11}, {0x0074, 11}, {0x00EB, 12}, {0x02F9, 12}, {0x005C, 13},
+	 {0x00ED, 12}, {0x03DD, 12}, {0x0326, 12}, {0x005E, 13}, {0x0016, 7}},
+	{{0x0004, 3},  {0x0014, 5},  {0x0017, 7},  {0x007F, 8},  {0x0154, 9},  {0x01F2, 10}, {0x00BF, 11}, {0x0065, 12},
+	 {0x0AAA, 12}, {0x0630, 13}, {0x1597, 13}, {0x03B7, 14}, {0x2B22, 14}, {0x0BE6, 15}, {0x000B, 4},  {0x0037, 7},
+	 {0x0062, 9},  {0x0007, 11}, {0x0166, 12}, {0x00CE, 13}, {0x1590, 13}, {0x05F6, 14}, {0x0BE7, 15}, {0x0007, 5},
+	 {0x006D, 8},  {0x0003, 11}, {0x031F, 12}, {0x05F2, 14}, {0x0002, 6},  {0x0061, 9},  {0x0055, 12}, {0x01DF, 14},
+	 {0x001A, 6},  {0x001E, 10}, {0x0AC9, 12}, {0x2B23, 14}, {0x001E, 6},  {0x001F, 10}, {0x0AC3, 12}, {0x2B2B, 14},
+	 {0x0006, 7},  {0x0004, 11}, {0x02F8, 13}, {0x0019, 7},  {0x0006, 11}, {0x063D, 13}, {0x0057, 7},  {0x0182, 11},
+	 {0x2AA2, 14}, {0x0004, 8},  {0x0180, 11}, {0x059C, 14}, {0x007D, 8},  {0x0164, 12}, {0x076D, 15}, {0x0002, 9},
+	 {0x018D, 11}, {0x1581, 13}, {0x00AD, 8},  {0x0060, 12}, {0x0C67, 14}, {0x001C, 9},  {0x00EE, 13}, {0x0003, 9},
+	 {0x02CF, 13}, {0x00D9, 9},  {0x1580, 13}, {0x0002, 11}, {0x0183, 11}, {0x0057, 12}, {0x0061, 12}, {0x0031, 11},
+	 {0x0066, 12}, {0x0631, 13}, {0x0632, 13}, {0x00AC, 13}, {0x031D, 12}, {0x0076, 12}, {0x003A, 11}, {0x0165, 12},
+	 {0x0C66, 14}, {0x0003, 2},  {0x0054, 7},  {0x02AB, 10}, {0x0016, 13}, {0x05F7, 14}, {0x0005, 4},  {0x00F8, 9},
+	 {0x0AA9, 12}, {0x005F, 15}, {0x0004, 4},  {0x001C, 10}, {0x1550, 13}, {0x0004, 5},  {0x0077, 11}, {0x076C, 15},
+	 {0x000E, 5},  {0x000A, 12}, {0x000C, 5},  {0x0562, 11}, {0x0004, 6},  {0x031C, 12}, {0x0006, 6},  {0x00C8, 13},
+	 {0x000D, 6},  {0x01DA, 13}, {0x0007, 6},  {0x00C9, 13}, {0x0001, 7},  {0x002E, 14}, {0x0014, 7},  {0x1596, 13},
+	 {0x000A, 7},  {0x0AC2, 12}, {0x0016, 7},  {0x015B, 14}, {0x0015, 7},  {0x015A, 14}, {0x000F, 8},  {0x005E, 15},
+	 {0x007E, 8},  {0x00AB, 8},  {0x002D, 9},  {0x00D8, 9},  {0x000B, 9},  {0x0014, 10}, {0x02B3, 10}, {0x01F3, 10},
+	 {0x003A, 10}, {0x0000, 10}, {0x0058, 10}, {0x002E, 9},  {0x005E, 10}, {0x0563, 11}, {0x00EC, 12}, {0x0054, 12},
+	 {0x0AC1, 12}, {0x1556, 13}, {0x02FA, 13}, {0x0181, 11}, {0x1557, 13}, {0x059D, 14}, {0x2AA3, 14}, {0x2B2A, 14},
+	 {0x01DE, 14}, {0x063C, 13}, {0x00CF, 13}, {0x1594, 13}, {0x000D, 9}},
+	{{0x0002, 2},  {0x0006, 3},  {0x000F, 4},  {0x000D, 5},  {0x000C, 5},  {0x0015, 6},  {0x0013, 6},  {0x0012, 6},
+	 {0x0017, 7},  {0x001F, 8},  {0x001E, 8},  {0x001D, 8},  {0x0025, 9},  {0x0024, 9},  {0x0023, 9},  {0x0021, 9},
+	 {0x0021, 10}, {0x0020, 10}, {0x000F, 10}, {0x000E, 10}, {0x0007, 11}, {0x0006, 11}, {0x0020, 11}, {0x0021, 11},
+	 {0x0050, 12}, {0x0051, 12}, {0x0052, 12}, {0x000E, 4},  {0x0014, 6},  {0x0016, 7},  {0x001C, 8},  {0x0020, 9},
+	 {0x001F, 9},  {0x000D, 10}, {0x0022, 11}, {0x0053, 12}, {0x0055, 12}, {0x000B, 5},  {0x0015, 7},  {0x001E, 9},
+	 {0x000C, 10}, {0x0056, 12}, {0x0011, 6},  {0x001B, 8},  {0x001D, 9},  {0x000B, 10}, {0x0010, 6},  {0x0022, 9},
+	 {0x000A, 10}, {0x000D, 6},  {0x001C, 9},  {0x0008, 10}, {0x0012, 7},  {0x001B, 9},  {0x0054, 12}, {0x0014, 7},
+	 {0x001A, 9},  {0x0057, 12}, {0x0019, 8},  {0x0009, 10}, {0x0018, 8},  {0x0023, 11}, {0x0017, 8},  {0x0019, 9},
+	 {0x0018, 9},  {0x0007, 10}, {0x0058, 12}, {0x0007, 4},  {0x000C, 6},  {0x0016, 8},  {0x0017, 9},  {0x0006, 10},
+	 {0x0005, 11}, {0x0004, 11}, {0x0059, 12}, {0x000F, 6},  {0x0016, 9},  {0x0005, 10}, {0x000E, 6},  {0x0004, 10},
+	 {0x0011, 7},  {0x0024, 11}, {0x0010, 7},  {0x0025, 11}, {0x0013, 7},  {0x005A, 12}, {0x0015, 8},  {0x005B, 12},
+	 {0x0014, 8},  {0x0013, 8},  {0x001A, 8},  {0x0015, 9},  {0x0014, 9},  {0x0013, 9},  {0x0012, 9},  {0x0011, 9},
+	 {0x0026, 11}, {0x0027, 11}, {0x005C, 12}, {0x005D, 12}, {0x005E, 12}, {0x005F, 12}, {0x0003, 7}},
+	{{0x0002, 2},  {0x000F, 4},  {0x0015, 6},  {0x0017, 7},  {0x001F, 8},  {0x0025, 9},  {0x0024, 9},  {0x0021, 10},
+	 {0x0020, 10}, {0x0007, 11}, {0x0006, 11}, {0x0020, 11}, {0x0006, 3},  {0x0014, 6},  {0x001E, 8},  {0x000F, 10},
+	 {0x0021, 11}, {0x0050, 12}, {0x000E, 4},  {0x001D, 8},  {0x000E, 10}, {0x0051, 12}, {0x000D, 5},  {0x0023, 9},
+	 {0x000D, 10}, {0x000C, 5},  {0x0022, 9},  {0x0052, 12}, {0x000B, 5},  {0x000C, 10}, {0x0053, 12}, {0x0013, 6},
+	 {0x000B, 10}, {0x0054, 12}, {0x0012, 6},  {0x000A, 10}, {0x0011, 6},  {0x0009, 10}, {0x0010, 6},  {0x0008, 10},
+	 {0x0016, 7},  {0x0055, 12}, {0x0015, 7},  {0x0014, 7},  {0x001C, 8},  {0x001B, 8},  {0x0021, 9},  {0x0020, 9},
+	 {0x001F, 9},  {0x001E, 9},  {0x001D, 9},  {0x001C, 9},  {0x001B, 9},  {0x001A, 9},  {0x0022, 11}, {0x0023, 11},
+	 {0x0056, 12}, {0x0057, 12}, {0x0007, 4},  {0x0019, 9},  {0x0005, 11}, {0x000F, 6},  {0x0004, 11}, {0x000E, 6},
+	 {0x000D, 6},  {0x000C, 6},  {0x0013, 7},  {0x0012, 7},  {0x0011, 7},  {0x0010, 7},  {0x001A, 8},  {0x0019, 8},
+	 {0x0018, 8},  {0x0017, 8},  {0x0016, 8},  {0x0015, 8},  {0x0014, 8},  {0x0013, 8},  {0x0018, 9},  {0x0017, 9},
+	 {0x0016, 9},  {0x0015, 9},  {0x0014, 9},  {0x0013, 9},  {0x0012, 9},  {0x0011, 9},  {0x0007, 10}, {0x0006, 10},
+	 {0x0005, 10}, {0x0004, 10}, {0x0024, 11}, {0x0025, 11}, {0x0026, 11}, {0x0027, 11}, {0x0058, 12}, {0x0059, 12},
+	 {0x005A, 12}, {0x005B, 12}, {0x005C, 12}, {0x005D, 12}, {0x005E, 12}, {0x005F, 12}, {0x0003, 7}},
+	{{0x0000, 2},  {0x0003, 3},  {0x000D, 4},  {0x0005, 4},  {0x001C, 5},  {0x0016, 5},  {0x003F, 6},  {0x003A, 6},
+	 {0x002E, 6},  {0x0022, 6},  {0x007B, 7},  {0x0067, 7},  {0x005F, 7},  {0x0047, 7},  {0x0026, 7},  {0x00EF, 8},
+	 {0x00CD, 8},  {0x00C1, 8},  {0x00A9, 8},  {0x004F, 8},  {0x01F2, 9},  {0x01DD, 9},  {0x0199, 9},  {0x0185, 9},
+	 {0x015D, 9},  {0x011B, 9},  {0x03EF, 10}, {0x03E1, 10}, {0x03C8, 10}, {0x0331, 10}, {0x0303, 10}, {0x02F1, 10},
+	 {0x02A0, 10}, {0x0233, 10}, {0x0126, 10}, {0x07C0, 11}, {0x076F, 11}, {0x076C, 11}, {0x0661, 11}, {0x0604, 11},
+	 {0x0572, 11}, {0x0551, 11}, {0x046A, 11}, {0x0274, 11}, {0x0F27, 12}, {0x0F24, 12}, {0x0EDB, 12}, {0x0C8E, 12},
+	 {0x0C0B, 12}, {0x0C0A, 12}, {0x0AE3, 12}, {0x08D6, 12}, {0x0490, 12}, {0x0495, 12}, {0x1F19, 13}, {0x1DB5, 13},
+	 {0x0009, 4},  {0x0010, 5},  {0x0029, 6},  {0x0062, 7},  {0x00F3, 8},  {0x00AD, 8},  {0x01E5, 9},  {0x0179, 9},
+	 {0x009C, 9},  {0x03B1, 10}, {0x02AE, 10}, {0x0127, 10}, {0x076E, 11}, {0x0570, 11}, {0x0275, 11}, {0x0F25, 12},
+	 {0x0EC0, 12}, {0x0AA0, 12}, {0x08D7, 12}, {0x1E4C, 13}, {0x0008, 5},  {0x0063, 7},  {0x00AF, 8},  {0x017B, 9},
+	 {0x03B3, 10}, {0x07DD, 11}, {0x0640, 11}, {0x0F8D, 12}, {0x0BC1, 12}, {0x0491, 12}, {0x0028, 6},  {0x00C3, 8},
+	 {0x0151, 9},  {0x02A1, 10}, {0x0573, 11}, {0x0EC3, 12}, {0x1F35, 13}, {0x0065, 7},  {0x01DA, 9},  {0x02AF, 10},
+	 {0x0277, 11}, {0x08C9, 12}, {0x1781, 13}, {0x0025, 7},  {0x0118, 9},  {0x0646, 11}, {0x0AA6, 12}, {0x1780, 13},
+	 {0x00C9, 8},  {0x0321, 10}, {0x0F9B, 12}, {0x191E, 13}, {0x0048, 8},  {0x07CC, 11}, {0x0AA1, 12}, {0x0180, 9},
+	 {0x0465, 11}, {0x1905, 13}, {0x03E2, 10}, {0x0EC1, 12}, {0x3C9B, 14}, {0x02F4, 10}, {0x08C8, 12}, {0x07C1, 11},
+	 {0x0928, 13}, {0x05E1, 11}, {0x320D, 14}, {0x0EC2, 12}, {0x6418, 15}, {0x1F34, 13}, {0x0078, 7},  {0x0155, 9},
+	 {0x0552, 11}, {0x191F, 13}, {0x00FA, 8},  {0x07DC, 11}, {0x1907, 13}, {0x00AC, 8},  {0x0249, 11}, {0x13B1, 14},
+	 {0x01F6, 9},  {0x0AE2, 12}, {0x01DC, 9},  {0x04ED, 12}, {0x0184, 9},  {0x1904, 13}, {0x0156, 9},  {0x09D9, 13},
+	 {0x03E7, 10}, {0x0929, 13}, {0x03B2, 10}, {0x3B68, 14}, {0x02F5, 10}, {0x13B0, 14}, {0x0322, 10}, {0x3B69, 14},
+	 {0x0234, 10}, {0x7935, 15}, {0x07C7, 11}, {0xC833, 16}, {0x0660, 11}, {0x7934, 15}, {0x024B, 11}, {0xC832, 16},
+	 {0x0AA7, 12}, {0x1F18, 13}, {0x007A, 7}},
+	{{0x0002, 2},    {0x0000, 3},    {0x001E, 5},    {0x0004, 5},    {0x0012, 6},    {0x0070, 7},   {0x001A, 7},
+	 {0x005F, 8},    {0x0047, 8},    {0x01D3, 9},    {0x00B5, 9},    {0x0057, 9},    {0x03B5, 10},  {0x016D, 10},
+	 {0x0162, 10},   {0x07CE, 11},   {0x0719, 11},   {0x0691, 11},   {0x02C6, 11},   {0x0156, 11},  {0x0F92, 12},
+	 {0x0D2E, 12},   {0x0D20, 12},   {0x059E, 12},   {0x0468, 12},   {0x02A6, 12},   {0x1DA2, 13},  {0x1C60, 13},
+	 {0x1A43, 13},   {0x0B1D, 13},   {0x08C0, 13},   {0x055D, 13},   {0x0003, 3},    {0x000A, 5},   {0x0077, 7},
+	 {0x00E5, 8},    {0x01D9, 9},    {0x03E5, 10},   {0x0166, 10},   {0x0694, 11},   {0x0152, 11},  {0x059F, 12},
+	 {0x1F3C, 13},   {0x1A4B, 13},   {0x055E, 13},   {0x000C, 4},    {0x007D, 7},    {0x0044, 8},   {0x03E0, 10},
+	 {0x0769, 11},   {0x0E31, 12},   {0x1F26, 13},   {0x055C, 13},   {0x001B, 5},    {0x00E2, 8},   {0x03A5, 10},
+	 {0x02C9, 11},   {0x1F23, 13},   {0x3B47, 14},   {0x0007, 5},    {0x01D8, 9},    {0x02D8, 11},  {0x1F27, 13},
+	 {0x3494, 14},   {0x0035, 6},    {0x03E1, 10},   {0x059C, 12},   {0x38C3, 14},   {0x000C, 6},   {0x0165, 10},
+	 {0x1D23, 13},   {0x1638, 14},   {0x0068, 7},    {0x0693, 11},   {0x3A45, 14},   {0x0020, 7},   {0x0F90, 12},
+	 {0x7CF6, 15},   {0x00E8, 8},    {0x058F, 12},   {0x2CEF, 15},   {0x0045, 8},    {0x0B3A, 13},  {0x01F1, 9},
+	 {0x3B46, 14},   {0x01A7, 9},    {0x1676, 14},   {0x0056, 9},    {0x692A, 15},   {0x038D, 10},  {0xE309, 16},
+	 {0x00AA, 10},   {0x1C611, 17},  {0x02DF, 11},   {0xB3B9, 17},   {0x02C8, 11},   {0x38C20, 18}, {0x01B0, 11},
+	 {0x16390, 18},  {0x0F9F, 12},   {0x16771, 18},  {0x0ED0, 12},   {0x71843, 19},  {0x0D2A, 12},  {0xF9E8C, 20},
+	 {0x0461, 12},   {0xF9E8E, 20},  {0x0B67, 13},   {0x055F, 13},   {0x003F, 6},    {0x006D, 9},   {0x0E90, 12},
+	 {0x054E, 13},   {0x0013, 6},    {0x0119, 10},   {0x0B66, 13},   {0x000B, 6},    {0x0235, 11},  {0x7CF5, 15},
+	 {0x0075, 7},    {0x0D24, 12},   {0xF9E9, 16},   {0x002E, 7},    {0x1F22, 13},   {0x0021, 7},   {0x054F, 13},
+	 {0x0014, 7},    {0x3A44, 14},   {0x00E4, 8},    {0x7CF7, 15},   {0x005E, 8},    {0x7185, 15},  {0x0037, 8},
+	 {0x2C73, 15},   {0x01DB, 9},    {0x59DD, 16},   {0x01C7, 9},    {0x692B, 15},   {0x01A6, 9},   {0x58E5, 16},
+	 {0x00B4, 9},    {0x1F3D0, 17},  {0x00B0, 9},    {0xB1C9, 17},   {0x03E6, 10},   {0x16770, 18}, {0x016E, 10},
+	 {0x3E7A2, 18},  {0x011B, 10},   {0xF9E8D, 20},  {0x00D9, 10},   {0xF9E8F, 20},  {0x00A8, 10},  {0x2C723, 19},
+	 {0x0749, 11},   {0xE3084, 20},  {0x0696, 11},   {0x58E45, 20},  {0x02DE, 11},   {0xB1C88, 21}, {0x0231, 11},
+	 {0x1C610A, 21}, {0x01B1, 11},   {0x71842D, 23}, {0x0D2B, 12},   {0x38C217, 22}, {0x0D2F, 12},  {0x163913, 22},
+	 {0x05B2, 12},   {0x163912, 22}, {0x0469, 12},   {0x71842C, 23}, {0x1A42, 13},   {0x08C1, 13},  {0x0073, 7}}};
+
+const int ff_vc1_ac_sizes[AC_MODES] = {186, 169, 133, 149, 103, 103, 163, 175};
+
+} // namespace VC1
+static inline uint8 clipByte(int value) {
+	return CLIP(value, 0, 255);
+}
+
+static inline uint32 roundAvg32(uint32 a, uint32 b) {
+	return (a | b) - (((a ^ b) & ~0x01010101U) >> 1);
+}
+
+/* Apply overlap transform to horizontal edge */
+// Overlap and loop-filter DSP
+
+static void vc1_v_overlap_c(uint8 *src, ptrdiff_t stride) {
+	int i;
+	int a, b, c, d;
+	int d1, d2;
+	int rnd = 1;
+	for (i = 0; i < 8; i++) {
+		a = src[-2 * stride];
+		b = src[-stride];
+		c = src[0];
+		d = src[stride];
+		d1 = (a - d + 3 + rnd) >> 3;
+		d2 = (a - d + b - c + 4 - rnd) >> 3;
+
+		src[-2 * stride] = a - d1;
+		src[-stride] = clipByte(b - d2);
+		src[0] = clipByte(c + d2);
+		src[stride] = d + d1;
+		src++;
+		rnd = !rnd;
+	}
+}
+
+/* Apply overlap transform to vertical edge */
+static void vc1_h_overlap_c(uint8 *src, ptrdiff_t stride) {
+	int i;
+	int a, b, c, d;
+	int d1, d2;
+	int rnd = 1;
+	for (i = 0; i < 8; i++) {
+		a = src[-2];
+		b = src[-1];
+		c = src[0];
+		d = src[1];
+		d1 = (a - d + 3 + rnd) >> 3;
+		d2 = (a - d + b - c + 4 - rnd) >> 3;
+
+		src[-2] = a - d1;
+		src[-1] = clipByte(b - d2);
+		src[0] = clipByte(c + d2);
+		src[1] = d + d1;
+		src += stride;
+		rnd = !rnd;
+	}
+}
+
+static void vc1_v_s_overlap_c(int16 *top, int16 *bottom) {
+	int i;
+	int a, b, c, d;
+	int d1, d2;
+	int rnd1 = 4, rnd2 = 3;
+	for (i = 0; i < 8; i++) {
+		a = top[48];
+		b = top[56];
+		c = bottom[0];
+		d = bottom[8];
+		d1 = a - d;
+		d2 = a - d + b - c;
+
+		top[48] = ((a * 8) - d1 + rnd1) >> 3;
+		top[56] = ((b * 8) - d2 + rnd2) >> 3;
+		bottom[0] = ((c * 8) + d2 + rnd1) >> 3;
+		bottom[8] = ((d * 8) + d1 + rnd2) >> 3;
+
+		bottom++;
+		top++;
+		rnd2 = 7 - rnd2;
+		rnd1 = 7 - rnd1;
+	}
+}
+
+static void vc1_h_s_overlap_c(int16 *left, int16 *right, ptrdiff_t left_stride, ptrdiff_t right_stride, int flags) {
+	int i;
+	int a, b, c, d;
+	int d1, d2;
+	int rnd1 = flags & 2 ? 3 : 4;
+	int rnd2 = 7 - rnd1;
+	for (i = 0; i < 8; i++) {
+		a = left[6];
+		b = left[7];
+		c = right[0];
+		d = right[1];
+		d1 = a - d;
+		d2 = a - d + b - c;
+
+		left[6] = ((a * 8) - d1 + rnd1) >> 3;
+		left[7] = ((b * 8) - d2 + rnd2) >> 3;
+		right[0] = ((c * 8) + d2 + rnd1) >> 3;
+		right[1] = ((d * 8) + d1 + rnd2) >> 3;
+
+		right += right_stride;
+		left += left_stride;
+		if (flags & 1) {
+			rnd2 = 7 - rnd2;
+			rnd1 = 7 - rnd1;
+		}
+	}
+}
+
+/**
+ * VC-1 in-loop deblocking filter for one line
+ * @param src source block type
+ * @param stride block stride
+ * @param pq block quantizer
+ * @return whether other 3 pairs should be filtered or not
+ * @see 8.6
+ */
+static inline int vc1_filter_line(uint8 *src, ptrdiff_t stride, int pq) {
+	int a0 = (2 * (src[-2 * stride] - src[1 * stride]) - 5 * (src[-1 * stride] - src[0 * stride]) + 4) >> 3;
+	int a0_sign = a0 >> 31; /* Store sign */
+
+	a0 = (a0 ^ a0_sign) - a0_sign; /* a0 = ABS(a0); */
+	if (a0 < pq) {
+		int a1 = ABS((2 * (src[-4 * stride] - src[-1 * stride]) - 5 * (src[-3 * stride] - src[-2 * stride]) + 4) >> 3);
+		int a2 = ABS((2 * (src[0 * stride] - src[3 * stride]) - 5 * (src[1 * stride] - src[2 * stride]) + 4) >> 3);
+		if (a1 < a0 || a2 < a0) {
+			int clip = src[-1 * stride] - src[0 * stride];
+			int clip_sign = clip >> 31;
+
+			clip = ((clip ^ clip_sign) - clip_sign) >> 1;
+			if (clip) {
+				int a3 = MIN(a1, a2);
+				int d = 5 * (a3 - a0);
+				int d_sign = (d >> 31);
+
+				d = ((d ^ d_sign) - d_sign) >> 3;
+				d_sign ^= a0_sign;
+
+				if (d_sign ^ clip_sign)
+					d = 0;
+				else {
+					d = MIN(d, clip);
+					d = (d ^ d_sign) - d_sign; /* Restore sign */
+					src[-1 * stride] = clipByte(src[-1 * stride] - d);
+					src[0 * stride] = clipByte(src[0 * stride] + d);
+				}
+				return 1;
+			}
+		}
+	}
+	return 0;
+}
+
+/**
+ * VC-1 in-loop deblocking filter
+ * @param src source block type
+ * @param step distance between horizontally adjacent elements
+ * @param stride distance between vertically adjacent elements
+ * @param len edge length to filter (4 or 8 pixels)
+ * @param pq block quantizer
+ * @see 8.6
+ */
+static inline void vc1_loop_filter(uint8 *src, ptrdiff_t step, ptrdiff_t stride, int len, int pq) {
+	int i;
+	int filt3;
+
+	for (i = 0; i < len; i += 4) {
+		filt3 = vc1_filter_line(src + 2 * step, stride, pq);
+		if (filt3) {
+			vc1_filter_line(src + 0 * step, stride, pq);
+			vc1_filter_line(src + 1 * step, stride, pq);
+			vc1_filter_line(src + 3 * step, stride, pq);
+		}
+		src += step * 4;
+	}
+}
+
+static void vc1_v_loop_filter4_c(uint8 *src, ptrdiff_t stride, int pq) {
+	vc1_loop_filter(src, 1, stride, 4, pq);
+}
+
+static void vc1_h_loop_filter4_c(uint8 *src, ptrdiff_t stride, int pq) {
+	vc1_loop_filter(src, stride, 1, 4, pq);
+}
+
+static void vc1_v_loop_filter8_c(uint8 *src, ptrdiff_t stride, int pq) {
+	vc1_loop_filter(src, 1, stride, 8, pq);
+}
+
+static void vc1_h_loop_filter8_c(uint8 *src, ptrdiff_t stride, int pq) {
+	vc1_loop_filter(src, stride, 1, 8, pq);
+}
+
+static void vc1_v_loop_filter16_c(uint8 *src, ptrdiff_t stride, int pq) {
+	vc1_loop_filter(src, 1, stride, 16, pq);
+}
+
+static void vc1_h_loop_filter16_c(uint8 *src, ptrdiff_t stride, int pq) {
+	vc1_loop_filter(src, stride, 1, 16, pq);
+}
+
+/* Do inverse transform on 8x8 block */
+// Inverse-transform DSP
+
+static void vc1_inv_trans_8x8_dc_c(uint8 *dest, ptrdiff_t stride, int16 *block) {
+	int i;
+	int dc = block[0];
+
+	dc = (3 * dc + 1) >> 1;
+	dc = (3 * dc + 16) >> 5;
+
+	for (i = 0; i < 8; i++) {
+		dest[0] = clipByte(dest[0] + dc);
+		dest[1] = clipByte(dest[1] + dc);
+		dest[2] = clipByte(dest[2] + dc);
+		dest[3] = clipByte(dest[3] + dc);
+		dest[4] = clipByte(dest[4] + dc);
+		dest[5] = clipByte(dest[5] + dc);
+		dest[6] = clipByte(dest[6] + dc);
+		dest[7] = clipByte(dest[7] + dc);
+		dest += stride;
+	}
+}
+
+static void vc1_inv_trans_8x8_c(int16 block[64]) {
+	int i;
+	int t1, t2, t3, t4, t5, t6, t7, t8;
+	int16 *src, *dst, temp[64];
+
+	src = block;
+	dst = temp;
+	for (i = 0; i < 8; i++) {
+		t1 = 12 * (src[0] + src[32]) + 4;
+		t2 = 12 * (src[0] - src[32]) + 4;
+		t3 = 16 * src[16] + 6 * src[48];
+		t4 = 6 * src[16] - 16 * src[48];
+
+		t5 = t1 + t3;
+		t6 = t2 + t4;
+		t7 = t2 - t4;
+		t8 = t1 - t3;
+
+		t1 = 16 * src[8] + 15 * src[24] + 9 * src[40] + 4 * src[56];
+		t2 = 15 * src[8] - 4 * src[24] - 16 * src[40] - 9 * src[56];
+		t3 = 9 * src[8] - 16 * src[24] + 4 * src[40] + 15 * src[56];
+		t4 = 4 * src[8] - 9 * src[24] + 15 * src[40] - 16 * src[56];
+
+		dst[0] = (t5 + t1) >> 3;
+		dst[1] = (t6 + t2) >> 3;
+		dst[2] = (t7 + t3) >> 3;
+		dst[3] = (t8 + t4) >> 3;
+		dst[4] = (t8 - t4) >> 3;
+		dst[5] = (t7 - t3) >> 3;
+		dst[6] = (t6 - t2) >> 3;
+		dst[7] = (t5 - t1) >> 3;
+
+		src += 1;
+		dst += 8;
+	}
+
+	src = temp;
+	dst = block;
+	for (i = 0; i < 8; i++) {
+		t1 = 12 * (src[0] + src[32]) + 64;
+		t2 = 12 * (src[0] - src[32]) + 64;
+		t3 = 16 * src[16] + 6 * src[48];
+		t4 = 6 * src[16] - 16 * src[48];
+
+		t5 = t1 + t3;
+		t6 = t2 + t4;
+		t7 = t2 - t4;
+		t8 = t1 - t3;
+
+		t1 = 16 * src[8] + 15 * src[24] + 9 * src[40] + 4 * src[56];
+		t2 = 15 * src[8] - 4 * src[24] - 16 * src[40] - 9 * src[56];
+		t3 = 9 * src[8] - 16 * src[24] + 4 * src[40] + 15 * src[56];
+		t4 = 4 * src[8] - 9 * src[24] + 15 * src[40] - 16 * src[56];
+
+		dst[0] = (t5 + t1) >> 7;
+		dst[8] = (t6 + t2) >> 7;
+		dst[16] = (t7 + t3) >> 7;
+		dst[24] = (t8 + t4) >> 7;
+		dst[32] = (t8 - t4 + 1) >> 7;
+		dst[40] = (t7 - t3 + 1) >> 7;
+		dst[48] = (t6 - t2 + 1) >> 7;
+		dst[56] = (t5 - t1 + 1) >> 7;
+
+		src++;
+		dst++;
+	}
+}
+
+/* Do inverse transform on 8x4 part of block */
+static void vc1_inv_trans_8x4_dc_c(uint8 *dest, ptrdiff_t stride, int16 *block) {
+	int i;
+	int dc = block[0];
+
+	dc = (3 * dc + 1) >> 1;
+	dc = (17 * dc + 64) >> 7;
+
+	for (i = 0; i < 4; i++) {
+		dest[0] = clipByte(dest[0] + dc);
+		dest[1] = clipByte(dest[1] + dc);
+		dest[2] = clipByte(dest[2] + dc);
+		dest[3] = clipByte(dest[3] + dc);
+		dest[4] = clipByte(dest[4] + dc);
+		dest[5] = clipByte(dest[5] + dc);
+		dest[6] = clipByte(dest[6] + dc);
+		dest[7] = clipByte(dest[7] + dc);
+		dest += stride;
+	}
+}
+
+static void vc1_inv_trans_8x4_c(uint8 *dest, ptrdiff_t stride, int16 *block) {
+	int i;
+	int t1, t2, t3, t4, t5, t6, t7, t8;
+	int16 *src, *dst;
+
+	src = block;
+	dst = block;
+
+	for (i = 0; i < 4; i++) {
+		t1 = 12 * (src[0] + src[4]) + 4;
+		t2 = 12 * (src[0] - src[4]) + 4;
+		t3 = 16 * src[2] + 6 * src[6];
+		t4 = 6 * src[2] - 16 * src[6];
+
+		t5 = t1 + t3;
+		t6 = t2 + t4;
+		t7 = t2 - t4;
+		t8 = t1 - t3;
+
+		t1 = 16 * src[1] + 15 * src[3] + 9 * src[5] + 4 * src[7];
+		t2 = 15 * src[1] - 4 * src[3] - 16 * src[5] - 9 * src[7];
+		t3 = 9 * src[1] - 16 * src[3] + 4 * src[5] + 15 * src[7];
+		t4 = 4 * src[1] - 9 * src[3] + 15 * src[5] - 16 * src[7];
+
+		dst[0] = (t5 + t1) >> 3;
+		dst[1] = (t6 + t2) >> 3;
+		dst[2] = (t7 + t3) >> 3;
+		dst[3] = (t8 + t4) >> 3;
+		dst[4] = (t8 - t4) >> 3;
+		dst[5] = (t7 - t3) >> 3;
+		dst[6] = (t6 - t2) >> 3;
+		dst[7] = (t5 - t1) >> 3;
+
+		src += 8;
+		dst += 8;
+	}
+
+	src = block;
+	for (i = 0; i < 8; i++) {
+		t1 = 17 * (src[0] + src[16]) + 64;
+		t2 = 17 * (src[0] - src[16]) + 64;
+		t3 = 22 * src[8] + 10 * src[24];
+		t4 = 22 * src[24] - 10 * src[8];
+
+		dest[0 * stride] = clipByte(dest[0 * stride] + ((t1 + t3) >> 7));
+		dest[1 * stride] = clipByte(dest[1 * stride] + ((t2 - t4) >> 7));
+		dest[2 * stride] = clipByte(dest[2 * stride] + ((t2 + t4) >> 7));
+		dest[3 * stride] = clipByte(dest[3 * stride] + ((t1 - t3) >> 7));
+
+		src++;
+		dest++;
+	}
+}
+
+/* Do inverse transform on 4x8 parts of block */
+static void vc1_inv_trans_4x8_dc_c(uint8 *dest, ptrdiff_t stride, int16 *block) {
+	int i;
+	int dc = block[0];
+
+	dc = (17 * dc + 4) >> 3;
+	dc = (12 * dc + 64) >> 7;
+
+	for (i = 0; i < 8; i++) {
+		dest[0] = clipByte(dest[0] + dc);
+		dest[1] = clipByte(dest[1] + dc);
+		dest[2] = clipByte(dest[2] + dc);
+		dest[3] = clipByte(dest[3] + dc);
+		dest += stride;
+	}
+}
+
+static void vc1_inv_trans_4x8_c(uint8 *dest, ptrdiff_t stride, int16 *block) {
+	int i;
+	int t1, t2, t3, t4, t5, t6, t7, t8;
+	int16 *src, *dst;
+
+	src = block;
+	dst = block;
+
+	for (i = 0; i < 8; i++) {
+		t1 = 17 * (src[0] + src[2]) + 4;
+		t2 = 17 * (src[0] - src[2]) + 4;
+		t3 = 22 * src[1] + 10 * src[3];
+		t4 = 22 * src[3] - 10 * src[1];
+
+		dst[0] = (t1 + t3) >> 3;
+		dst[1] = (t2 - t4) >> 3;
+		dst[2] = (t2 + t4) >> 3;
+		dst[3] = (t1 - t3) >> 3;
+
+		src += 8;
+		dst += 8;
+	}
+
+	src = block;
+	for (i = 0; i < 4; i++) {
+		t1 = 12 * (src[0] + src[32]) + 64;
+		t2 = 12 * (src[0] - src[32]) + 64;
+		t3 = 16 * src[16] + 6 * src[48];
+		t4 = 6 * src[16] - 16 * src[48];
+
+		t5 = t1 + t3;
+		t6 = t2 + t4;
+		t7 = t2 - t4;
+		t8 = t1 - t3;
+
+		t1 = 16 * src[8] + 15 * src[24] + 9 * src[40] + 4 * src[56];
+		t2 = 15 * src[8] - 4 * src[24] - 16 * src[40] - 9 * src[56];
+		t3 = 9 * src[8] - 16 * src[24] + 4 * src[40] + 15 * src[56];
+		t4 = 4 * src[8] - 9 * src[24] + 15 * src[40] - 16 * src[56];
+
+		dest[0 * stride] = clipByte(dest[0 * stride] + ((t5 + t1) >> 7));
+		dest[1 * stride] = clipByte(dest[1 * stride] + ((t6 + t2) >> 7));
+		dest[2 * stride] = clipByte(dest[2 * stride] + ((t7 + t3) >> 7));
+		dest[3 * stride] = clipByte(dest[3 * stride] + ((t8 + t4) >> 7));
+		dest[4 * stride] = clipByte(dest[4 * stride] + ((t8 - t4 + 1) >> 7));
+		dest[5 * stride] = clipByte(dest[5 * stride] + ((t7 - t3 + 1) >> 7));
+		dest[6 * stride] = clipByte(dest[6 * stride] + ((t6 - t2 + 1) >> 7));
+		dest[7 * stride] = clipByte(dest[7 * stride] + ((t5 - t1 + 1) >> 7));
+
+		src++;
+		dest++;
+	}
+}
+
+/* Do inverse transform on 4x4 part of block */
+static void vc1_inv_trans_4x4_dc_c(uint8 *dest, ptrdiff_t stride, int16 *block) {
+	int i;
+	int dc = block[0];
+
+	dc = (17 * dc + 4) >> 3;
+	dc = (17 * dc + 64) >> 7;
+
+	for (i = 0; i < 4; i++) {
+		dest[0] = clipByte(dest[0] + dc);
+		dest[1] = clipByte(dest[1] + dc);
+		dest[2] = clipByte(dest[2] + dc);
+		dest[3] = clipByte(dest[3] + dc);
+		dest += stride;
+	}
+}
+
+static void vc1_inv_trans_4x4_c(uint8 *dest, ptrdiff_t stride, int16 *block) {
+	int i;
+	int t1, t2, t3, t4;
+	int16 *src, *dst;
+
+	src = block;
+	dst = block;
+	for (i = 0; i < 4; i++) {
+		t1 = 17 * (src[0] + src[2]) + 4;
+		t2 = 17 * (src[0] - src[2]) + 4;
+		t3 = 22 * src[1] + 10 * src[3];
+		t4 = 22 * src[3] - 10 * src[1];
+
+		dst[0] = (t1 + t3) >> 3;
+		dst[1] = (t2 - t4) >> 3;
+		dst[2] = (t2 + t4) >> 3;
+		dst[3] = (t1 - t3) >> 3;
+
+		src += 8;
+		dst += 8;
+	}
+
+	src = block;
+	for (i = 0; i < 4; i++) {
+		t1 = 17 * (src[0] + src[16]) + 64;
+		t2 = 17 * (src[0] - src[16]) + 64;
+		t3 = 22 * src[8] + 10 * src[24];
+		t4 = 22 * src[24] - 10 * src[8];
+
+		dest[0 * stride] = clipByte(dest[0 * stride] + ((t1 + t3) >> 7));
+		dest[1 * stride] = clipByte(dest[1 * stride] + ((t2 - t4) >> 7));
+		dest[2 * stride] = clipByte(dest[2 * stride] + ((t2 + t4) >> 7));
+		dest[3 * stride] = clipByte(dest[3 * stride] + ((t1 - t3) >> 7));
+
+		src++;
+		dest++;
+	}
+}
+
+/* motion compensation functions */
+
+/* Filter in case of 2 filters */
+#define VC1_MSPEL_FILTER_16B(DIR, TYPE)                                                                                \
+	static inline int vc1_mspel_##DIR##_filter_16bits(const TYPE *src, ptrdiff_t stride, int mode) {                   \
+		switch (mode) {                                                                                                \
+		case 0: /* no shift - should not occur */                                                                      \
+			return 0;                                                                                                  \
+		case 1: /* 1/4 shift */                                                                                        \
+			return -4 * src[-stride] + 53 * src[0] + 18 * src[stride] - 3 * src[stride * 2];                           \
+		case 2: /* 1/2 shift */                                                                                        \
+			return -1 * src[-stride] + 9 * src[0] + 9 * src[stride] - 1 * src[stride * 2];                             \
+		case 3: /* 3/4 shift */                                                                                        \
+			return -3 * src[-stride] + 18 * src[0] + 53 * src[stride] - 4 * src[stride * 2];                           \
+		}                                                                                                              \
+		return 0; /* should not occur */                                                                               \
+	}
+
+VC1_MSPEL_FILTER_16B(ver, uint8)
+VC1_MSPEL_FILTER_16B(hor, int16)
+
+/* Filter used to interpolate fractional pel values */
+static inline int vc1_mspel_filter(const uint8 *src, ptrdiff_t stride, int mode, int r) {
+	switch (mode) {
+	case 0: // no shift
+		return src[0];
+	case 1: // 1/4 shift
+		return (-4 * src[-stride] + 53 * src[0] + 18 * src[stride] - 3 * src[stride * 2] + 32 - r) >> 6;
+	case 2: // 1/2 shift
+		return (-1 * src[-stride] + 9 * src[0] + 9 * src[stride] - 1 * src[stride * 2] + 8 - r) >> 4;
+	case 3: // 3/4 shift
+		return (-3 * src[-stride] + 18 * src[0] + 53 * src[stride] - 4 * src[stride * 2] + 32 - r) >> 6;
+	}
+	return 0; // should not occur
+}
+
+/* Function used to do motion compensation with bicubic interpolation */
+#define VC1_MSPEL_MC(OP, OP4, OPNAME)                                                                                  \
+	static inline void OPNAME##vc1_mspel_mc(uint8 *dst, const uint8 *src, ptrdiff_t stride, int hmode, int vmode,      \
+											int rnd) {                                                                 \
+		int i, j;                                                                                                      \
+                                                                                                                       \
+		if (vmode) { /* Horizontal filter to apply */                                                                  \
+			int r;                                                                                                     \
+                                                                                                                       \
+			if (hmode) { /* Vertical filter to apply, output to tmp */                                                 \
+				static const int shift_value[] = {0, 5, 1, 5};                                                         \
+				int shift = (shift_value[hmode] + shift_value[vmode]) >> 1;                                            \
+				int16 tmp[11 * 8], *tptr = tmp;                                                                        \
+                                                                                                                       \
+				r = (1 << (shift - 1)) + rnd - 1;                                                                      \
+                                                                                                                       \
+				src -= 1;                                                                                              \
+				for (j = 0; j < 8; j++) {                                                                              \
+					for (i = 0; i < 11; i++)                                                                           \
+						tptr[i] = (vc1_mspel_ver_filter_16bits(src + i, stride, vmode) + r) >> shift;                  \
+					src += stride;                                                                                     \
+					tptr += 11;                                                                                        \
+				}                                                                                                      \
+                                                                                                                       \
+				r = 64 - rnd;                                                                                          \
+				tptr = tmp + 1;                                                                                        \
+				for (j = 0; j < 8; j++) {                                                                              \
+					for (i = 0; i < 8; i++)                                                                            \
+						OP(dst[i], (vc1_mspel_hor_filter_16bits(tptr + i, 1, hmode) + r) >> 7);                        \
+					dst += stride;                                                                                     \
+					tptr += 11;                                                                                        \
+				}                                                                                                      \
+                                                                                                                       \
+				return;                                                                                                \
+			} else { /* No horizontal filter, output 8 lines to dst */                                                 \
+				r = 1 - rnd;                                                                                           \
+                                                                                                                       \
+				for (j = 0; j < 8; j++) {                                                                              \
+					for (i = 0; i < 8; i++)                                                                            \
+						OP(dst[i], vc1_mspel_filter(src + i, stride, vmode, r));                                       \
+					src += stride;                                                                                     \
+					dst += stride;                                                                                     \
+				}                                                                                                      \
+				return;                                                                                                \
+			}                                                                                                          \
+		}                                                                                                              \
+                                                                                                                       \
+		/* Horizontal mode with no vertical mode */                                                                    \
+		for (j = 0; j < 8; j++) {                                                                                      \
+			for (i = 0; i < 8; i++)                                                                                    \
+				OP(dst[i], vc1_mspel_filter(src + i, 1, hmode, rnd));                                                  \
+			dst += stride;                                                                                             \
+			src += stride;                                                                                             \
+		}                                                                                                              \
+	}                                                                                                                  \
+	static inline void OPNAME##vc1_mspel_mc_16(uint8 *dst, const uint8 *src, ptrdiff_t stride, int hmode, int vmode,   \
+											   int rnd) {                                                              \
+		int i, j;                                                                                                      \
+                                                                                                                       \
+		if (vmode) { /* Horizontal filter to apply */                                                                  \
+			int r;                                                                                                     \
+                                                                                                                       \
+			if (hmode) { /* Vertical filter to apply, output to tmp */                                                 \
+				static const int shift_value[] = {0, 5, 1, 5};                                                         \
+				int shift = (shift_value[hmode] + shift_value[vmode]) >> 1;                                            \
+				int16 tmp[19 * 16], *tptr = tmp;                                                                       \
+                                                                                                                       \
+				r = (1 << (shift - 1)) + rnd - 1;                                                                      \
+                                                                                                                       \
+				src -= 1;                                                                                              \
+				for (j = 0; j < 16; j++) {                                                                             \
+					for (i = 0; i < 19; i++)                                                                           \
+						tptr[i] = (vc1_mspel_ver_filter_16bits(src + i, stride, vmode) + r) >> shift;                  \
+					src += stride;                                                                                     \
+					tptr += 19;                                                                                        \
+				}                                                                                                      \
+                                                                                                                       \
+				r = 64 - rnd;                                                                                          \
+				tptr = tmp + 1;                                                                                        \
+				for (j = 0; j < 16; j++) {                                                                             \
+					for (i = 0; i < 16; i++)                                                                           \
+						OP(dst[i], (vc1_mspel_hor_filter_16bits(tptr + i, 1, hmode) + r) >> 7);                        \
+					dst += stride;                                                                                     \
+					tptr += 19;                                                                                        \
+				}                                                                                                      \
+                                                                                                                       \
+				return;                                                                                                \
+			} else { /* No horizontal filter, output 8 lines to dst */                                                 \
+				r = 1 - rnd;                                                                                           \
+                                                                                                                       \
+				for (j = 0; j < 16; j++) {                                                                             \
+					for (i = 0; i < 16; i++)                                                                           \
+						OP(dst[i], vc1_mspel_filter(src + i, stride, vmode, r));                                       \
+					src += stride;                                                                                     \
+					dst += stride;                                                                                     \
+				}                                                                                                      \
+				return;                                                                                                \
+			}                                                                                                          \
+		}                                                                                                              \
+                                                                                                                       \
+		/* Horizontal mode with no vertical mode */                                                                    \
+		for (j = 0; j < 16; j++) {                                                                                     \
+			for (i = 0; i < 16; i++)                                                                                   \
+				OP(dst[i], vc1_mspel_filter(src + i, 1, hmode, rnd));                                                  \
+			dst += stride;                                                                                             \
+			src += stride;                                                                                             \
+		}                                                                                                              \
+	}                                                                                                                  \
+	static void OPNAME##pixels8x8_c(uint8 *block, const uint8 *pixels, ptrdiff_t line_size, int rnd) {                 \
+		int i;                                                                                                         \
+		for (i = 0; i < 8; i++) {                                                                                      \
+			OP4(block, READ_UINT32(pixels));                                                                           \
+			OP4(block + 4, READ_UINT32(pixels + 4));                                                                   \
+			pixels += line_size;                                                                                       \
+			block += line_size;                                                                                        \
+		}                                                                                                              \
+	}                                                                                                                  \
+	static void OPNAME##pixels16x16_c(uint8 *block, const uint8 *pixels, ptrdiff_t line_size, int rnd) {               \
+		int i;                                                                                                         \
+		for (i = 0; i < 16; i++) {                                                                                     \
+			OP4(block, READ_UINT32(pixels));                                                                           \
+			OP4(block + 4, READ_UINT32(pixels + 4));                                                                   \
+			OP4(block + 8, READ_UINT32(pixels + 8));                                                                   \
+			OP4(block + 12, READ_UINT32(pixels + 12));                                                                 \
+			pixels += line_size;                                                                                       \
+			block += line_size;                                                                                        \
+		}                                                                                                              \
+	}
+
+#define op_put(a, b) (a) = clipByte(b)
+#define op_avg(a, b) (a) = ((a) + clipByte(b) + 1) >> 1
+#define op4_avg(a, b) WRITE_UINT32(a, roundAvg32(READ_UINT32(a), b))
+#define op4_put(a, b) WRITE_UINT32(a, b)
+
+VC1_MSPEL_MC(op_put, op4_put, put_)
+VC1_MSPEL_MC(op_avg, op4_avg, avg_)
+
+/* pixel functions - really are entry points to vc1_mspel_mc */
+
+#define PUT_VC1_MSPEL(a, b)                                                                                            \
+	static void put_vc1_mspel_mc##a##b##_c(uint8 *dst, const uint8 *src, ptrdiff_t stride, int rnd) {                  \
+		put_vc1_mspel_mc(dst, src, stride, a, b, rnd);                                                                 \
+	}                                                                                                                  \
+	static void avg_vc1_mspel_mc##a##b##_c(uint8 *dst, const uint8 *src, ptrdiff_t stride, int rnd) {                  \
+		avg_vc1_mspel_mc(dst, src, stride, a, b, rnd);                                                                 \
+	}                                                                                                                  \
+	static void put_vc1_mspel_mc##a##b##_16_c(uint8 *dst, const uint8 *src, ptrdiff_t stride, int rnd) {               \
+		put_vc1_mspel_mc_16(dst, src, stride, a, b, rnd);                                                              \
+	}                                                                                                                  \
+	static void avg_vc1_mspel_mc##a##b##_16_c(uint8 *dst, const uint8 *src, ptrdiff_t stride, int rnd) {               \
+		avg_vc1_mspel_mc_16(dst, src, stride, a, b, rnd);                                                              \
+	}
+
+PUT_VC1_MSPEL(1, 0)
+PUT_VC1_MSPEL(2, 0)
+PUT_VC1_MSPEL(3, 0)
+
+PUT_VC1_MSPEL(0, 1)
+PUT_VC1_MSPEL(1, 1)
+PUT_VC1_MSPEL(2, 1)
+PUT_VC1_MSPEL(3, 1)
+
+PUT_VC1_MSPEL(0, 2)
+PUT_VC1_MSPEL(1, 2)
+PUT_VC1_MSPEL(2, 2)
+PUT_VC1_MSPEL(3, 2)
+
+PUT_VC1_MSPEL(0, 3)
+PUT_VC1_MSPEL(1, 3)
+PUT_VC1_MSPEL(2, 3)
+PUT_VC1_MSPEL(3, 3)
+
+#define chroma_mc(a) ((A * src[a] + B * src[a + 1] + C * src[stride + a] + D * src[stride + a + 1] + 32 - 4) >> 6)
+static void put_no_rnd_vc1_chroma_mc8_c(uint8 *dst /* align 8 */, const uint8 *src /* align 1 */, ptrdiff_t stride,
+										int h, int x, int y) {
+	const int A = (8 - x) * (8 - y);
+	const int B = (x) * (8 - y);
+	const int C = (8 - x) * (y);
+	const int D = (x) * (y);
+	int i;
+
+	assert(x < 8 && y < 8 && x >= 0 && y >= 0);
+
+	for (i = 0; i < h; i++) {
+		dst[0] = chroma_mc(0);
+		dst[1] = chroma_mc(1);
+		dst[2] = chroma_mc(2);
+		dst[3] = chroma_mc(3);
+		dst[4] = chroma_mc(4);
+		dst[5] = chroma_mc(5);
+		dst[6] = chroma_mc(6);
+		dst[7] = chroma_mc(7);
+		dst += stride;
+		src += stride;
+	}
+}
+
+static void put_no_rnd_vc1_chroma_mc4_c(uint8 *dst, const uint8 *src, ptrdiff_t stride, int h, int x, int y) {
+	const int A = (8 - x) * (8 - y);
+	const int B = (x) * (8 - y);
+	const int C = (8 - x) * (y);
+	const int D = (x) * (y);
+	int i;
+
+	assert(x < 8 && y < 8 && x >= 0 && y >= 0);
+
+	for (i = 0; i < h; i++) {
+		dst[0] = chroma_mc(0);
+		dst[1] = chroma_mc(1);
+		dst[2] = chroma_mc(2);
+		dst[3] = chroma_mc(3);
+		dst += stride;
+		src += stride;
+	}
+}
+
+#define avg2(a, b) (((a) + (b) + 1) >> 1)
+static void avg_no_rnd_vc1_chroma_mc8_c(uint8 *dst /* align 8 */, const uint8 *src /* align 1 */, ptrdiff_t stride,
+										int h, int x, int y) {
+	const int A = (8 - x) * (8 - y);
+	const int B = (x) * (8 - y);
+	const int C = (8 - x) * (y);
+	const int D = (x) * (y);
+	int i;
+
+	assert(x < 8 && y < 8 && x >= 0 && y >= 0);
+
+	for (i = 0; i < h; i++) {
+		dst[0] = avg2(dst[0], chroma_mc(0));
+		dst[1] = avg2(dst[1], chroma_mc(1));
+		dst[2] = avg2(dst[2], chroma_mc(2));
+		dst[3] = avg2(dst[3], chroma_mc(3));
+		dst[4] = avg2(dst[4], chroma_mc(4));
+		dst[5] = avg2(dst[5], chroma_mc(5));
+		dst[6] = avg2(dst[6], chroma_mc(6));
+		dst[7] = avg2(dst[7], chroma_mc(7));
+		dst += stride;
+		src += stride;
+	}
+}
+
+static void avg_no_rnd_vc1_chroma_mc4_c(uint8 *dst /* align 8 */, const uint8 *src /* align 1 */, ptrdiff_t stride,
+										int h, int x, int y) {
+	const int A = (8 - x) * (8 - y);
+	const int B = (x) * (8 - y);
+	const int C = (8 - x) * (y);
+	const int D = (x) * (y);
+	int i;
+
+	assert(x < 8 && y < 8 && x >= 0 && y >= 0);
+
+	for (i = 0; i < h; i++) {
+		dst[0] = avg2(dst[0], chroma_mc(0));
+		dst[1] = avg2(dst[1], chroma_mc(1));
+		dst[2] = avg2(dst[2], chroma_mc(2));
+		dst[3] = avg2(dst[3], chroma_mc(3));
+		dst += stride;
+		src += stride;
+	}
+}
+
+#define FN_ASSIGN(X, Y)                                                                                                \
+	dsp->put_vc1_mspel_pixels_tab[1][X + 4 * Y] = put_vc1_mspel_mc##X##Y##_c;                                          \
+	dsp->put_vc1_mspel_pixels_tab[0][X + 4 * Y] = put_vc1_mspel_mc##X##Y##_16_c;                                       \
+	dsp->avg_vc1_mspel_pixels_tab[1][X + 4 * Y] = avg_vc1_mspel_mc##X##Y##_c;                                          \
+	dsp->avg_vc1_mspel_pixels_tab[0][X + 4 * Y] = avg_vc1_mspel_mc##X##Y##_16_c
+
+void initWMV3DSP(WMV3DSP *dsp) {
+	*dsp = WMV3DSP();
+	dsp->vc1_inv_trans_8x8 = vc1_inv_trans_8x8_c;
+	dsp->vc1_inv_trans_4x8 = vc1_inv_trans_4x8_c;
+	dsp->vc1_inv_trans_8x4 = vc1_inv_trans_8x4_c;
+	dsp->vc1_inv_trans_4x4 = vc1_inv_trans_4x4_c;
+	dsp->vc1_inv_trans_8x8_dc = vc1_inv_trans_8x8_dc_c;
+	dsp->vc1_inv_trans_4x8_dc = vc1_inv_trans_4x8_dc_c;
+	dsp->vc1_inv_trans_8x4_dc = vc1_inv_trans_8x4_dc_c;
+	dsp->vc1_inv_trans_4x4_dc = vc1_inv_trans_4x4_dc_c;
+
+	dsp->vc1_h_overlap = vc1_h_overlap_c;
+	dsp->vc1_v_overlap = vc1_v_overlap_c;
+	dsp->vc1_h_s_overlap = vc1_h_s_overlap_c;
+	dsp->vc1_v_s_overlap = vc1_v_s_overlap_c;
+
+	dsp->vc1_v_loop_filter4 = vc1_v_loop_filter4_c;
+	dsp->vc1_h_loop_filter4 = vc1_h_loop_filter4_c;
+	dsp->vc1_v_loop_filter8 = vc1_v_loop_filter8_c;
+	dsp->vc1_h_loop_filter8 = vc1_h_loop_filter8_c;
+	dsp->vc1_v_loop_filter16 = vc1_v_loop_filter16_c;
+	dsp->vc1_h_loop_filter16 = vc1_h_loop_filter16_c;
+
+	dsp->put_vc1_mspel_pixels_tab[0][0] = put_pixels16x16_c;
+	dsp->avg_vc1_mspel_pixels_tab[0][0] = avg_pixels16x16_c;
+	dsp->put_vc1_mspel_pixels_tab[1][0] = put_pixels8x8_c;
+	dsp->avg_vc1_mspel_pixels_tab[1][0] = avg_pixels8x8_c;
+	FN_ASSIGN(0, 1);
+	FN_ASSIGN(0, 2);
+	FN_ASSIGN(0, 3);
+
+	FN_ASSIGN(1, 0);
+	FN_ASSIGN(1, 1);
+	FN_ASSIGN(1, 2);
+	FN_ASSIGN(1, 3);
+
+	FN_ASSIGN(2, 0);
+	FN_ASSIGN(2, 1);
+	FN_ASSIGN(2, 2);
+	FN_ASSIGN(2, 3);
+
+	FN_ASSIGN(3, 0);
+	FN_ASSIGN(3, 1);
+	FN_ASSIGN(3, 2);
+	FN_ASSIGN(3, 3);
+
+	dsp->put_no_rnd_vc1_chroma_pixels_tab[0] = put_no_rnd_vc1_chroma_mc8_c;
+	dsp->avg_no_rnd_vc1_chroma_pixels_tab[0] = avg_no_rnd_vc1_chroma_mc8_c;
+	dsp->put_no_rnd_vc1_chroma_pixels_tab[1] = put_no_rnd_vc1_chroma_mc4_c;
+	dsp->avg_no_rnd_vc1_chroma_pixels_tab[1] = avg_no_rnd_vc1_chroma_mc4_c;
+}
+
+#undef FN_ASSIGN
+#undef PUT_VC1_MSPEL
+#undef VC1_MSPEL_FILTER_16B
+#undef VC1_MSPEL_MC
+#undef avg2
+#undef chroma_mc
+#undef op4_avg
+#undef op4_put
+#undef op_avg
+#undef op_put
+
+enum { PROFILE_SIMPLE, PROFILE_MAIN, PROFILE_COMPLEX, PROFILE_ADVANCED };
+
+static int setDimensions(VC1Header *v, int width, int height) {
+	if (width <= 0 || height <= 0) {
+		v->width = v->height = 0;
+		return -1;
+	}
+	v->width = width;
+	v->height = height;
+	return 0;
+}
+
+static void validateAspect(VC1Header *v) {
+	const VC1Ratio &sar = v->sample_aspect_ratio;
+	bool valid = sar.den > 0 && sar.num >= 0;
+	if (valid && sar.num && sar.num != sar.den) {
+		int64 scaled = sar.num < sar.den ? (int64)v->width * sar.num / sar.den : (int64)v->height * sar.den / sar.num;
+		valid = scaled > 0;
+	}
+	if (!valid)
+		v->sample_aspect_ratio = VC1Ratio();
+}
+
+static void reduceAspect(VC1Ratio &aspect, int num, int den) {
+	if (den <= 0) {
+		aspect = VC1Ratio();
+		return;
+	}
+	Common::Rational ratio(num, den);
+	aspect.num = ratio.getNumerator();
+	aspect.den = ratio.getDenominator();
+}
+
+static const uint8 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,
+};
+
+static const uint8 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,
+};
+
+static const uint8 ff_vc1_adv_progressive_8x4_zz[32] = {/* Table 233 */
+														0,  8,  1,  16, 2,  9, 10, 3,  24, 17, 4,  11, 18, 12, 5,  19,
+														25, 13, 20, 26, 27, 6, 21, 28, 14, 22, 29, 7,  30, 15, 23, 31};
+
+static const uint8 ff_vc1_adv_progressive_4x8_zz[32] = {/* Table 234 */
+														0,  1,  8,  2,  9,  16, 17, 24, 10, 32, 25, 18, 40, 3,  33, 26,
+														48, 11, 56, 41, 34, 49, 57, 42, 19, 50, 27, 58, 35, 43, 51, 59};
+
+static const VC1Ratio ff_vc1_pixel_aspect[16] = {{0, 1},   {1, 1},    {12, 11}, {10, 11}, {16, 11}, {40, 33},
+												 {24, 11}, {20, 11},  {32, 11}, {80, 33}, {18, 11}, {15, 11},
+												 {64, 33}, {160, 99}, {0, 1},   {0, 1}};
+
+static const int ff_vc1_fps_nr[7] = {24, 25, 30, 50, 60, 48, 72};
+static const int ff_vc1_fps_dr[2] = {1000, 1001};
+
+static int readVC1Advanced(VC1Header *v, Common::BitStream8MSB *gb);
+
+/**
+ * Decode Simple/Main Profiles sequence header
+ * @see Figure 7-8, p16-17
+ * @param v Parsed codec state
+ * @param gb Bit stream containing the codec sequence header
+ * @return Status
+ */
+// Sequence and entry-point headers
+
+int readVC1Sequence(VC1Header *v, Common::BitStream8MSB *gb) {
+
+	v->profile = gb->getBits(2);
+	if (v->profile == PROFILE_COMPLEX) {
+		warning("WMV3 Complex Profile is not fully supported\n");
+	}
+
+	if (v->profile == PROFILE_ADVANCED) {
+		v->zz_8x4 = ff_vc1_adv_progressive_8x4_zz;
+		v->zz_4x8 = ff_vc1_adv_progressive_4x8_zz;
+		return readVC1Advanced(v, gb);
+	} else {
+		v->chromaformat = 1;
+		v->zz_8x4 = ff_wmv2_scantableA;
+		v->zz_4x8 = ff_wmv2_scantableB;
+		v->res_y411 = gb->getBit();
+		v->res_sprite = gb->getBit();
+		if (v->res_y411) {
+			warning("Old interlaced mode is not supported\n");
+			return -1;
+		}
+	}
+
+	// (fps-2)/4 (->30)
+	v->frmrtq_postproc = gb->getBits(3); // common
+	// (bitrate-32kbps)/64kbps
+	v->bitrtq_postproc = gb->getBits(5); // common
+	v->loop_filter = gb->getBit();       // common
+	if (v->loop_filter == 1 && v->profile == PROFILE_SIMPLE) {
+		warning("LOOPFILTER shall not be enabled in Simple Profile\n");
+	}
+
+	v->res_x8 = gb->getBit(); // reserved
+	v->multires = gb->getBit();
+	v->res_fasttx = gb->getBit();
+
+	v->fastuvmc = gb->getBit(); // common
+	if (!v->profile && !v->fastuvmc) {
+		warning("FASTUVMC unavailable in Simple Profile\n");
+		return -1;
+	}
+	v->extended_mv = gb->getBit(); // common
+	if (!v->profile && v->extended_mv) {
+		warning("Extended MVs unavailable in Simple Profile\n");
+		return -1;
+	}
+	v->dquant = gb->getBits(2);    // common
+	v->vstransform = gb->getBit(); // common
+
+	v->res_transtab = gb->getBit();
+	if (v->res_transtab) {
+		warning("1 for reserved RES_TRANSTAB is forbidden\n");
+		return -1;
+	}
+
+	v->overlap = gb->getBit(); // common
+
+	v->resync_marker = gb->getBit();
+	v->rangered = gb->getBit();
+	if (v->rangered && v->profile == PROFILE_SIMPLE) {
+		warning("RANGERED should be set to 0 in Simple Profile\n");
+	}
+
+	v->max_b_frames = gb->getBits(3);   // common
+	v->quantizer_mode = gb->getBits(2); // common
+
+	v->finterpflag = gb->getBit(); // common
+
+	if (v->res_sprite) {
+		int w = gb->getBits(11);
+		int h = gb->getBits(11);
+		int ret = setDimensions(v, w, h);
+		if (ret < 0) {
+			warning("Failed to set dimensions %d %d\n", w, h);
+			return ret;
+		}
+		gb->skip(5); // frame rate
+		v->res_x8 = gb->getBit();
+		if (gb->getBit()) { // something to do with DC VLC selection
+			warning("Unsupported sprite feature\n");
+			return -1;
+		}
+		gb->skip(3); // slice code
+		v->res_rtm_flag = 0;
+	} else {
+		v->res_rtm_flag = gb->getBit(); // reserved
+	}
+	// TODO: figure out what they mean (always 0x402F)
+	if (gb->pos() > gb->size())
+		return -1;
+	if (!v->res_fasttx)
+		gb->skip(16);
+	return 0;
+}
+
+static int readVC1Advanced(VC1Header *v, Common::BitStream8MSB *gb) {
+	v->res_rtm_flag = 1;
+	v->level = gb->getBits(3);
+	if (v->level >= 5) {
+		warning("Reserved LEVEL %i\n", v->level);
+	}
+	v->chromaformat = gb->getBits(2);
+	if (v->chromaformat != 1) {
+		warning("Only 4:2:0 chroma format supported\n");
+		return -1;
+	}
+
+	// (fps-2)/4 (->30)
+	v->frmrtq_postproc = gb->getBits(3); // common
+	// (bitrate-32kbps)/64kbps
+	v->bitrtq_postproc = gb->getBits(5); // common
+	v->postprocflag = gb->getBit();      // common
+
+	v->max_coded_width = (gb->getBits(12) + 1) << 1;
+	v->max_coded_height = (gb->getBits(12) + 1) << 1;
+	v->broadcast = gb->getBit();
+	v->interlace = gb->getBit();
+	v->tfcntrflag = gb->getBit();
+	v->finterpflag = gb->getBit();
+	gb->skip(1); // reserved
+
+	v->psf = gb->getBit();
+	if (v->psf) { // PsF, 6.1.13
+		warning("Progressive Segmented Frame mode: not supported (yet)\n");
+		return -1;
+	}
+	v->max_b_frames = 7;
+	if (gb->getBit()) { // Display Info - decoding is not affected by it
+		int w, h, ar = 0;
+
+		w = gb->getBits(14) + 1;
+		h = gb->getBits(14) + 1;
+
+		if (gb->getBit())
+			ar = gb->getBits(4);
+		if (ar && ar < 14) {
+			v->sample_aspect_ratio = ff_vc1_pixel_aspect[ar];
+		} else if (ar == 15) {
+			w = gb->getBits(8) + 1;
+			h = gb->getBits(8) + 1;
+			v->sample_aspect_ratio = VC1Ratio(w, h);
+		} else {
+			if (v->width > v->max_coded_width || v->height > v->max_coded_height) {
+				warning("VC-1: Huge resolution");
+			} else
+				reduceAspect(v->sample_aspect_ratio, v->height * w, v->width * h);
+		}
+
+		validateAspect(v);
+
+		if (gb->getBit()) { // framerate stuff
+			if (gb->getBit()) {
+				v->framerate.den = 32;
+				v->framerate.num = gb->getBits(16) + 1;
+			} else {
+				int nr, dr;
+				nr = gb->getBits(8);
+				dr = gb->getBits(4);
+				if (nr > 0 && nr < 8 && dr > 0 && dr < 3) {
+					v->framerate.den = ff_vc1_fps_dr[dr - 1];
+					v->framerate.num = ff_vc1_fps_nr[nr - 1] * 1000;
+				}
+			}
+		}
+
+		if (gb->getBit()) {
+			v->color_prim = gb->getBits(8);
+			v->transfer_char = gb->getBits(8);
+			v->matrix_coef = gb->getBits(8);
+		}
+	}
+
+	v->hrd_param_flag = gb->getBit();
+	if (v->hrd_param_flag) {
+		int i;
+		v->hrd_num_leaky_buckets = gb->getBits(5);
+		gb->skip(4); // bitrate exponent
+		gb->skip(4); // buffer size exponent
+		for (i = 0; i < v->hrd_num_leaky_buckets; i++) {
+			gb->skip(16); // hrd_rate[n]
+			gb->skip(16); // hrd_buffer[n]
+		}
+	}
+	return gb->pos() <= gb->size() ? 0 : -1;
+}
+
+int readVC1Entry(VC1Header *v, Common::BitStream8MSB *gb) {
+	int i;
+	int w, h;
+	int ret;
+
+	v->broken_link = gb->getBit();
+	v->closed_entry = gb->getBit();
+	v->panscanflag = gb->getBit();
+	v->refdist_flag = gb->getBit();
+	v->loop_filter = gb->getBit();
+	v->fastuvmc = gb->getBit();
+	v->extended_mv = gb->getBit();
+	v->dquant = gb->getBits(2);
+	v->vstransform = gb->getBit();
+	v->overlap = gb->getBit();
+	v->quantizer_mode = gb->getBits(2);
+
+	if (v->hrd_param_flag) {
+		for (i = 0; i < v->hrd_num_leaky_buckets; i++) {
+			gb->skip(8); // hrd_full[n]
+		}
+	}
+
+	if (gb->getBit()) {
+		w = (gb->getBits(12) + 1) << 1;
+		h = (gb->getBits(12) + 1) << 1;
+	} else {
+		w = v->max_coded_width;
+		h = v->max_coded_height;
+	}
+	if ((ret = setDimensions(v, w, h)) < 0) {
+		warning("Failed to set dimensions %d %d\n", w, h);
+		return ret;
+	}
+
+	if (v->extended_mv)
+		v->extended_dmv = gb->getBit();
+	if ((v->range_mapy_flag = gb->getBit())) {
+		warning("Luma scaling is not supported, expect wrong picture\n");
+		v->range_mapy = gb->getBits(3);
+	}
+	if ((v->range_mapuv_flag = gb->getBit())) {
+		warning("Chroma scaling is not supported, expect wrong picture\n");
+		v->range_mapuv = gb->getBits(3);
+	}
+
+	return gb->pos() <= gb->size() ? 0 : -1;
+}
+
+enum { IMODE_RAW, IMODE_NORM2, IMODE_DIFF2, IMODE_NORM6, IMODE_DIFF6, IMODE_ROWSKIP, IMODE_COLSKIP };
+
+/* BitPlane IMODE - such a small table... */
+static const uint32 vc1_imode_codes[7] = {0, 2, 1, 3, 1, 2, 3};
+static const uint8 vc1_imode_bits[7] = {4, 2, 3, 2, 4, 3, 3};
+
+/* Normal-2 imode */
+static const uint32 vc1_norm2_codes[4] = {0, 4, 5, 3};
+static const uint8 vc1_norm2_bits[4] = {1, 3, 3, 2};
+
+static const uint32 vc1_norm6_codes[64] = {
+	0x001, 0x002, 0x003, 0x000, 0x004, 0x001, 0x002, 0x047, 0x005, 0x003, 0x004, 0x04B, 0x005, 0x04D, 0x04E, 0x30E,
+	0x006, 0x006, 0x007, 0x053, 0x008, 0x055, 0x056, 0x30D, 0x009, 0x059, 0x05A, 0x30C, 0x05C, 0x30B, 0x30A, 0x037,
+	0x007, 0x00A, 0x00B, 0x043, 0x00C, 0x045, 0x046, 0x309, 0x00D, 0x049, 0x04A, 0x308, 0x04C, 0x307, 0x306, 0x036,
+	0x00E, 0x051, 0x052, 0x305, 0x054, 0x304, 0x303, 0x035, 0x058, 0x302, 0x301, 0x034, 0x300, 0x033, 0x032, 0x007,
+};
+
+static const uint8 vc1_norm6_bits[64] = {
+	1,  4,  4,  8,  4,  8,  8,  10, 4,  8,  8,  10, 8,  10, 10, 13, 4,  8,  8, 10, 8,  10,
+	10, 13, 8,  10, 10, 13, 10, 13, 13, 9,  4,  8,  8,  10, 8,  10, 10, 13, 8, 10, 10, 13,
+	10, 13, 13, 9,  8,  10, 10, 13, 10, 13, 13, 9,  10, 13, 13, 9,  13, 9,  9, 6,
+};
+
+static void initCodes(uint16 *table, uint maxBits, const uint32 *codes, const uint8 *lengths, uint count) {
+	for (uint i = 0; i < (1U << maxBits); ++i)
+		table[i] = 0xffff;
+	for (uint i = 0; i < count; ++i) {
+		uint shift = maxBits - lengths[i];
+		uint start = codes[i] << shift;
+		for (uint j = 0; j < (1U << shift); ++j)
+			table[start + j] = (i << 4) | lengths[i];
+	}
+}
+
+static int readCode(Common::BitStream8MSB &bits, const uint16 *table, uint maxBits) {
+	uint16 entry = table[bits.peekBits(maxBits)];
+	if (entry == 0xffff)
+		return -1;
+	bits.skip(entry & 15);
+	if (bits.pos() > bits.size())
+		return -1;
+	return entry >> 4;
+}
+
+// Bitplane decoding
+
+VC1Bitplane::VC1Bitplane() {
+	initCodes(_imode, 4, vc1_imode_codes, vc1_imode_bits, 7);
+	initCodes(_norm2, 3, vc1_norm2_codes, vc1_norm2_bits, 4);
+	initCodes(_norm6, 13, vc1_norm6_codes, vc1_norm6_bits, 64);
+}
+
+static void decode_rowskip(uint8 *plane, int width, int height, int stride, Common::BitStream8MSB *gb) {
+	int x, y;
+
+	for (y = 0; y < height; y++) {
+		if (!gb->getBit()) // rowskip
+			memset(plane, 0, width);
+		else
+			for (x = 0; x < width; x++)
+				plane[x] = gb->getBit();
+		plane += stride;
+	}
+}
+
+/** Decode columns by checking if they are skipped
+ * @param plane Buffer to store decoded bits
+ * @param[in] width Width of this buffer
+ * @param[in] height Height of this buffer
+ * @param[in] stride of this buffer
+ * @todo FIXME: Optimize
+ */
+static void decode_colskip(uint8 *plane, int width, int height, int stride, Common::BitStream8MSB *gb) {
+	int x, y;
+
+	for (x = 0; x < width; x++) {
+		if (!gb->getBit()) // colskip
+			for (y = 0; y < height; y++)
+				plane[y * stride] = 0;
+		else
+			for (y = 0; y < height; y++)
+				plane[y * stride] = gb->getBit();
+		plane++;
+	}
+}
+
+/** Decode a bitplane's bits
+ * @param data bitplane where to store the decode bits
+ * @param[out] raw_flag pointer to the flag indicating that this bitplane is not coded explicitly
+ * @param gb Bit stream containing the coded bitplane
+ * @return Status
+ * @todo FIXME: Optimize
+ */
+int VC1Bitplane::decode(uint8 *data, int *raw_flag, int width, int height, int stride,
+						Common::BitStream8MSB *gb) const {
+	if (!data || !raw_flag || width <= 0 || height <= 0 || stride < width)
+		return -1;
+	int imode, x, y, code, offset;
+	uint8 invert, *planep = data;
+	invert = gb->getBit();
+	imode = readCode(*gb, _imode, 4);
+
+	if (imode < 0)
+		return -1;
+	*raw_flag = 0;
+	switch (imode) {
+	case IMODE_RAW:
+		// Data is actually read in the MB layer (same for all tests == "raw")
+		*raw_flag = 1; // invert ignored
+		return gb->pos() <= gb->size() ? invert : -1;
+	case IMODE_DIFF2:
+	case IMODE_NORM2:
+		if ((height * width) & 1) {
+			*planep++ = gb->getBit();
+			y = offset = 1;
+			if (offset == width) {
+				offset = 0;
+				planep += stride - width;
+			}
+		} else
+			y = offset = 0;
+		// decode bitplane as one long line
+		for (; y < height * width; y += 2) {
+			code = readCode(*gb, _norm2, 3);
+			if (code < 0)
+				return -1;
+			*planep++ = code & 1;
+			offset++;
+			if (offset == width) {
+				offset = 0;
+				planep += stride - width;
+			}
+			*planep++ = code >> 1;
+			offset++;
+			if (offset == width) {
+				offset = 0;
+				planep += stride - width;
+			}
+		}
+		break;
+	case IMODE_DIFF6:
+	case IMODE_NORM6:
+		if (!(height % 3) && (width % 3)) { // use 2x3 decoding
+			for (y = 0; y < height; y += 3) {
+				for (x = width & 1; x < width; x += 2) {
+					code = readCode(*gb, _norm6, 13);
+					if (code < 0) {
+						return -1;
+					}
+					planep[x + 0] = (code >> 0) & 1;
+					planep[x + 1] = (code >> 1) & 1;
+					planep[x + 0 + stride] = (code >> 2) & 1;
+					planep[x + 1 + stride] = (code >> 3) & 1;
+					planep[x + 0 + stride * 2] = (code >> 4) & 1;
+					planep[x + 1 + stride * 2] = (code >> 5) & 1;
+				}
+				planep += stride * 3;
+			}
+			if (width & 1)
+				decode_colskip(data, 1, height, stride, gb);
+		} else { // 3x2
+			planep += (height & 1) * stride;
+			for (y = height & 1; y < height; y += 2) {
+				for (x = width % 3; x < width; x += 3) {
+					code = readCode(*gb, _norm6, 13);
+					if (code < 0) {
+						return -1;
+					}
+					planep[x + 0] = (code >> 0) & 1;
+					planep[x + 1] = (code >> 1) & 1;
+					planep[x + 2] = (code >> 2) & 1;
+					planep[x + 0 + stride] = (code >> 3) & 1;
+					planep[x + 1 + stride] = (code >> 4) & 1;
+					planep[x + 2 + stride] = (code >> 5) & 1;
+				}
+				planep += stride * 2;
+			}
+			x = width % 3;
+			if (x)
+				decode_colskip(data, x, height, stride, gb);
+			if (height & 1)
+				decode_rowskip(data + x, width - x, 1, stride, gb);
+		}
+		break;
+	case IMODE_ROWSKIP:
+		decode_rowskip(data, width, height, stride, gb);
+		break;
+	case IMODE_COLSKIP:
+		decode_colskip(data, width, height, stride, gb);
+		break;
+	default:
+		break;
+	}
+
+	/* Applying diff operator */
+	if (imode == IMODE_DIFF2 || imode == IMODE_DIFF6) {
+		planep = data;
+		planep[0] ^= invert;
+		for (x = 1; x < width; x++)
+			planep[x] ^= planep[x - 1];
+		for (y = 1; y < height; y++) {
+			planep += stride;
+			planep[0] ^= planep[-stride];
+			for (x = 1; x < width; x++) {
+				if (planep[x - 1] != planep[x - stride])
+					planep[x] ^= invert;
+				else
+					planep[x] ^= planep[x - 1];
+			}
+		}
+	} else if (invert) {
+		planep = data;
+		for (x = 0; x < stride * height; x++)
+			planep[x] = !planep[x]; // FIXME stride
+	}
+	return gb->pos() <= gb->size() ? (imode << 1) + invert : -1;
+}
+
+namespace VC1 {
+const VLC *ff_msmp4_mb_i_vlc;
+const VLC *ff_msmp4_dc_vlc[2][2];
+/** Table for conversion between TTBLK and TTMB */
+const int ff_vc1_ttblk_to_tt[3][8] = {
+	{TT_8X4, TT_4X8, TT_8X8, TT_4X4, TT_8X4_TOP, TT_8X4_BOTTOM, TT_4X8_RIGHT, TT_4X8_LEFT},
+	{TT_8X8, TT_4X8_RIGHT, TT_4X8_LEFT, TT_4X4, TT_8X4, TT_4X8, TT_8X4_BOTTOM, TT_8X4_TOP},
+	{TT_8X8, TT_4X8, TT_4X4, TT_8X4_BOTTOM, TT_4X8_RIGHT, TT_4X8_LEFT, TT_8X4, TT_8X4_TOP}};
+
+const int ff_vc1_ttfrm_to_tt[4] = {TT_8X8, TT_8X4, TT_4X8, TT_4X4};
+
+/** MV P mode - the 5th element is only used for mode 1 */
+const uint8 ff_vc1_mv_pmode_table[2][5] = {
+	{MV_PMODE_1MV_HPEL_BILIN, MV_PMODE_1MV, MV_PMODE_1MV_HPEL, MV_PMODE_INTENSITY_COMP, MV_PMODE_MIXED_MV},
+	{MV_PMODE_1MV, MV_PMODE_MIXED_MV, MV_PMODE_1MV_HPEL, MV_PMODE_INTENSITY_COMP, MV_PMODE_1MV_HPEL_BILIN}};
+const uint8 ff_vc1_mv_pmode_table2[2][4] = {
+	{MV_PMODE_1MV_HPEL_BILIN, MV_PMODE_1MV, MV_PMODE_1MV_HPEL, MV_PMODE_MIXED_MV},
+	{MV_PMODE_1MV, MV_PMODE_MIXED_MV, MV_PMODE_1MV_HPEL, MV_PMODE_1MV_HPEL_BILIN}};
+
+/* MBMODE table for interlaced frame P-picture */
+const uint8 ff_vc1_mbmode_intfrp[2][15][4] = {{/* 1: 4-MV, 0: non-4-MV */
+											   /* Type, FIELDTX, 1-MV Differential present, Residuals (CBP) present */
+											   /* Table 164 - Table 167 */
+											   {MV_PMODE_INTFR_1MV, 0, 1, 1},
+											   {MV_PMODE_INTFR_1MV, 1, 1, 1},
+											   {MV_PMODE_INTFR_1MV, 0, 1, 0},
+											   {MV_PMODE_INTFR_1MV, 0, 0, 1},
+											   {MV_PMODE_INTFR_1MV, 1, 0, 1},
+											   {MV_PMODE_INTFR_2MV_FIELD, 0, 0, 1},
+											   {MV_PMODE_INTFR_2MV_FIELD, 1, 0, 1},
+											   {MV_PMODE_INTFR_2MV_FIELD, 1, 0, 0},
+											   {MV_PMODE_INTFR_INTRA, 0, 0, 0}},
+											  {/* Table 160 - Table 163 */
+											   {MV_PMODE_INTFR_1MV, 0, 1, 1},
+											   {MV_PMODE_INTFR_1MV, 1, 1, 1},
+											   {MV_PMODE_INTFR_1MV, 0, 1, 0},
+											   {MV_PMODE_INTFR_1MV, 0, 0, 1},
+											   {MV_PMODE_INTFR_1MV, 1, 0, 1},
+											   {MV_PMODE_INTFR_2MV_FIELD, 0, 0, 1},
+											   {MV_PMODE_INTFR_2MV_FIELD, 1, 0, 1},
+											   {MV_PMODE_INTFR_2MV_FIELD, 1, 0, 0},
+											   {MV_PMODE_INTFR_4MV, 0, 0, 1},
+											   {MV_PMODE_INTFR_4MV, 1, 0, 1},
+											   {MV_PMODE_INTFR_4MV, 0, 0, 0},
+											   {MV_PMODE_INTFR_4MV_FIELD, 0, 0, 1},
+											   {MV_PMODE_INTFR_4MV_FIELD, 1, 0, 1},
+											   {MV_PMODE_INTFR_4MV_FIELD, 1, 0, 0},
+											   {MV_PMODE_INTFR_INTRA, 0, 0, 0}}};
+
+const int ff_vc1_fps_nr[7] = {24, 25, 30, 50, 60, 48, 72}, ff_vc1_fps_dr[2] = {1000, 1001};
+const uint8 ff_vc1_pquant_table[3][32] = {
+	/* Implicit quantizer */
+	{0, 1, 2, 3, 4, 5, 6, 7, 8, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 27, 29, 31},
+	/* Explicit quantizer, pquantizer uniform */
+	{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},
+	/* Explicit quantizer, pquantizer non-uniform */
+	{0,  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, 24, 25, 26, 27, 29, 31}};
+
+/** @name VC-1 VLC tables
+ *  @todo TODO move this into the context
+ */
+//@{
+const VLC *ff_vc1_imode_vlc;
+const VLC *ff_vc1_norm2_vlc;
+const VLC *ff_vc1_norm6_vlc;
+const VLC *ff_vc1_ttmb_vlc[3];
+const VLC *ff_vc1_mv_diff_vlc[4];
+const VLC *ff_vc1_cbpcy_p_vlc[4];
+const VLC *ff_vc1_icbpcy_vlc[8];
+const VLC *ff_vc1_4mv_block_pattern_vlc[4];
+const VLC *ff_vc1_2mv_block_pattern_vlc[4];
+const VLC *ff_vc1_ttblk_vlc[3];
+const VLC *ff_vc1_subblkpat_vlc[3];
+const VLC *ff_vc1_intfr_4mv_mbmode_vlc[4];
+const VLC *ff_vc1_intfr_non4mv_mbmode_vlc[4];
+const VLC *ff_vc1_if_mmv_mbmode_vlc[8];
+const VLC *ff_vc1_if_1mv_mbmode_vlc[8];
+const VLC *ff_vc1_1ref_mvdata_vlc[4];
+const VLC *ff_vc1_2ref_mvdata_vlc[8];
+
+const VLC *ff_vc1_ac_coeff_table[8];
+
+//@}
+
+#if B_FRACTION_DEN == 840 // original bfraction from vc9data.h, not conforming to standard
+/* bfraction is fractional, we scale to the GCD 3*5*7*8 = 840 */
+const int16 ff_vc1_bfraction_lut[23] = {
+	420 /*1/2*/,
+	280 /*1/3*/,
+	560 /*2/3*/,
+	210 /*1/4*/,
+	630 /*3/4*/,
+	168 /*1/5*/,
+	336 /*2/5*/,
+	504 /*3/5*/,
+	672 /*4/5*/,
+	140 /*1/6*/,
+	700 /*5/6*/,
+	120 /*1/7*/,
+	240 /*2/7*/,
+	360 /*3/7*/,
+	480 /*4/7*/,
+	600 /*5/7*/,
+	720 /*6/7*/,
+	105 /*1/8*/,
+	315 /*3/8*/,
+	525 /*5/8*/,
+	735 /*7/8*/,
+	-1 /*inv.*/,
+	0 /*BI fm*/
+};
+#else
+/* pre-computed scales for all bfractions and base=256 */
+const int16 ff_vc1_bfraction_lut[23] = {
+	128 /*1/2*/,
+	85 /*1/3*/,
+	170 /*2/3*/,
+	64 /*1/4*/,
+	192 /*3/4*/,
+	51 /*1/5*/,
+	102 /*2/5*/,
+	153 /*3/5*/,
+	204 /*4/5*/,
+	43 /*1/6*/,
+	215 /*5/6*/,
+	37 /*1/7*/,
+	74 /*2/7*/,
+	111 /*3/7*/,
+	148 /*4/7*/,
+	185 /*5/7*/,
+	222 /*6/7*/,
+	32 /*1/8*/,
+	96 /*3/8*/,
+	160 /*5/8*/,
+	224 /*7/8*/,
+	-1 /*inv.*/,
+	0 /*BI fm*/
+};
+#endif
+
+// Same as H.264
+const VC1Ratio ff_vc1_pixel_aspect[16] = {{0, 1},   {1, 1},    {12, 11}, {10, 11}, {16, 11}, {40, 33},
+										  {24, 11}, {20, 11},  {32, 11}, {80, 33}, {18, 11}, {15, 11},
+										  {64, 33}, {160, 99}, {0, 1},   {0, 1}};
+
+const uint8 ff_wmv3_dc_scale_table[32] = {0,  2,  4,  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};
+
+/* DC differentials low+hi-mo, p217 are the same as in msmpeg4data .h */
+
+/* Table 232 */
+const uint8 ff_vc1_simple_progressive_4x4_zz[16] = {0, 8, 16, 1, 9, 24, 17, 2, 10, 18, 25, 3, 11, 26, 19, 27};
+
+const uint8 ff_vc1_adv_progressive_8x4_zz[32] = {/* Table 233 */
+												 0,  8,  1,  16, 2,  9, 10, 3,  24, 17, 4,  11, 18, 12, 5,  19,
+												 25, 13, 20, 26, 27, 6, 21, 28, 14, 22, 29, 7,  30, 15, 23, 31};
+
+const uint8 ff_vc1_adv_progressive_4x8_zz[32] = {/* Table 234 */
+												 0,  1,  8,  2,  9,  16, 17, 24, 10, 32, 25, 18, 40, 3,  33, 26,
+												 48, 11, 56, 41, 34, 49, 57, 42, 19, 50, 27, 58, 35, 43, 51, 59};
+
+const uint8 ff_vc1_adv_interlaced_8x8_zz[64] = {/* Table 235 */
+												0,  8,  1,  16, 24, 9,  2,  32, 40, 48, 56, 17, 10, 3,  25, 18,
+												11, 4,  33, 41, 49, 57, 26, 34, 42, 50, 58, 19, 12, 5,  27, 20,
+												13, 6,  35, 28, 21, 14, 7,  15, 22, 29, 36, 43, 51, 59, 60, 52,
+												44, 37, 30, 23, 31, 38, 45, 53, 61, 62, 54, 46, 39, 47, 55, 63};
+
+const uint8 ff_vc1_adv_interlaced_8x4_zz[32] = {/* Table 236 */
+												0,  8, 16, 24, 1,  9, 2,  17, 25, 10, 3,  18, 26, 4,  11, 19,
+												12, 5, 13, 20, 27, 6, 21, 28, 14, 22, 29, 7,  30, 15, 23, 31};
+
+const uint8 ff_vc1_adv_interlaced_4x8_zz[32] = {/* Table 237 */
+												0,  1,  2,  8,  16, 9,  24, 17, 10, 3,  32, 40, 48, 56, 25, 18,
+												33, 26, 41, 34, 49, 57, 11, 42, 19, 50, 27, 58, 35, 43, 51, 59};
+
+const uint8 ff_vc1_adv_interlaced_4x4_zz[16] = {/* Table 238 */
+												0, 8, 16, 24, 1, 9, 17, 2, 25, 10, 18, 3, 26, 11, 19, 27};
+
+/* DQScale as specified in 8.1.3.9 - almost identical to 0x40000/i */
+const int32 ff_vc1_dqscale[63] = {
+	0x40000, 0x20000, 0x15555, 0x10000, 0xCCCD, 0xAAAB, 0x9249, 0x8000, 0x71C7, 0x6666, 0x5D17, 0x5555, 0x4EC5,
+	0x4925,  0x4444,  0x4000,  0x3C3C,  0x38E4, 0x35E5, 0x3333, 0x30C3, 0x2E8C, 0x2C86, 0x2AAB, 0x28F6, 0x2762,
+	0x25ED,  0x2492,  0x234F,  0x2222,  0x2108, 0x2000, 0x1F08, 0x1E1E, 0x1D42, 0x1C72, 0x1BAD, 0x1AF3, 0x1A42,
+	0x199A,  0x18FA,  0x1862,  0x17D0,  0x1746, 0x16C1, 0x1643, 0x15CA, 0x1555, 0x14E6, 0x147B, 0x1414, 0x13B1,
+	0x1352,  0x12F7,  0x129E,  0x1249,  0x11F7, 0x11A8, 0x115B, 0x1111, 0x10C9, 0x1084, 0x1041};
+
+/* P Interlaced field picture MV predictor scaling values (Table 114) */
+const uint16 ff_vc1_field_mvpred_scales[2][7][4] = {
+	// Refdist:
+	//      0       1       2       3 or greater
+	{
+		// current field is first
+		{128, 192, 213, 224}, // SCALEOPP
+		{512, 341, 307, 293}, // SCALESAME1
+		{219, 236, 242, 245}, // SCALESAME2
+		{32, 48, 53, 56},     // SCALEZONE1_X
+		{8, 12, 13, 14},      // SCALEZONE1_Y
+		{37, 20, 14, 11},     // ZONE1OFFSET_X
+		{10, 5, 4, 3}         // ZONE1OFFSET_Y
+	},
+	{
+		// current field is second
+		{128, 64, 43, 32},       // SCALEOPP
+		{512, 1024, 1536, 2048}, // SCALESAME1
+		{219, 204, 200, 198},    // SCALESAME2
+		{32, 16, 11, 8},         // SCALEZONE1_X
+		{8, 4, 3, 2},            // SCALEZONE1_Y
+		{37, 52, 56, 58},        // ZONE1OFFSET_X
+		{10, 13, 14, 15}         // ZONE1OFFSET_Y
+	}};
+
+/* B Interlaced field picture backward MV predictor scaling values for first field (Table 115) */
+const uint16 ff_vc1_b_field_mvpred_scales[7][4] = {
+	// BRFD:
+	//  0       1       2       3 or greater
+	{171, 205, 219, 228}, // SCALESAME
+	{384, 320, 299, 288}, // SCALEOPP1
+	{230, 239, 244, 246}, // SCALEOPP2
+	{43, 51, 55, 57},     // SCALEZONE1_X
+	{11, 13, 14, 14},     // SCALEZONE1_Y
+	{26, 17, 12, 10},     // ZONE1OFFSET_X
+	{7, 4, 3, 3}          // ZONE1OFFSET_Y
+};
+
+const uint8 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,
+	}};
+
+// VLC table initialization
+
+void initTables() {
+
+	ff_vc1_norm2_vlc = makeVLC(4, vc1_norm2_bits, 1, 1, vc1_norm2_codes, 1, 1);
+	ff_vc1_norm6_vlc = makeVLC(64, vc1_norm6_bits, 1, 1, vc1_norm6_codes, 2, 2);
+	ff_vc1_imode_vlc = makeVLC(7, vc1_imode_bits, 1, 1, vc1_imode_codes, 1, 1);
+	for (int i = 0; i < 3; i++) {
+		ff_vc1_ttmb_vlc[i] = makeVLC(16, vc1_ttmb_bits[i], 1, 1, vc1_ttmb_codes[i], 2, 2);
+		ff_vc1_ttblk_vlc[i] = makeVLC(8, vc1_ttblk_bits[i], 1, 1, vc1_ttblk_codes[i], 1, 1);
+		ff_vc1_subblkpat_vlc[i] = makeVLC(15, vc1_subblkpat_bits[i], 1, 1, vc1_subblkpat_codes[i], 1, 1);
+	}
+	for (int i = 0; i < 4; i++) {
+		ff_vc1_4mv_block_pattern_vlc[i] =
+			makeVLC(16, vc1_4mv_block_pattern_bits[i], 1, 1, vc1_4mv_block_pattern_codes[i], 1, 1);
+		ff_vc1_cbpcy_p_vlc[i] = makeVLC(64, vc1_cbpcy_p_bits[i], 1, 1, vc1_cbpcy_p_codes[i], 2, 2);
+		ff_vc1_mv_diff_vlc[i] = makeVLC(73, vc1_mv_diff_bits[i], 1, 1, vc1_mv_diff_codes[i], 2, 2);
+		/* initialize 4MV MBMODE VLC tables for interlaced frame P picture */
+		ff_vc1_intfr_4mv_mbmode_vlc[i] =
+			makeVLC(15, vc1_intfr_4mv_mbmode_bits[i], 1, 1, vc1_intfr_4mv_mbmode_codes[i], 2, 2);
+		/* initialize NON-4MV MBMODE VLC tables for the same */
+		ff_vc1_intfr_non4mv_mbmode_vlc[i] =
+			makeVLC(9, vc1_intfr_non4mv_mbmode_bits[i], 1, 1, vc1_intfr_non4mv_mbmode_codes[i], 1, 1);
+		/* initialize interlaced MVDATA tables (1-Ref) */
+		ff_vc1_1ref_mvdata_vlc[i] = makeVLC(72, vc1_1ref_mvdata_bits[i], 1, 1, vc1_1ref_mvdata_codes[i], 4, 4);
+		/* Initialize 2MV Block pattern VLC tables */
+		ff_vc1_2mv_block_pattern_vlc[i] =
+			makeVLC(4, vc1_2mv_block_pattern_bits[i], 1, 1, vc1_2mv_block_pattern_codes[i], 1, 1);
+	}
+	for (int i = 0; i < 8; i++) {
+		ff_vc1_ac_coeff_table[i] =
+			makeVLC(ff_vc1_ac_sizes[i], &vc1_ac_tables[i][0][1], 8, 4, &vc1_ac_tables[i][0][0], 8, 4);
+		/* initialize interlaced MVDATA tables (2-Ref) */
+		ff_vc1_2ref_mvdata_vlc[i] = makeVLC(126, vc1_2ref_mvdata_bits[i], 1, 1, vc1_2ref_mvdata_codes[i], 4, 4);
+		/* Initialize interlaced CBPCY VLC tables (Table 124 - Table 131) */
+		ff_vc1_icbpcy_vlc[i] = makeVLC(63, vc1_icbpcy_p_bits[i], 1, 1, vc1_icbpcy_p_codes[i], 2, 2);
+		/* Initialize interlaced field picture MBMODE VLC tables */
+		ff_vc1_if_mmv_mbmode_vlc[i] = makeVLC(8, vc1_if_mmv_mbmode_bits[i], 1, 1, vc1_if_mmv_mbmode_codes[i], 1, 1);
+		ff_vc1_if_1mv_mbmode_vlc[i] = makeVLC(6, vc1_if_1mv_mbmode_bits[i], 1, 1, vc1_if_1mv_mbmode_codes[i], 1, 1);
+	}
+	for (int i = 0; i < 2; ++i)
+		for (int j = 0; j < 2; ++j)
+			ff_msmp4_dc_vlc[i][j] =
+				makeVLC(120, &ff_msmp4_dc_tables[i][j][0][1], 8, 4, &ff_msmp4_dc_tables[i][j][0][0], 8, 4);
+	ff_msmp4_mb_i_vlc = makeVLC(64, &ff_msmp4_mb_i_table[0][1], 4, 2, &ff_msmp4_mb_i_table[0][0], 4, 2);
+}
+
+// Scalar reconstruction helpers
+
+static uint32 tableValue(const void *p, int size) {
+	if (size == 1)
+		return *(const uint8 *)p;
+	if (size == 2)
+		return READ_UINT16(p);
+	return READ_UINT32(p);
+}
+
+const VLC *makeVLC(int count, const void *lengths, int ls, int lz, const void *codes, int cs, int cz) {
+	VLC *v = new VLC;
+	v->nodes.push_back(VLC::Node());
+	for (int i = 0; i < count; ++i) {
+		int length = tableValue((const uint8 *)lengths + i * ls, lz);
+		if (!length)
+			continue;
+		uint32 code = tableValue((const uint8 *)codes + i * cs, cz);
+		int at = 0;
+		for (int k = length - 1; k >= 0; --k) {
+			int bit = (code >> k) & 1;
+			int next = v->nodes[at].child[bit];
+			if (next < 0) {
+				next = v->nodes.size();
+				v->nodes[at].child[bit] = next;
+				v->nodes.push_back(VLC::Node());
+			}
+			at = next;
+		}
+		assert(v->nodes[at].symbol == -1);
+		v->nodes[at].symbol = i;
+	}
+	return v;
+}
+
+int get_vlc2(Bits *b, const VLC *v) {
+	int at = 0;
+	if (!v)
+		return -1;
+	for (int k = 0; k < 32; ++k) {
+		if (v->nodes[at].symbol >= 0)
+			return v->nodes[at].symbol;
+		if (get_bits_left(b) <= 0)
+			return -1;
+		at = v->nodes[at].child[get_bits1(b)];
+		if (at < 0)
+			return -1;
+	}
+	return -1;
+}
+
+static void clearBlock(int16 *p) {
+	memset(p, 0, 64 * sizeof(*p));
+}
+static void clearBlocks(int16 *p) {
+	memset(p, 0, 6 * 64 * sizeof(*p));
+}
+template<int mode> static void clampBlock(const int16 *b, uint8 *d, ptrdiff_t stride) {
+	for (int y = 0; y < 8; ++y) {
+		for (int x = 0; x < 8; ++x)
+			d[x] = av_clip_uint8(b[y * 8 + x] + (mode == 1 ? 128 : mode == 2 ? d[x] : 0));
+		d += stride;
+	}
+}
+
+template<int width, int xy, bool round, bool average>
+static void halfPixels(uint8 *d, const uint8 *s, ptrdiff_t stride, int h) {
+	putHalfPixels<width>(d, s, stride, h, xy, !round, average);
+}
+
+template<int width, bool average>
+static void chromaPixels(uint8 *d, const uint8 *s, ptrdiff_t stride, int h, int x, int y) {
+	int a = (8 - x) * (8 - y), b = x * (8 - y), c = (8 - x) * y, e = x * y;
+	for (int row = 0; row < h; ++row) {
+		for (int col = 0; col < width; ++col) {
+			int value = (a * s[col] + b * s[col + 1] + c * s[col + stride] + e * s[col + stride + 1] + 32) >> 6;
+			d[col] = average ? (d[col] + value + 1) >> 1 : value;
+		}
+		d += stride;
+		s += stride;
+	}
+}
+
+static void edgePixels(uint8 *dst, const uint8 *src, ptrdiff_t ds, ptrdiff_t ss, int bw, int bh, int x, int y, int w,
+					   int h) {
+	for (int row = 0; row < bh; ++row) {
+		int sy = CLIP(y + row, 0, h - 1) - y;
+		for (int col = 0; col < bw; ++col)
+			dst[col] = src[sy * ss + CLIP(x + col, 0, w - 1) - x];
+		dst += ds;
+	}
+}
+
+void initSupport(PictureState *s, ChromaDSP *c) {
+	s->bdsp.clear_block = clearBlock;
+	s->bdsp.clear_blocks = clearBlocks;
+	s->idsp.put_pixels_clamped = clampBlock<0>;
+	s->idsp.put_signed_pixels_clamped = clampBlock<1>;
+	s->idsp.add_pixels_clamped = clampBlock<2>;
+	s->vdsp.emulated_edge_mc = edgePixels;
+#define H(w, i, xy)                                                                                                    \
+	s->hdsp.put_pixels_tab[i][xy] = halfPixels<w, xy, true, false>;                                                    \
+	s->hdsp.put_no_rnd_pixels_tab[i][xy] = halfPixels<w, xy, false, false>;                                            \
+	s->hdsp.avg_pixels_tab[i][xy] = halfPixels<w, xy, true, true>;
+	H(16, 0, 0)
+	H(16, 0, 1)
+	H(16, 0, 2)
+	H(16, 0, 3)
+	H(8, 1, 0)
+	H(8, 1, 1)
+	H(8, 1, 2)
+	H(8, 1, 3)
+#undef H
+		s->hdsp.avg_no_rnd_pixels_tab[0] = halfPixels<16, 0, false, true>;
+	s->hdsp.avg_no_rnd_pixels_tab[1] = halfPixels<16, 1, false, true>;
+	s->hdsp.avg_no_rnd_pixels_tab[2] = halfPixels<16, 2, false, true>;
+	s->hdsp.avg_no_rnd_pixels_tab[3] = halfPixels<16, 3, false, true>;
+	c->put_h264_chroma_pixels_tab[0] = chromaPixels<8, false>;
+	c->put_h264_chroma_pixels_tab[1] = chromaPixels<4, false>;
+	c->put_h264_chroma_pixels_tab[2] = chromaPixels<2, false>;
+	c->avg_h264_chroma_pixels_tab[0] = chromaPixels<8, true>;
+	c->avg_h264_chroma_pixels_tab[1] = chromaPixels<4, true>;
+	c->avg_h264_chroma_pixels_tab[2] = chromaPixels<2, true>;
+}
+
+void ff_init_block_index(PictureState *s) {
+	const int linesize = s->cur_pic.linesize[0], uvlinesize = s->cur_pic.linesize[1];
+	s->block_index[0] = s->b8_stride * (s->mb_y * 2) - 2 + s->mb_x * 2;
+	s->block_index[1] = s->b8_stride * (s->mb_y * 2) - 1 + s->mb_x * 2;
+	s->block_index[2] = s->b8_stride * (s->mb_y * 2 + 1) - 2 + s->mb_x * 2;
+	s->block_index[3] = s->b8_stride * (s->mb_y * 2 + 1) - 1 + s->mb_x * 2;
+	s->block_index[4] = s->mb_stride * (s->mb_y + 1) + s->b8_stride * s->mb_height * 2 + s->mb_x - 1;
+	s->block_index[5] = s->mb_stride * (s->mb_y + s->mb_height + 2) + s->b8_stride * s->mb_height * 2 + s->mb_x - 1;
+	s->dest[0] = s->cur_pic.data[0] + (s->mb_x - 1) * 16 + s->mb_y * linesize * 16;
+	s->dest[1] = s->cur_pic.data[1] + (s->mb_x - 1) * 8 + s->mb_y * uvlinesize * 8;
+	s->dest[2] = s->cur_pic.data[2] + (s->mb_x - 1) * 8 + s->mb_y * uvlinesize * 8;
+}
+
+void ff_update_block_index(PictureState *s, int, int, int) {
+	for (int i = 0; i < 4; ++i)
+		s->block_index[i] += 2;
+	++s->block_index[4];
+	++s->block_index[5];
+	s->dest[0] += 16;
+	s->dest[1] += 8;
+	s->dest[2] += 8;
+}
+
+/**
+ * @file
+ * simpleidct in C.
+ */
+/* Based upon some commented-out C code from mpeg2dec (idct_mmx.c
+ * written by Aaron Holtzman <aholtzma at ess.engr.uvic.ca>). */
+static inline void idctRowCondDC_int16_8bit(int16 *row, int extra_shift) {
+	unsigned a0, a1, a2, a3, b0, b1, b2, b3;
+	// TODO: Add DC-only support for int32 input
+	if (!(READ_UINT32(row + 2) | READ_UINT32(row + 4) | READ_UINT32(row + 6) | row[1])) {
+		uint32 temp;
+		if (3 - extra_shift >= 0) {
+			temp = (row[0] * (1 << (3 - extra_shift))) & 0xffff;
+		} else {
+			temp = ((row[0] + (1 << (extra_shift - 3 - 1))) >> (extra_shift - 3)) & 0xffff;
+		}
+		temp += temp * (1 << 16);
+		WRITE_UINT32(row, temp);
+		WRITE_UINT32(row + 2, temp);
+		WRITE_UINT32(row + 4, temp);
+		WRITE_UINT32(row + 6, temp);
+		return;
+	}
+	a0 = ((unsigned)16383 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * row[0]) + (1 << (11 + extra_shift - 1));
+	a1 = a0;
+	a2 = a0;
+	a3 = a0;
+	a0 += (unsigned)21407 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * row[2];
+	a1 += (unsigned)8867 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * row[2];
+	a2 -= (unsigned)8867 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * row[2];
+	a3 -= (unsigned)21407 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * row[2];
+	b0 = ((22725 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (row[1]));
+	((b0) += (19266 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (row[3]));
+	b1 = ((19266 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (row[1]));
+	((b1) += (-4520 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (row[3]));
+	b2 = ((12873 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (row[1]));
+	((b2) += (-22725 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (row[3]));
+	b3 = ((4520 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (row[1]));
+	((b3) += (-12873 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (row[3]));
+	if (READ_UINT64(row + 4)) {
+		a0 += (unsigned)16383 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * row[4] +
+			  (unsigned)8867 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * row[6];
+		a1 += (unsigned)-16383 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * row[4] -
+			  (unsigned)21407 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * row[6];
+		a2 += (unsigned)-16383 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * row[4] +
+			  (unsigned)21407 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * row[6];
+		a3 += (unsigned)16383 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * row[4] -
+			  (unsigned)8867 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * row[6];
+		((b0) += (12873 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (row[5]));
+		((b0) += (4520 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (row[7]));
+		((b1) += (-22725 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (row[5]));
+		((b1) += (-12873 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (row[7]));
+		((b2) += (4520 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (row[5]));
+		((b2) += (19266 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (row[7]));
+		((b3) += (19266 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (row[5]));
+		((b3) += (-22725 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (row[7]));
+	}
+	row[0] = (int)(a0 + b0) >> (11 + extra_shift);
+	row[7] = (int)(a0 - b0) >> (11 + extra_shift);
+	row[1] = (int)(a1 + b1) >> (11 + extra_shift);
+	row[6] = (int)(a1 - b1) >> (11 + extra_shift);
+	row[2] = (int)(a2 + b2) >> (11 + extra_shift);
+	row[5] = (int)(a2 - b2) >> (11 + extra_shift);
+	row[3] = (int)(a3 + b3) >> (11 + extra_shift);
+	row[4] = (int)(a3 - b3) >> (11 + extra_shift);
+}
+
+static inline void idctSparseCol_int16_8bit(int16 *col) {
+	unsigned a0, a1, a2, a3, b0, b1, b2, b3;
+	do {
+		a0 = (unsigned)16383 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ *
+			 (col[8 * 0] + ((1 << (20 - 1)) / 16383 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/));
+		a1 = a0;
+		a2 = a0;
+		a3 = a0;
+		a0 += (unsigned)21407 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 2];
+		a1 += (unsigned)8867 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 2];
+		a2 += (unsigned)-8867 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 2];
+		a3 += (unsigned)-21407 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 2];
+		b0 = ((22725 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 1]));
+		b1 = ((19266 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 1]));
+		b2 = ((12873 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 1]));
+		b3 = ((4520 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 1]));
+		((b0) += (19266 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 3]));
+		((b1) += (-4520 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 3]));
+		((b2) += (-22725 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 3]));
+		((b3) += (-12873 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 3]));
+		if (col[8 * 4]) {
+			a0 += (unsigned)16383 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 4];
+			a1 += (unsigned)-16383 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 4];
+			a2 += (unsigned)-16383 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 4];
+			a3 += (unsigned)16383 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 4];
+		}
+		if (col[8 * 5]) {
+			((b0) += (12873 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 5]));
+			((b1) += (-22725 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 5]));
+			((b2) += (4520 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 5]));
+			((b3) += (19266 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 5]));
+		}
+		if (col[8 * 6]) {
+			a0 += (unsigned)8867 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 6];
+			a1 += (unsigned)-21407 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 6];
+			a2 += (unsigned)21407 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 6];
+			a3 += (unsigned)-8867 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 6];
+		}
+		if (col[8 * 7]) {
+			((b0) += (4520 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 7]));
+			((b1) += (-12873 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 7]));
+			((b2) += (19266 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 7]));
+			((b3) += (-22725 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 7]));
+		}
+	} while (0);
+	col[0] = ((int)(a0 + b0) >> 20);
+	col[8] = ((int)(a1 + b1) >> 20);
+	col[16] = ((int)(a2 + b2) >> 20);
+	col[24] = ((int)(a3 + b3) >> 20);
+	col[32] = ((int)(a3 - b3) >> 20);
+	col[40] = ((int)(a2 - b2) >> 20);
+	col[48] = ((int)(a1 - b1) >> 20);
+	col[56] = ((int)(a0 - b0) >> 20);
+}
+
+static inline void idctSparseColPut_int16_8bit(uint8 *dest, ptrdiff_t line_size, int16 *col) {
+	unsigned a0, a1, a2, a3, b0, b1, b2, b3;
+	do {
+		a0 = (unsigned)16383 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ *
+			 (col[8 * 0] + ((1 << (20 - 1)) / 16383 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/));
+		a1 = a0;
+		a2 = a0;
+		a3 = a0;
+		a0 += (unsigned)21407 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 2];
+		a1 += (unsigned)8867 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 2];
+		a2 += (unsigned)-8867 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 2];
+		a3 += (unsigned)-21407 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 2];
+		b0 = ((22725 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 1]));
+		b1 = ((19266 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 1]));
+		b2 = ((12873 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 1]));
+		b3 = ((4520 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 1]));
+		((b0) += (19266 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 3]));
+		((b1) += (-4520 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 3]));
+		((b2) += (-22725 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 3]));
+		((b3) += (-12873 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 3]));
+		if (col[8 * 4]) {
+			a0 += (unsigned)16383 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 4];
+			a1 += (unsigned)-16383 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 4];
+			a2 += (unsigned)-16383 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 4];
+			a3 += (unsigned)16383 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 4];
+		}
+		if (col[8 * 5]) {
+			((b0) += (12873 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 5]));
+			((b1) += (-22725 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 5]));
+			((b2) += (4520 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 5]));
+			((b3) += (19266 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 5]));
+		}
+		if (col[8 * 6]) {
+			a0 += (unsigned)8867 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 6];
+			a1 += (unsigned)-21407 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 6];
+			a2 += (unsigned)21407 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 6];
+			a3 += (unsigned)-8867 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 6];
+		}
+		if (col[8 * 7]) {
+			((b0) += (4520 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 7]));
+			((b1) += (-12873 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 7]));
+			((b2) += (19266 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 7]));
+			((b3) += (-22725 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 7]));
+		}
+	} while (0);
+	dest[0] = av_clip_uint8((int)(a0 + b0) >> 20);
+	dest += line_size;
+	dest[0] = av_clip_uint8((int)(a1 + b1) >> 20);
+	dest += line_size;
+	dest[0] = av_clip_uint8((int)(a2 + b2) >> 20);
+	dest += line_size;
+	dest[0] = av_clip_uint8((int)(a3 + b3) >> 20);
+	dest += line_size;
+	dest[0] = av_clip_uint8((int)(a3 - b3) >> 20);
+	dest += line_size;
+	dest[0] = av_clip_uint8((int)(a2 - b2) >> 20);
+	dest += line_size;
+	dest[0] = av_clip_uint8((int)(a1 - b1) >> 20);
+	dest += line_size;
+	dest[0] = av_clip_uint8((int)(a0 - b0) >> 20);
+}
+
+static inline void idctSparseColAdd_int16_8bit(uint8 *dest, ptrdiff_t line_size, int16 *col) {
+	unsigned a0, a1, a2, a3, b0, b1, b2, b3;
+	do {
+		a0 = (unsigned)16383 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ *
+			 (col[8 * 0] + ((1 << (20 - 1)) / 16383 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/));
+		a1 = a0;
+		a2 = a0;
+		a3 = a0;
+		a0 += (unsigned)21407 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 2];
+		a1 += (unsigned)8867 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 2];
+		a2 += (unsigned)-8867 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 2];
+		a3 += (unsigned)-21407 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 2];
+		b0 = ((22725 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 1]));
+		b1 = ((19266 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 1]));
+		b2 = ((12873 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 1]));
+		b3 = ((4520 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 1]));
+		((b0) += (19266 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 3]));
+		((b1) += (-4520 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 3]));
+		((b2) += (-22725 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 3]));
+		((b3) += (-12873 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 3]));
+		if (col[8 * 4]) {
+			a0 += (unsigned)16383 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 4];
+			a1 += (unsigned)-16383 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 4];
+			a2 += (unsigned)-16383 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 4];
+			a3 += (unsigned)16383 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 4];
+		}
+		if (col[8 * 5]) {
+			((b0) += (12873 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 5]));
+			((b1) += (-22725 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 5]));
+			((b2) += (4520 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 5]));
+			((b3) += (19266 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 5]));
+		}
+		if (col[8 * 6]) {
+			a0 += (unsigned)8867 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 6];
+			a1 += (unsigned)-21407 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 6];
+			a2 += (unsigned)21407 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 6];
+			a3 += (unsigned)-8867 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/ * col[8 * 6];
+		}
+		if (col[8 * 7]) {
+			((b0) += (4520 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 7]));
+			((b1) += (-12873 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 7]));
+			((b2) += (19266 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 7]));
+			((b3) += (-22725 /*cos(i*M_PI/16)*sqrt(2)*(1<<14) + 0.5*/) * (col[8 * 7]));
+		}
+	} while (0);
+	dest[0] = av_clip_uint8(dest[0] + ((int)(a0 + b0) >> 20));
+	dest += line_size;
+	dest[0] = av_clip_uint8(dest[0] + ((int)(a1 + b1) >> 20));
+	dest += line_size;
+	dest[0] = av_clip_uint8(dest[0] + ((int)(a2 + b2) >> 20));
+	dest += line_size;
+	dest[0] = av_clip_uint8(dest[0] + ((int)(a3 + b3) >> 20));
+	dest += line_size;
+	dest[0] = av_clip_uint8(dest[0] + ((int)(a3 - b3) >> 20));
+	dest += line_size;
+	dest[0] = av_clip_uint8(dest[0] + ((int)(a2 - b2) >> 20));
+	dest += line_size;
+	dest[0] = av_clip_uint8(dest[0] + ((int)(a1 - b1) >> 20));
+	dest += line_size;
+	dest[0] = av_clip_uint8(dest[0] + ((int)(a0 - b0) >> 20));
+}
+
+void ff_simple_idct_put_int16_8bit(uint8 *dest_, ptrdiff_t line_size, int16 *block_) {
+	int16 *block = (int16 *)block_;
+	uint8 *dest = (uint8 *)dest_;
+	int i;
+	line_size /= sizeof(uint8);
+	for (i = 0; i < 8; i++)
+		idctRowCondDC_int16_8bit(block + i * 8, 0);
+	for (i = 0; i < 8; i++)
+		idctSparseColPut_int16_8bit(dest + i, line_size, block + i);
+}
+
+void ff_simple_idct_add_int16_8bit(uint8 *dest_, ptrdiff_t line_size, int16 *block) {
+	uint8 *dest = (uint8 *)dest_;
+	int i;
+	line_size /= sizeof(uint8);
+	for (i = 0; i < 8; i++)
+		idctRowCondDC_int16_8bit(block + i * 8, 0);
+	for (i = 0; i < 8; i++)
+		idctSparseColAdd_int16_8bit(dest + i, line_size, block + i);
+}
+
+void ff_simple_idct_int16_8bit(int16 *block) {
+	int i;
+	for (i = 0; i < 8; i++)
+		idctRowCondDC_int16_8bit(block + i * 8, 0);
+	for (i = 0; i < 8; i++)
+		idctSparseCol_int16_8bit(block + i);
+}
+
+static inline void idct4col_add(uint8 *dest, ptrdiff_t line_size, const int16 *col) {
+	int c0, c1, c2, c3, a0, a1, a2, a3;
+	a0 = col[8 * 0];
+	a1 = col[8 * 1];
+	a2 = col[8 * 2];
+	a3 = col[8 * 3];
+	c0 = (a0 + a2) * ((int)((0.5) * M_SQRT2 * (1 << 12) + 0.5)) + (1 << ((4 + 1 + 12) - 1));
+	c2 = (a0 - a2) * ((int)((0.5) * M_SQRT2 * (1 << 12) + 0.5)) + (1 << ((4 + 1 + 12) - 1));
+	c1 = a1 * ((int)((0.6532814824) * M_SQRT2 * (1 << 12) + 0.5)) +
+		 a3 * ((int)((0.2705980501) * M_SQRT2 * (1 << 12) + 0.5));
+	c3 = a1 * ((int)((0.2705980501) * M_SQRT2 * (1 << 12) + 0.5)) -
+		 a3 * ((int)((0.6532814824) * M_SQRT2 * (1 << 12) + 0.5));
+	dest[0] = av_clip_uint8(dest[0] + ((c0 + c1) >> (4 + 1 + 12)));
+	dest += line_size;
+	dest[0] = av_clip_uint8(dest[0] + ((c2 + c3) >> (4 + 1 + 12)));
+	dest += line_size;
+	dest[0] = av_clip_uint8(dest[0] + ((c2 - c3) >> (4 + 1 + 12)));
+	dest += line_size;
+	dest[0] = av_clip_uint8(dest[0] + ((c0 - c1) >> (4 + 1 + 12)));
+}
+
+static inline void idct4row(int16 *row) {
+	unsigned c0, c1, c2, c3;
+	int a0, a1, a2, a3;
+	a0 = row[0];
+	a1 = row[1];
+	a2 = row[2];
+	a3 = row[3];
+	c0 = (a0 + a2) * ((int)((0.5) * M_SQRT2 * (1 << 15) + 0.5)) + (1 << (11 - 1));
+	c2 = (a0 - a2) * ((int)((0.5) * M_SQRT2 * (1 << 15) + 0.5)) + (1 << (11 - 1));
+	c1 = a1 * ((int)((0.6532814824) * M_SQRT2 * (1 << 15) + 0.5)) +
+		 a3 * ((int)((0.2705980501) * M_SQRT2 * (1 << 15) + 0.5));
+	c3 = a1 * ((int)((0.2705980501) * M_SQRT2 * (1 << 15) + 0.5)) -
+		 a3 * ((int)((0.6532814824) * M_SQRT2 * (1 << 15) + 0.5));
+	row[0] = (c0 + c1) >> 11;
+	row[1] = (c2 + c3) >> 11;
+	row[2] = (c2 - c3) >> 11;
+	row[3] = (c0 - c1) >> 11;
+}
+
+void ff_simple_idct84_add(uint8 *dest, ptrdiff_t line_size, int16 *block) {
+	int i;
+	/* IDCT8 on each line */
+	for (i = 0; i < 4; i++) {
+		idctRowCondDC_int16_8bit(block + i * 8, 0);
+	}
+	/* IDCT4 and store */
+	for (i = 0; i < 8; i++) {
+		idct4col_add(dest + i, line_size, block + i);
+	}
+}
+
+void ff_simple_idct48_add(uint8 *dest, ptrdiff_t line_size, int16 *block) {
+	int i;
+	/* IDCT4 on each line */
+	for (i = 0; i < 8; i++) {
+		idct4row(block + i * 8);
+	}
+	/* IDCT8 and store */
+	for (i = 0; i < 4; i++) {
+		idctSparseColAdd_int16_8bit(dest + i, line_size, block + i);
+	}
+}
+
+void ff_simple_idct44_add(uint8 *dest, ptrdiff_t line_size, int16 *block) {
+	int i;
+	/* IDCT4 on each line */
+	for (i = 0; i < 4; i++) {
+		idct4row(block + i * 8);
+	}
+	/* IDCT4 and store */
+	for (i = 0; i < 4; i++) {
+		idct4col_add(dest + i, line_size, block + i);
+	}
+}
+
+static void copy_block8(uint8 *d, const uint8 *s, ptrdiff_t ds, ptrdiff_t ss, int h) {
+	for (int y = 0; y < h; ++y) {
+		memcpy(d, s, 8);
+		d += ds;
+		s += ss;
+	}
+}
+
+static void copy_block9(uint8 *d, const uint8 *s, ptrdiff_t ds, ptrdiff_t ss, int h) {
+	for (int y = 0; y < h; ++y) {
+		memcpy(d, s, 9);
+		d += ds;
+		s += ss;
+	}
+}
+
+static void copy_block16(uint8 *d, const uint8 *s, ptrdiff_t ds, ptrdiff_t ss, int h) {
+	for (int y = 0; y < h; ++y) {
+		memcpy(d, s, 16);
+		d += ds;
+		s += ss;
+	}
+}
+
+static void copy_block17(uint8 *d, const uint8 *s, ptrdiff_t ds, ptrdiff_t ss, int h) {
+	for (int y = 0; y < h; ++y) {
+		memcpy(d, s, 17);
+		d += ds;
+		s += ss;
+	}
+}
+
+static void put_pixels8_8_c(uint8 *d, const uint8 *s, ptrdiff_t stride, int h) {
+	for (int y = 0; y < h; ++y) {
+		for (int x = 0; x < 8; ++x) {
+			int val = s[x];
+			d[x] = val;
+		}
+		d += stride;
+		s += stride;
+	}
+}
+
+static void put_pixels8_l2_8(uint8 *d, const uint8 *a, const uint8 *b, int ds, int as, int bs, int h) {
+	for (int y = 0; y < h; ++y) {
+		for (int x = 0; x < 8; ++x) {
+			int val = (a[x] + b[x] + 1) >> 1;
+			d[x] = val;
+		}
+		d += ds;
+		a += as;
+		b += bs;
+	}
+}
+
+static void put_pixels8_l4_8(uint8 *d, const uint8 *a, const uint8 *b, const uint8 *c, const uint8 *e, int ds, int as,
+							 int bs, int cs, int es, int h) {
+	for (int y = 0; y < h; ++y) {
+		for (int x = 0; x < 8; ++x) {
+			int val = (a[x] + b[x] + c[x] + e[x] + 2) >> 2;
+			d[x] = val;
+		}
+		d += ds;
+		a += as;
+		b += bs;
+		c += cs;
+		e += es;
+	}
+}
+
+static void avg_pixels8_8_c(uint8 *d, const uint8 *s, ptrdiff_t stride, int h) {
+	for (int y = 0; y < h; ++y) {
+		for (int x = 0; x < 8; ++x) {
+			int val = s[x];
+			d[x] = (d[x] + val + 1) >> 1;
+		}
+		d += stride;
+		s += stride;
+	}
+}
+
+static void avg_pixels8_l2_8(uint8 *d, const uint8 *a, const uint8 *b, int ds, int as, int bs, int h) {
+	for (int y = 0; y < h; ++y) {
+		for (int x = 0; x < 8; ++x) {
+			int val = (a[x] + b[x] + 1) >> 1;
+			d[x] = (d[x] + val + 1) >> 1;
+		}
+		d += ds;
+		a += as;
+		b += bs;
+	}
+}
+
+static void avg_pixels8_l4_8(uint8 *d, const uint8 *a, const uint8 *b, const uint8 *c, const uint8 *e, int ds, int as,
+							 int bs, int cs, int es, int h) {
+	for (int y = 0; y < h; ++y) {
+		for (int x = 0; x < 8; ++x) {
+			int val = (a[x] + b[x] + c[x] + e[x] + 2) >> 2;
+			d[x] = (d[x] + val + 1) >> 1;
+		}
+		d += ds;
+		a += as;
+		b += bs;
+		c += cs;
+		e += es;
+	}
+}
+
+static void put_no_rnd_pixels8_l2_8(uint8 *d, const uint8 *a, const uint8 *b, int ds, int as, int bs, int h) {
+	for (int y = 0; y < h; ++y) {
+		for (int x = 0; x < 8; ++x) {
+			int val = (a[x] + b[x] + 0) >> 1;
+			d[x] = val;
+		}
+		d += ds;
+		a += as;
+		b += bs;
+	}
+}
+
+static void put_no_rnd_pixels8_l4_8(uint8 *d, const uint8 *a, const uint8 *b, const uint8 *c, const uint8 *e, int ds,
+									int as, int bs, int cs, int es, int h) {
+	for (int y = 0; y < h; ++y) {
+		for (int x = 0; x < 8; ++x) {
+			int val = (a[x] + b[x] + c[x] + e[x] + 1) >> 2;
+			d[x] = val;
+		}
+		d += ds;
+		a += as;
+		b += bs;
+		c += cs;
+		e += es;
+	}
+}
+
+static void put_pixels16_8_c(uint8 *d, const uint8 *s, ptrdiff_t stride, int h) {
+	for (int y = 0; y < h; ++y) {
+		for (int x = 0; x < 16; ++x) {
+			int val = s[x];
+			d[x] = val;
+		}
+		d += stride;
+		s += stride;
+	}
+}
+
+static void put_pixels16_l2_8(uint8 *d, const uint8 *a, const uint8 *b, int ds, int as, int bs, int h) {
+	for (int y = 0; y < h; ++y) {
+		for (int x = 0; x < 16; ++x) {
+			int val = (a[x] + b[x] + 1) >> 1;
+			d[x] = val;
+		}
+		d += ds;
+		a += as;
+		b += bs;
+	}
+}
+
+static void put_pixels16_l4_8(uint8 *d, const uint8 *a, const uint8 *b, const uint8 *c, const uint8 *e, int ds, int as,
+							  int bs, int cs, int es, int h) {
+	for (int y = 0; y < h; ++y) {
+		for (int x = 0; x < 16; ++x) {
+			int val = (a[x] + b[x] + c[x] + e[x] + 2) >> 2;
+			d[x] = val;
+		}
+		d += ds;
+		a += as;
+		b += bs;
+		c += cs;
+		e += es;
+	}
+}
+
+static void avg_pixels16_8_c(uint8 *d, const uint8 *s, ptrdiff_t stride, int h) {
+	for (int y = 0; y < h; ++y) {
+		for (int x = 0; x < 16; ++x) {
+			int val = s[x];
+			d[x] = (d[x] + val + 1) >> 1;
+		}
+		d += stride;
+		s += stride;
+	}
+}
+
+static void avg_pixels16_l2_8(uint8 *d, const uint8 *a, const uint8 *b, int ds, int as, int bs, int h) {
+	for (int y = 0; y < h; ++y) {
+		for (int x = 0; x < 16; ++x) {
+			int val = (a[x] + b[x] + 1) >> 1;
+			d[x] = (d[x] + val + 1) >> 1;
+		}
+		d += ds;
+		a += as;
+		b += bs;
+	}
+}
+
+static void avg_pixels16_l4_8(uint8 *d, const uint8 *a, const uint8 *b, const uint8 *c, const uint8 *e, int ds, int as,
+							  int bs, int cs, int es, int h) {
+	for (int y = 0; y < h; ++y) {
+		for (int x = 0; x < 16; ++x) {
+			int val = (a[x] + b[x] + c[x] + e[x] + 2) >> 2;
+			d[x] = (d[x] + val + 1) >> 1;
+		}
+		d += ds;
+		a += as;
+		b += bs;
+		c += cs;
+		e += es;
+	}
+}
+
+static void put_no_rnd_pixels16_l2_8(uint8 *d, const uint8 *a, const uint8 *b, int ds, int as, int bs, int h) {
+	for (int y = 0; y < h; ++y) {
+		for (int x = 0; x < 16; ++x) {
+			int val = (a[x] + b[x] + 0) >> 1;
+			d[x] = val;
+		}
+		d += ds;
+		a += as;
+		b += bs;
+	}
+}
+
+static void put_no_rnd_pixels16_l4_8(uint8 *d, const uint8 *a, const uint8 *b, const uint8 *c, const uint8 *e, int ds,
+									 int as, int bs, int cs, int es, int h) {
+	for (int y = 0; y < h; ++y) {
+		for (int x = 0; x < 16; ++x) {
+			int val = (a[x] + b[x] + c[x] + e[x] + 1) >> 2;
+			d[x] = val;
+		}
+		d += ds;
+		a += as;
+		b += bs;
+		c += cs;
+		e += es;
+	}
+}
+#define QPEL_MC(r, OPNAME, RND, OP)                                                                                    \
+	static void OPNAME##mpeg4_qpel8_h_lowpass(uint8 *dst, const uint8 *src, int dstStride, int srcStride, int h) {     \
+		const Crop cm;                                                                                                 \
+		int i;                                                                                                         \
+                                                                                                                       \
+		for (i = 0; i < h; i++) {                                                                                      \
+			OP(dst[0], (src[0] + src[1]) * 20 - (src[0] + src[2]) * 6 + (src[1] + src[3]) * 3 - (src[2] + src[4]));    \
+			OP(dst[1], (src[1] + src[2]) * 20 - (src[0] + src[3]) * 6 + (src[0] + src[4]) * 3 - (src[1] + src[5]));    \
+			OP(dst[2], (src[2] + src[3]) * 20 - (src[1] + src[4]) * 6 + (src[0] + src[5]) * 3 - (src[0] + src[6]));    \
+			OP(dst[3], (src[3] + src[4]) * 20 - (src[2] + src[5]) * 6 + (src[1] + src[6]) * 3 - (src[0] + src[7]));    \
+			OP(dst[4], (src[4] + src[5]) * 20 - (src[3] + src[6]) * 6 + (src[2] + src[7]) * 3 - (src[1] + src[8]));    \
+			OP(dst[5], (src[5] + src[6]) * 20 - (src[4] + src[7]) * 6 + (src[3] + src[8]) * 3 - (src[2] + src[8]));    \
+			OP(dst[6], (src[6] + src[7]) * 20 - (src[5] + src[8]) * 6 + (src[4] + src[8]) * 3 - (src[3] + src[7]));    \
+			OP(dst[7], (src[7] + src[8]) * 20 - (src[6] + src[8]) * 6 + (src[5] + src[7]) * 3 - (src[4] + src[6]));    \
+			dst += dstStride;                                                                                          \
+			src += srcStride;                                                                                          \
+		}                                                                                                              \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##mpeg4_qpel8_v_lowpass(uint8 *dst, const uint8 *src, int dstStride, int srcStride) {            \
+		const Crop cm;                                                                                                 \
+		const int w = 8;                                                                                               \
+		int i;                                                                                                         \
+                                                                                                                       \
+		for (i = 0; i < w; i++) {                                                                                      \
+			const int src0 = src[0 * srcStride];                                                                       \
+			const int src1 = src[1 * srcStride];                                                                       \
+			const int src2 = src[2 * srcStride];                                                                       \
+			const int src3 = src[3 * srcStride];                                                                       \
+			const int src4 = src[4 * srcStride];                                                                       \
+			const int src5 = src[5 * srcStride];                                                                       \
+			const int src6 = src[6 * srcStride];                                                                       \
+			const int src7 = src[7 * srcStride];                                                                       \
+			const int src8 = src[8 * srcStride];                                                                       \
+			OP(dst[0 * dstStride], (src0 + src1) * 20 - (src0 + src2) * 6 + (src1 + src3) * 3 - (src2 + src4));        \
+			OP(dst[1 * dstStride], (src1 + src2) * 20 - (src0 + src3) * 6 + (src0 + src4) * 3 - (src1 + src5));        \
+			OP(dst[2 * dstStride], (src2 + src3) * 20 - (src1 + src4) * 6 + (src0 + src5) * 3 - (src0 + src6));        \
+			OP(dst[3 * dstStride], (src3 + src4) * 20 - (src2 + src5) * 6 + (src1 + src6) * 3 - (src0 + src7));        \
+			OP(dst[4 * dstStride], (src4 + src5) * 20 - (src3 + src6) * 6 + (src2 + src7) * 3 - (src1 + src8));        \
+			OP(dst[5 * dstStride], (src5 + src6) * 20 - (src4 + src7) * 6 + (src3 + src8) * 3 - (src2 + src8));        \
+			OP(dst[6 * dstStride], (src6 + src7) * 20 - (src5 + src8) * 6 + (src4 + src8) * 3 - (src3 + src7));        \
+			OP(dst[7 * dstStride], (src7 + src8) * 20 - (src6 + src8) * 6 + (src5 + src7) * 3 - (src4 + src6));        \
+			dst++;                                                                                                     \
+			src++;                                                                                                     \
+		}                                                                                                              \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##mpeg4_qpel16_h_lowpass(uint8 *dst, const uint8 *src, int dstStride, int srcStride, int h) {    \
+		const Crop cm;                                                                                                 \
+		int i;                                                                                                         \
+                                                                                                                       \
+		for (i = 0; i < h; i++) {                                                                                      \
+			OP(dst[0], (src[0] + src[1]) * 20 - (src[0] + src[2]) * 6 + (src[1] + src[3]) * 3 - (src[2] + src[4]));    \
+			OP(dst[1], (src[1] + src[2]) * 20 - (src[0] + src[3]) * 6 + (src[0] + src[4]) * 3 - (src[1] + src[5]));    \
+			OP(dst[2], (src[2] + src[3]) * 20 - (src[1] + src[4]) * 6 + (src[0] + src[5]) * 3 - (src[0] + src[6]));    \
+			OP(dst[3], (src[3] + src[4]) * 20 - (src[2] + src[5]) * 6 + (src[1] + src[6]) * 3 - (src[0] + src[7]));    \
+			OP(dst[4], (src[4] + src[5]) * 20 - (src[3] + src[6]) * 6 + (src[2] + src[7]) * 3 - (src[1] + src[8]));    \
+			OP(dst[5], (src[5] + src[6]) * 20 - (src[4] + src[7]) * 6 + (src[3] + src[8]) * 3 - (src[2] + src[9]));    \
+			OP(dst[6], (src[6] + src[7]) * 20 - (src[5] + src[8]) * 6 + (src[4] + src[9]) * 3 - (src[3] + src[10]));   \
+			OP(dst[7], (src[7] + src[8]) * 20 - (src[6] + src[9]) * 6 + (src[5] + src[10]) * 3 - (src[4] + src[11]));  \
+			OP(dst[8], (src[8] + src[9]) * 20 - (src[7] + src[10]) * 6 + (src[6] + src[11]) * 3 - (src[5] + src[12])); \
+			OP(dst[9],                                                                                                 \
+			   (src[9] + src[10]) * 20 - (src[8] + src[11]) * 6 + (src[7] + src[12]) * 3 - (src[6] + src[13]));        \
+			OP(dst[10],                                                                                                \
+			   (src[10] + src[11]) * 20 - (src[9] + src[12]) * 6 + (src[8] + src[13]) * 3 - (src[7] + src[14]));       \
+			OP(dst[11],                                                                                                \
+			   (src[11] + src[12]) * 20 - (src[10] + src[13]) * 6 + (src[9] + src[14]) * 3 - (src[8] + src[15]));      \
+			OP(dst[12],                                                                                                \
+			   (src[12] + src[13]) * 20 - (src[11] + src[14]) * 6 + (src[10] + src[15]) * 3 - (src[9] + src[16]));     \
+			OP(dst[13],                                                                                                \
+			   (src[13] + src[14]) * 20 - (src[12] + src[15]) * 6 + (src[11] + src[16]) * 3 - (src[10] + src[16]));    \
+			OP(dst[14],                                                                                                \
+			   (src[14] + src[15]) * 20 - (src[13] + src[16]) * 6 + (src[12] + src[16]) * 3 - (src[11] + src[15]));    \
+			OP(dst[15],                                                                                                \
+			   (src[15] + src[16]) * 20 - (src[14] + src[16]) * 6 + (src[13] + src[15]) * 3 - (src[12] + src[14]));    \
+			dst += dstStride;                                                                                          \
+			src += srcStride;                                                                                          \
+		}                                                                                                              \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##mpeg4_qpel16_v_lowpass(uint8 *dst, const uint8 *src, int dstStride, int srcStride) {           \
+		const Crop cm;                                                                                                 \
+		const int w = 16;                                                                                              \
+		int i;                                                                                                         \
+                                                                                                                       \
+		for (i = 0; i < w; i++) {                                                                                      \
+			const int src0 = src[0 * srcStride];                                                                       \
+			const int src1 = src[1 * srcStride];                                                                       \
+			const int src2 = src[2 * srcStride];                                                                       \
+			const int src3 = src[3 * srcStride];                                                                       \
+			const int src4 = src[4 * srcStride];                                                                       \
+			const int src5 = src[5 * srcStride];                                                                       \
+			const int src6 = src[6 * srcStride];                                                                       \
+			const int src7 = src[7 * srcStride];                                                                       \
+			const int src8 = src[8 * srcStride];                                                                       \
+			const int src9 = src[9 * srcStride];                                                                       \
+			const int src10 = src[10 * srcStride];                                                                     \
+			const int src11 = src[11 * srcStride];                                                                     \
+			const int src12 = src[12 * srcStride];                                                                     \
+			const int src13 = src[13 * srcStride];                                                                     \
+			const int src14 = src[14 * srcStride];                                                                     \
+			const int src15 = src[15 * srcStride];                                                                     \
+			const int src16 = src[16 * srcStride];                                                                     \
+			OP(dst[0 * dstStride], (src0 + src1) * 20 - (src0 + src2) * 6 + (src1 + src3) * 3 - (src2 + src4));        \
+			OP(dst[1 * dstStride], (src1 + src2) * 20 - (src0 + src3) * 6 + (src0 + src4) * 3 - (src1 + src5));        \
+			OP(dst[2 * dstStride], (src2 + src3) * 20 - (src1 + src4) * 6 + (src0 + src5) * 3 - (src0 + src6));        \
+			OP(dst[3 * dstStride], (src3 + src4) * 20 - (src2 + src5) * 6 + (src1 + src6) * 3 - (src0 + src7));        \
+			OP(dst[4 * dstStride], (src4 + src5) * 20 - (src3 + src6) * 6 + (src2 + src7) * 3 - (src1 + src8));        \
+			OP(dst[5 * dstStride], (src5 + src6) * 20 - (src4 + src7) * 6 + (src3 + src8) * 3 - (src2 + src9));        \
+			OP(dst[6 * dstStride], (src6 + src7) * 20 - (src5 + src8) * 6 + (src4 + src9) * 3 - (src3 + src10));       \
+			OP(dst[7 * dstStride], (src7 + src8) * 20 - (src6 + src9) * 6 + (src5 + src10) * 3 - (src4 + src11));      \
+			OP(dst[8 * dstStride], (src8 + src9) * 20 - (src7 + src10) * 6 + (src6 + src11) * 3 - (src5 + src12));     \
+			OP(dst[9 * dstStride], (src9 + src10) * 20 - (src8 + src11) * 6 + (src7 + src12) * 3 - (src6 + src13));    \
+			OP(dst[10 * dstStride], (src10 + src11) * 20 - (src9 + src12) * 6 + (src8 + src13) * 3 - (src7 + src14));  \
+			OP(dst[11 * dstStride], (src11 + src12) * 20 - (src10 + src13) * 6 + (src9 + src14) * 3 - (src8 + src15)); \
+			OP(dst[12 * dstStride],                                                                                    \
+			   (src12 + src13) * 20 - (src11 + src14) * 6 + (src10 + src15) * 3 - (src9 + src16));                     \
+			OP(dst[13 * dstStride],                                                                                    \
+			   (src13 + src14) * 20 - (src12 + src15) * 6 + (src11 + src16) * 3 - (src10 + src16));                    \
+			OP(dst[14 * dstStride],                                                                                    \
+			   (src14 + src15) * 20 - (src13 + src16) * 6 + (src12 + src16) * 3 - (src11 + src15));                    \
+			OP(dst[15 * dstStride],                                                                                    \
+			   (src15 + src16) * 20 - (src14 + src16) * 6 + (src13 + src15) * 3 - (src12 + src14));                    \
+			dst++;                                                                                                     \
+			src++;                                                                                                     \
+		}                                                                                                              \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel8_mc10_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                 \
+		uint8 half[64];                                                                                                \
+                                                                                                                       \
+		put##RND##mpeg4_qpel8_h_lowpass(half, src, 8, stride, 8);                                                      \
+		OPNAME##pixels8_l2_8(dst, src, half, stride, stride, 8, 8);                                                    \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel8_mc20_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                 \
+		OPNAME##mpeg4_qpel8_h_lowpass(dst, src, stride, stride, 8);                                                    \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel8_mc30_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                 \
+		uint8 half[64];                                                                                                \
+                                                                                                                       \
+		put##RND##mpeg4_qpel8_h_lowpass(half, src, 8, stride, 8);                                                      \
+		OPNAME##pixels8_l2_8(dst, src + 1, half, stride, stride, 8, 8);                                                \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel8_mc01_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                 \
+		uint8 full[16 * 9];                                                                                            \
+		uint8 half[64];                                                                                                \
+                                                                                                                       \
+		copy_block8(full, src, 16, stride, 9);                                                                         \
+		put##RND##mpeg4_qpel8_v_lowpass(half, full, 8, 16);                                                            \
+		OPNAME##pixels8_l2_8(dst, full, half, stride, 16, 8, 8);                                                       \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel8_mc02_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                 \
+		uint8 full[16 * 9];                                                                                            \
+                                                                                                                       \
+		copy_block8(full, src, 16, stride, 9);                                                                         \
+		OPNAME##mpeg4_qpel8_v_lowpass(dst, full, stride, 16);                                                          \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel8_mc03_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                 \
+		uint8 full[16 * 9];                                                                                            \
+		uint8 half[64];                                                                                                \
+                                                                                                                       \
+		copy_block8(full, src, 16, stride, 9);                                                                         \
+		put##RND##mpeg4_qpel8_v_lowpass(half, full, 8, 16);                                                            \
+		OPNAME##pixels8_l2_8(dst, full + 16, half, stride, 16, 8, 8);                                                  \
+	}                                                                                                                  \
+                                                                                                                       \
+	void ff_##OPNAME##qpel8_mc11_old_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                               \
+		uint8 full[16 * 9];                                                                                            \
+		uint8 halfH[72];                                                                                               \
+		uint8 halfV[64];                                                                                               \
+		uint8 halfHV[64];                                                                                              \
+                                                                                                                       \
+		copy_block9(full, src, 16, stride, 9);                                                                         \
+		put##RND##mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);                                                        \
+		put##RND##mpeg4_qpel8_v_lowpass(halfV, full, 8, 16);                                                           \
+		put##RND##mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);                                                          \
+		OPNAME##pixels8_l4_8(dst, full, halfH, halfV, halfHV, stride, 16, 8, 8, 8, 8);                                 \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel8_mc11_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                 \
+		uint8 full[16 * 9];                                                                                            \
+		uint8 halfH[72];                                                                                               \
+		uint8 halfHV[64];                                                                                              \
+                                                                                                                       \
+		copy_block9(full, src, 16, stride, 9);                                                                         \
+		put##RND##mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);                                                        \
+		put##RND##pixels8_l2_8(halfH, halfH, full, 8, 8, 16, 9);                                                       \
+		put##RND##mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);                                                          \
+		OPNAME##pixels8_l2_8(dst, halfH, halfHV, stride, 8, 8, 8);                                                     \
+	}                                                                                                                  \
+                                                                                                                       \
+	void ff_##OPNAME##qpel8_mc31_old_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                               \
+		uint8 full[16 * 9];                                                                                            \
+		uint8 halfH[72];                                                                                               \
+		uint8 halfV[64];                                                                                               \
+		uint8 halfHV[64];                                                                                              \
+                                                                                                                       \
+		copy_block9(full, src, 16, stride, 9);                                                                         \
+		put##RND##mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);                                                        \
+		put##RND##mpeg4_qpel8_v_lowpass(halfV, full + 1, 8, 16);                                                       \
+		put##RND##mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);                                                          \
+		OPNAME##pixels8_l4_8(dst, full + 1, halfH, halfV, halfHV, stride, 16, 8, 8, 8, 8);                             \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel8_mc31_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                 \
+		uint8 full[16 * 9];                                                                                            \
+		uint8 halfH[72];                                                                                               \
+		uint8 halfHV[64];                                                                                              \
+                                                                                                                       \
+		copy_block9(full, src, 16, stride, 9);                                                                         \
+		put##RND##mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);                                                        \
+		put##RND##pixels8_l2_8(halfH, halfH, full + 1, 8, 8, 16, 9);                                                   \
+		put##RND##mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);                                                          \
+		OPNAME##pixels8_l2_8(dst, halfH, halfHV, stride, 8, 8, 8);                                                     \
+	}                                                                                                                  \
+                                                                                                                       \
+	void ff_##OPNAME##qpel8_mc13_old_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                               \
+		uint8 full[16 * 9];                                                                                            \
+		uint8 halfH[72];                                                                                               \
+		uint8 halfV[64];                                                                                               \
+		uint8 halfHV[64];                                                                                              \
+                                                                                                                       \
+		copy_block9(full, src, 16, stride, 9);                                                                         \
+		put##RND##mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);                                                        \
+		put##RND##mpeg4_qpel8_v_lowpass(halfV, full, 8, 16);                                                           \
+		put##RND##mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);                                                          \
+		OPNAME##pixels8_l4_8(dst, full + 16, halfH + 8, halfV, halfHV, stride, 16, 8, 8, 8, 8);                        \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel8_mc13_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                 \
+		uint8 full[16 * 9];                                                                                            \
+		uint8 halfH[72];                                                                                               \
+		uint8 halfHV[64];                                                                                              \
+                                                                                                                       \
+		copy_block9(full, src, 16, stride, 9);                                                                         \
+		put##RND##mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);                                                        \
+		put##RND##pixels8_l2_8(halfH, halfH, full, 8, 8, 16, 9);                                                       \
+		put##RND##mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);                                                          \
+		OPNAME##pixels8_l2_8(dst, halfH + 8, halfHV, stride, 8, 8, 8);                                                 \
+	}                                                                                                                  \
+                                                                                                                       \
+	void ff_##OPNAME##qpel8_mc33_old_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                               \
+		uint8 full[16 * 9];                                                                                            \
+		uint8 halfH[72];                                                                                               \
+		uint8 halfV[64];                                                                                               \
+		uint8 halfHV[64];                                                                                              \
+                                                                                                                       \
+		copy_block9(full, src, 16, stride, 9);                                                                         \
+		put##RND##mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);                                                        \
+		put##RND##mpeg4_qpel8_v_lowpass(halfV, full + 1, 8, 16);                                                       \
+		put##RND##mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);                                                          \
+		OPNAME##pixels8_l4_8(dst, full + 17, halfH + 8, halfV, halfHV, stride, 16, 8, 8, 8, 8);                        \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel8_mc33_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                 \
+		uint8 full[16 * 9];                                                                                            \
+		uint8 halfH[72];                                                                                               \
+		uint8 halfHV[64];                                                                                              \
+                                                                                                                       \
+		copy_block9(full, src, 16, stride, 9);                                                                         \
+		put##RND##mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);                                                        \
+		put##RND##pixels8_l2_8(halfH, halfH, full + 1, 8, 8, 16, 9);                                                   \
+		put##RND##mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);                                                          \
+		OPNAME##pixels8_l2_8(dst, halfH + 8, halfHV, stride, 8, 8, 8);                                                 \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel8_mc21_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                 \
+		uint8 halfH[72];                                                                                               \
+		uint8 halfHV[64];                                                                                              \
+                                                                                                                       \
+		put##RND##mpeg4_qpel8_h_lowpass(halfH, src, 8, stride, 9);                                                     \
+		put##RND##mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);                                                          \
+		OPNAME##pixels8_l2_8(dst, halfH, halfHV, stride, 8, 8, 8);                                                     \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel8_mc23_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                 \
+		uint8 halfH[72];                                                                                               \
+		uint8 halfHV[64];                                                                                              \
+                                                                                                                       \
+		put##RND##mpeg4_qpel8_h_lowpass(halfH, src, 8, stride, 9);                                                     \
+		put##RND##mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);                                                          \
+		OPNAME##pixels8_l2_8(dst, halfH + 8, halfHV, stride, 8, 8, 8);                                                 \
+	}                                                                                                                  \
+                                                                                                                       \
+	void ff_##OPNAME##qpel8_mc12_old_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                               \
+		uint8 full[16 * 9];                                                                                            \
+		uint8 halfH[72];                                                                                               \
+		uint8 halfV[64];                                                                                               \
+		uint8 halfHV[64];                                                                                              \
+                                                                                                                       \
+		copy_block9(full, src, 16, stride, 9);                                                                         \
+		put##RND##mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);                                                        \
+		put##RND##mpeg4_qpel8_v_lowpass(halfV, full, 8, 16);                                                           \
+		put##RND##mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);                                                          \
+		OPNAME##pixels8_l2_8(dst, halfV, halfHV, stride, 8, 8, 8);                                                     \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel8_mc12_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                 \
+		uint8 full[16 * 9];                                                                                            \
+		uint8 halfH[72];                                                                                               \
+                                                                                                                       \
+		copy_block9(full, src, 16, stride, 9);                                                                         \
+		put##RND##mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);                                                        \
+		put##RND##pixels8_l2_8(halfH, halfH, full, 8, 8, 16, 9);                                                       \
+		OPNAME##mpeg4_qpel8_v_lowpass(dst, halfH, stride, 8);                                                          \
+	}                                                                                                                  \
+                                                                                                                       \
+	void ff_##OPNAME##qpel8_mc32_old_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                               \
+		uint8 full[16 * 9];                                                                                            \
+		uint8 halfH[72];                                                                                               \
+		uint8 halfV[64];                                                                                               \
+		uint8 halfHV[64];                                                                                              \
+                                                                                                                       \
+		copy_block9(full, src, 16, stride, 9);                                                                         \
+		put##RND##mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);                                                        \
+		put##RND##mpeg4_qpel8_v_lowpass(halfV, full + 1, 8, 16);                                                       \
+		put##RND##mpeg4_qpel8_v_lowpass(halfHV, halfH, 8, 8);                                                          \
+		OPNAME##pixels8_l2_8(dst, halfV, halfHV, stride, 8, 8, 8);                                                     \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel8_mc32_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                 \
+		uint8 full[16 * 9];                                                                                            \
+		uint8 halfH[72];                                                                                               \
+                                                                                                                       \
+		copy_block9(full, src, 16, stride, 9);                                                                         \
+		put##RND##mpeg4_qpel8_h_lowpass(halfH, full, 8, 16, 9);                                                        \
+		put##RND##pixels8_l2_8(halfH, halfH, full + 1, 8, 8, 16, 9);                                                   \
+		OPNAME##mpeg4_qpel8_v_lowpass(dst, halfH, stride, 8);                                                          \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel8_mc22_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                 \
+		uint8 halfH[72];                                                                                               \
+                                                                                                                       \
+		put##RND##mpeg4_qpel8_h_lowpass(halfH, src, 8, stride, 9);                                                     \
+		OPNAME##mpeg4_qpel8_v_lowpass(dst, halfH, stride, 8);                                                          \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel16_mc10_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                \
+		uint8 half[256];                                                                                               \
+                                                                                                                       \
+		put##RND##mpeg4_qpel16_h_lowpass(half, src, 16, stride, 16);                                                   \
+		OPNAME##pixels16_l2_8(dst, src, half, stride, stride, 16, 16);                                                 \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel16_mc20_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                \
+		OPNAME##mpeg4_qpel16_h_lowpass(dst, src, stride, stride, 16);                                                  \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel16_mc30_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                \
+		uint8 half[256];                                                                                               \
+                                                                                                                       \
+		put##RND##mpeg4_qpel16_h_lowpass(half, src, 16, stride, 16);                                                   \
+		OPNAME##pixels16_l2_8(dst, src + 1, half, stride, stride, 16, 16);                                             \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel16_mc01_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                \
+		uint8 full[24 * 17];                                                                                           \
+		uint8 half[256];                                                                                               \
+                                                                                                                       \
+		copy_block16(full, src, 24, stride, 17);                                                                       \
+		put##RND##mpeg4_qpel16_v_lowpass(half, full, 16, 24);                                                          \
+		OPNAME##pixels16_l2_8(dst, full, half, stride, 24, 16, 16);                                                    \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel16_mc02_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                \
+		uint8 full[24 * 17];                                                                                           \
+                                                                                                                       \
+		copy_block16(full, src, 24, stride, 17);                                                                       \
+		OPNAME##mpeg4_qpel16_v_lowpass(dst, full, stride, 24);                                                         \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel16_mc03_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                \
+		uint8 full[24 * 17];                                                                                           \
+		uint8 half[256];                                                                                               \
+                                                                                                                       \
+		copy_block16(full, src, 24, stride, 17);                                                                       \
+		put##RND##mpeg4_qpel16_v_lowpass(half, full, 16, 24);                                                          \
+		OPNAME##pixels16_l2_8(dst, full + 24, half, stride, 24, 16, 16);                                               \
+	}                                                                                                                  \
+                                                                                                                       \
+	void ff_##OPNAME##qpel16_mc11_old_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                              \
+		uint8 full[24 * 17];                                                                                           \
+		uint8 halfH[272];                                                                                              \
+		uint8 halfV[256];                                                                                              \
+		uint8 halfHV[256];                                                                                             \
+                                                                                                                       \
+		copy_block17(full, src, 24, stride, 17);                                                                       \
+		put##RND##mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);                                                     \
+		put##RND##mpeg4_qpel16_v_lowpass(halfV, full, 16, 24);                                                         \
+		put##RND##mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);                                                       \
+		OPNAME##pixels16_l4_8(dst, full, halfH, halfV, halfHV, stride, 24, 16, 16, 16, 16);                            \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel16_mc11_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                \
+		uint8 full[24 * 17];                                                                                           \
+		uint8 halfH[272];                                                                                              \
+		uint8 halfHV[256];                                                                                             \
+                                                                                                                       \
+		copy_block17(full, src, 24, stride, 17);                                                                       \
+		put##RND##mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);                                                     \
+		put##RND##pixels16_l2_8(halfH, halfH, full, 16, 16, 24, 17);                                                   \
+		put##RND##mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);                                                       \
+		OPNAME##pixels16_l2_8(dst, halfH, halfHV, stride, 16, 16, 16);                                                 \
+	}                                                                                                                  \
+                                                                                                                       \
+	void ff_##OPNAME##qpel16_mc31_old_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                              \
+		uint8 full[24 * 17];                                                                                           \
+		uint8 halfH[272];                                                                                              \
+		uint8 halfV[256];                                                                                              \
+		uint8 halfHV[256];                                                                                             \
+                                                                                                                       \
+		copy_block17(full, src, 24, stride, 17);                                                                       \
+		put##RND##mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);                                                     \
+		put##RND##mpeg4_qpel16_v_lowpass(halfV, full + 1, 16, 24);                                                     \
+		put##RND##mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);                                                       \
+		OPNAME##pixels16_l4_8(dst, full + 1, halfH, halfV, halfHV, stride, 24, 16, 16, 16, 16);                        \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel16_mc31_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                \
+		uint8 full[24 * 17];                                                                                           \
+		uint8 halfH[272];                                                                                              \
+		uint8 halfHV[256];                                                                                             \
+                                                                                                                       \
+		copy_block17(full, src, 24, stride, 17);                                                                       \
+		put##RND##mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);                                                     \
+		put##RND##pixels16_l2_8(halfH, halfH, full + 1, 16, 16, 24, 17);                                               \
+		put##RND##mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);                                                       \
+		OPNAME##pixels16_l2_8(dst, halfH, halfHV, stride, 16, 16, 16);                                                 \
+	}                                                                                                                  \
+                                                                                                                       \
+	void ff_##OPNAME##qpel16_mc13_old_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                              \
+		uint8 full[24 * 17];                                                                                           \
+		uint8 halfH[272];                                                                                              \
+		uint8 halfV[256];                                                                                              \
+		uint8 halfHV[256];                                                                                             \
+                                                                                                                       \
+		copy_block17(full, src, 24, stride, 17);                                                                       \
+		put##RND##mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);                                                     \
+		put##RND##mpeg4_qpel16_v_lowpass(halfV, full, 16, 24);                                                         \
+		put##RND##mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);                                                       \
+		OPNAME##pixels16_l4_8(dst, full + 24, halfH + 16, halfV, halfHV, stride, 24, 16, 16, 16, 16);                  \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel16_mc13_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                \
+		uint8 full[24 * 17];                                                                                           \
+		uint8 halfH[272];                                                                                              \
+		uint8 halfHV[256];                                                                                             \
+                                                                                                                       \
+		copy_block17(full, src, 24, stride, 17);                                                                       \
+		put##RND##mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);                                                     \
+		put##RND##pixels16_l2_8(halfH, halfH, full, 16, 16, 24, 17);                                                   \
+		put##RND##mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);                                                       \
+		OPNAME##pixels16_l2_8(dst, halfH + 16, halfHV, stride, 16, 16, 16);                                            \
+	}                                                                                                                  \
+                                                                                                                       \
+	void ff_##OPNAME##qpel16_mc33_old_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                              \
+		uint8 full[24 * 17];                                                                                           \
+		uint8 halfH[272];                                                                                              \
+		uint8 halfV[256];                                                                                              \
+		uint8 halfHV[256];                                                                                             \
+                                                                                                                       \
+		copy_block17(full, src, 24, stride, 17);                                                                       \
+		put##RND##mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);                                                     \
+		put##RND##mpeg4_qpel16_v_lowpass(halfV, full + 1, 16, 24);                                                     \
+		put##RND##mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);                                                       \
+		OPNAME##pixels16_l4_8(dst, full + 25, halfH + 16, halfV, halfHV, stride, 24, 16, 16, 16, 16);                  \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel16_mc33_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                \
+		uint8 full[24 * 17];                                                                                           \
+		uint8 halfH[272];                                                                                              \
+		uint8 halfHV[256];                                                                                             \
+                                                                                                                       \
+		copy_block17(full, src, 24, stride, 17);                                                                       \
+		put##RND##mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);                                                     \
+		put##RND##pixels16_l2_8(halfH, halfH, full + 1, 16, 16, 24, 17);                                               \
+		put##RND##mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);                                                       \
+		OPNAME##pixels16_l2_8(dst, halfH + 16, halfHV, stride, 16, 16, 16);                                            \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel16_mc21_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                \
+		uint8 halfH[272];                                                                                              \
+		uint8 halfHV[256];                                                                                             \
+                                                                                                                       \
+		put##RND##mpeg4_qpel16_h_lowpass(halfH, src, 16, stride, 17);                                                  \
+		put##RND##mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);                                                       \
+		OPNAME##pixels16_l2_8(dst, halfH, halfHV, stride, 16, 16, 16);                                                 \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel16_mc23_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                \
+		uint8 halfH[272];                                                                                              \
+		uint8 halfHV[256];                                                                                             \
+                                                                                                                       \
+		put##RND##mpeg4_qpel16_h_lowpass(halfH, src, 16, stride, 17);                                                  \
+		put##RND##mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);                                                       \
+		OPNAME##pixels16_l2_8(dst, halfH + 16, halfHV, stride, 16, 16, 16);                                            \
+	}                                                                                                                  \
+                                                                                                                       \
+	void ff_##OPNAME##qpel16_mc12_old_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                              \
+		uint8 full[24 * 17];                                                                                           \
+		uint8 halfH[272];                                                                                              \
+		uint8 halfV[256];                                                                                              \
+		uint8 halfHV[256];                                                                                             \
+                                                                                                                       \
+		copy_block17(full, src, 24, stride, 17);                                                                       \
+		put##RND##mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);                                                     \
+		put##RND##mpeg4_qpel16_v_lowpass(halfV, full, 16, 24);                                                         \
+		put##RND##mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);                                                       \
+		OPNAME##pixels16_l2_8(dst, halfV, halfHV, stride, 16, 16, 16);                                                 \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel16_mc12_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                \
+		uint8 full[24 * 17];                                                                                           \
+		uint8 halfH[272];                                                                                              \
+                                                                                                                       \
+		copy_block17(full, src, 24, stride, 17);                                                                       \
+		put##RND##mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);                                                     \
+		put##RND##pixels16_l2_8(halfH, halfH, full, 16, 16, 24, 17);                                                   \
+		OPNAME##mpeg4_qpel16_v_lowpass(dst, halfH, stride, 16);                                                        \
+	}                                                                                                                  \
+                                                                                                                       \
+	void ff_##OPNAME##qpel16_mc32_old_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                              \
+		uint8 full[24 * 17];                                                                                           \
+		uint8 halfH[272];                                                                                              \
+		uint8 halfV[256];                                                                                              \
+		uint8 halfHV[256];                                                                                             \
+                                                                                                                       \
+		copy_block17(full, src, 24, stride, 17);                                                                       \
+		put##RND##mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);                                                     \
+		put##RND##mpeg4_qpel16_v_lowpass(halfV, full + 1, 16, 24);                                                     \
+		put##RND##mpeg4_qpel16_v_lowpass(halfHV, halfH, 16, 16);                                                       \
+		OPNAME##pixels16_l2_8(dst, halfV, halfHV, stride, 16, 16, 16);                                                 \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel16_mc32_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                \
+		uint8 full[24 * 17];                                                                                           \
+		uint8 halfH[272];                                                                                              \
+                                                                                                                       \
+		copy_block17(full, src, 24, stride, 17);                                                                       \
+		put##RND##mpeg4_qpel16_h_lowpass(halfH, full, 16, 24, 17);                                                     \
+		put##RND##pixels16_l2_8(halfH, halfH, full + 1, 16, 16, 24, 17);                                               \
+		OPNAME##mpeg4_qpel16_v_lowpass(dst, halfH, stride, 16);                                                        \
+	}                                                                                                                  \
+                                                                                                                       \
+	static void OPNAME##qpel16_mc22_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {                                \
+		uint8 halfH[272];                                                                                              \
+                                                                                                                       \
+		put##RND##mpeg4_qpel16_h_lowpass(halfH, src, 16, stride, 17);                                                  \
+		OPNAME##mpeg4_qpel16_v_lowpass(dst, halfH, stride, 16);                                                        \
+	}
+
+#define op_avg(a, b) a = (((a) + cm[((b) + 16) >> 5] + 1) >> 1)
+#define op_put(a, b) a = cm[((b) + 16) >> 5]
+#define op_put_no_rnd(a, b) a = cm[((b) + 15) >> 5]
+
+QPEL_MC(0, put_, _, op_put)
+QPEL_MC(1, put_no_rnd_, _no_rnd_, op_put_no_rnd)
+QPEL_MC(0, avg_, _, op_avg)
+
+#undef op_avg
+#undef op_put
+#undef op_put_no_rnd
+
+void ff_put_pixels8x8_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {
+	put_pixels8_8_c(dst, src, stride, 8);
+}
+
+void ff_avg_pixels8x8_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {
+	avg_pixels8_8_c(dst, src, stride, 8);
+}
+
+void ff_put_pixels16x16_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {
+	put_pixels16_8_c(dst, src, stride, 16);
+}
+
+void ff_avg_pixels16x16_c(uint8 *dst, const uint8 *src, ptrdiff_t stride) {
+	avg_pixels16_8_c(dst, src, stride, 16);
+}
+
+#define put_qpel8_mc00_c ff_put_pixels8x8_c
+#define avg_qpel8_mc00_c ff_avg_pixels8x8_c
+#define put_qpel16_mc00_c ff_put_pixels16x16_c
+#define avg_qpel16_mc00_c ff_avg_pixels16x16_c
+#define put_no_rnd_qpel8_mc00_c ff_put_pixels8x8_c
+#define put_no_rnd_qpel16_mc00_c ff_put_pixels16x16_c
+
+void initQpel(QpelDSP *c) {
+#define dspfunc(PFX, IDX, NUM)                                                                                         \
+	c->PFX##_pixels_tab[IDX][0] = PFX##NUM##_mc00_c;                                                                   \
+	c->PFX##_pixels_tab[IDX][1] = PFX##NUM##_mc10_c;                                                                   \
+	c->PFX##_pixels_tab[IDX][2] = PFX##NUM##_mc20_c;                                                                   \
+	c->PFX##_pixels_tab[IDX][3] = PFX##NUM##_mc30_c;                                                                   \
+	c->PFX##_pixels_tab[IDX][4] = PFX##NUM##_mc01_c;                                                                   \
+	c->PFX##_pixels_tab[IDX][5] = PFX##NUM##_mc11_c;                                                                   \
+	c->PFX##_pixels_tab[IDX][6] = PFX##NUM##_mc21_c;                                                                   \
+	c->PFX##_pixels_tab[IDX][7] = PFX##NUM##_mc31_c;                                                                   \
+	c->PFX##_pixels_tab[IDX][8] = PFX##NUM##_mc02_c;                                                                   \
+	c->PFX##_pixels_tab[IDX][9] = PFX##NUM##_mc12_c;                                                                   \
+	c->PFX##_pixels_tab[IDX][10] = PFX##NUM##_mc22_c;                                                                  \
+	c->PFX##_pixels_tab[IDX][11] = PFX##NUM##_mc32_c;                                                                  \
+	c->PFX##_pixels_tab[IDX][12] = PFX##NUM##_mc03_c;                                                                  \
+	c->PFX##_pixels_tab[IDX][13] = PFX##NUM##_mc13_c;                                                                  \
+	c->PFX##_pixels_tab[IDX][14] = PFX##NUM##_mc23_c;                                                                  \
+	c->PFX##_pixels_tab[IDX][15] = PFX##NUM##_mc33_c
+
+	dspfunc(put_qpel, 0, 16);
+	dspfunc(put_qpel, 1, 8);
+
+	dspfunc(put_no_rnd_qpel, 0, 16);
+	dspfunc(put_no_rnd_qpel, 1, 8);
+
+	dspfunc(avg_qpel, 0, 16);
+	dspfunc(avg_qpel, 1, 8);
+}
+
+#undef QPEL_MC
+#undef avg_qpel16_mc00_c
+#undef avg_qpel8_mc00_c
+#undef dspfunc
+#undef put_no_rnd_qpel16_mc00_c
+#undef put_no_rnd_qpel8_mc00_c
+#undef put_qpel16_mc00_c
+#undef put_qpel8_mc00_c
+
+/*
+ * 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)
+
+/**
+ Collect statistics and prepare the edge pixels required by the other spatial compensation functions.
+
+ * @param src pointer to the beginning of the processed block
+ * @param dst pointer to emu_edge, edge pixels are stored the way other compensation routines do.
+ * @param linesize byte offset between 2 vertical pixels in the source image
+ * @param range pointer to the variable where the edge pixel range is to be stored (max-min values)
+ * @param psum  pointer to the variable where the edge pixel sum is to be stored
+ * @param edges Informs this routine that the block is on an image border, so it has to interpolate the missing edge
+pixels. and some of the edge pixels should be interpolated, the flag has the following meaning: 1   - mb_x==0 - first
+block in the row, interpolate area #1,#2,#3; 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(const uint8 *src, uint8 *dst, ptrdiff_t stride, int *range, int *psum,
+										  int edges) {
+	const uint8 *ptr;
+	int sum;
+	int i;
+	int min_pix, max_pix;
+	uint8 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. */
+		return;
+	}
+
+	min_pix = 256;
+	max_pix = -1;
+
+	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;
+
+			sum += c;
+			min_pix = MIN(min_pix, int(c));
+			max_pix = MAX(max_pix, int(c));
+			dst[area2 + i] = c;
+
+			ptr += stride;
+		}
+	}
+
+	if (!(edges & 2)) {     // (mb_y != 0) // there is row above
+		ptr = src - stride; // top line
+		for (i = 0; i < 8; i++) {
+			c = *(ptr + i);
+			sum += c;
+			min_pix = MIN(min_pix, int(c));
+			max_pix = MAX(max_pix, int(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
+		}
+		// area6 always present in the above block
+		memcpy(dst + area6, ptr - stride, 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, 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 c = *(src - 1 - stride);
+		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;
+}
+
+static const uint16 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(const uint8 *src, uint8 *dst, ptrdiff_t stride) {
+	int i, j;
+	int x, y;
+	unsigned int p; // power divided by 2
+	int a;
+	uint16 left_sum[2][8] = {{0}};
+	uint16 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[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 < 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 (y = 0; y < 8; y++) {
+		for (x = 0; x < 8; x++)
+			dst[x] = ((uint32)top_sum[0][x] * zero_prediction_weights[y * 16 + x * 2 + 0] +
+					  (uint32)left_sum[0][y] * zero_prediction_weights[y * 16 + x * 2 + 1] + 0x8000) >>
+					 16;
+		dst += stride;
+	}
+}
+
+static void spatial_compensation_1(const uint8 *src, uint8 *dst, ptrdiff_t stride) {
+	int x, y;
+
+	for (y = 0; y < 8; y++) {
+		for (x = 0; x < 8; x++)
+			dst[x] = src[area4 + MIN(2 * y + x + 2, 15)];
+		dst += stride;
+	}
+}
+
+static void spatial_compensation_2(const uint8 *src, uint8 *dst, ptrdiff_t stride) {
+	for (int y = 0; y < 8; y++) {
+		memcpy(dst, src + area4 + 1 + y, 8);
+		dst += stride;
+	}
+}
+
+static void spatial_compensation_3(const uint8 *src, uint8 *dst, ptrdiff_t stride) {
+	for (int y = 0; y < 8; y++) {
+		memcpy(dst, src + area4 + ((y + 1) >> 1), 8);
+		dst += stride;
+	}
+}
+
+static void spatial_compensation_4(const uint8 *src, uint8 *dst, ptrdiff_t stride) {
+	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 += stride;
+	}
+}
+
+static void spatial_compensation_5(const uint8 *src, uint8 *dst, ptrdiff_t stride) {
+	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 += stride;
+	}
+}
+
+static void spatial_compensation_6(const uint8 *src, uint8 *dst, ptrdiff_t stride) {
+	for (int y = 0; y < 8; y++) {
+		memcpy(dst, src + area3 - y, 8);
+		dst += stride;
+	}
+}
+
+static void spatial_compensation_7(const uint8 *src, uint8 *dst, ptrdiff_t stride) {
+	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 += stride;
+	}
+}
+
+static void spatial_compensation_8(const uint8 *src, uint8 *dst, ptrdiff_t stride) {
+	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 += stride;
+	}
+}
+
+static void spatial_compensation_9(const uint8 *src, uint8 *dst, ptrdiff_t stride) {
+	int x, y;
+
+	for (y = 0; y < 8; y++) {
+		for (x = 0; x < 8; x++)
+			dst[x] = src[area2 + 6 - MIN(x + y, 6)];
+		dst += stride;
+	}
+}
+
+static void spatial_compensation_10(const uint8 *src, uint8 *dst, ptrdiff_t stride) {
+	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 += stride;
+	}
+}
+
+static void spatial_compensation_11(const uint8 *src, uint8 *dst, ptrdiff_t stride) {
+	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 += stride;
+	}
+}
+
+static void x8_loop_filter(uint8 *ptr, const ptrdiff_t a_stride, const ptrdiff_t 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 = (ABS(p1 - p2) <= ql) + (ABS(p2 - p3) <= ql) + (ABS(p3 - p4) <= ql) + (ABS(p4 - p5) <= ql);
+
+		// You need at least 1 to be able to reach a total score of 6.
+		if (t > 0) {
+			t += (ABS(p5 - p6) <= ql) + (ABS(p6 - p7) <= ql) + (ABS(p7 - p8) <= ql) + (ABS(p8 - p9) <= ql) +
+				 (ABS(p0 - p1) <= ql);
+			if (t >= 6) {
+				int min, max;
+
+				min = max = p1;
+				min = MIN(min, p3);
+				max = MAX(max, p3);
+				min = MIN(min, p5);
+				max = MAX(max, p5);
+				min = MIN(min, p8);
+				max = MAX(max, p8);
+				if (max - min < 2 * quant) { // early stop
+					min = MIN(min, p2);
+					max = MAX(max, p2);
+					min = MIN(min, p4);
+					max = MAX(max, p4);
+					min = MIN(min, p6);
+					max = MAX(max, p6);
+					min = MIN(min, p7);
+					max = MAX(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 m;
+
+			x0 = (2 * p3 - 5 * p4 + 5 * p5 - 2 * p6 + 4) >> 3;
+			if (ABS(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 = ABS(x0) - MIN(ABS(x1), ABS(x2));
+				m = p4 - p5;
+
+				if (x > 0 && (m ^ x0) < 0) {
+					int32 sign;
+
+					sign = m >> 31;
+					m = (m ^ sign) - sign; // abs(m)
+					m >>= 1;
+
+					x = 5 * x >> 3;
+
+					if (x > m)
+						x = m;
+
+					x = (x ^ sign) - sign;
+
+					ptr[-1 * a_stride] -= x;
+					ptr[0] += x;
+				}
+			}
+		}
+	}
+}
+
+static void x8_h_loop_filter(uint8 *src, ptrdiff_t stride, int qscale) {
+	x8_loop_filter(src, stride, 1, qscale);
+}
+
+static void x8_v_loop_filter(uint8 *src, ptrdiff_t stride, int qscale) {
+	x8_loop_filter(src, 1, stride, qscale);
+}
+
+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;
+}
+
+#undef area1
+#undef area2
+#undef area3
+#undef area4
+#undef area5
+#undef area6
+
+static const uint8 x8_orient_lowquant_table[4][12][2] = {
+	{
+		/* Orient lowquant table 0 */
+		{0, 1},
+		{1, 3},
+		{2, 3},
+		{3, 4},
+		{4, 4},
+		{5, 6},
+		{7, 6},
+		{6, 5},
+		{8, 6},
+		{9, 6},
+		{10, 6},
+		{11, 6},
+	},
+	{
+		/* Orient lowquant table 1 */
+		{0, 5},
+		{1, 5},
+		{2, 5},
+		{6, 5},
+		{5, 4},
+		{8, 4},
+		{3, 2},
+		{4, 2},
+		{7, 3},
+		{9, 4},
+		{10, 5},
+		{11, 5},
+	},
+	{
+		/* Orient lowquant table 2 */
+		{0, 2},
+		{1, 2},
+		{2, 3},
+		{3, 3},
+		{4, 3},
+		{5, 6},
+		{6, 6},
+		{7, 5},
+		{8, 6},
+		{9, 6},
+		{10, 6},
+		{11, 6},
+	},
+	{
+		/* Orient lowquant table 3 */
+		{0, 3},
+		{1, 4},
+		{2, 4},
+		{3, 2},
+		{4, 2},
+		{5, 5},
+		{6, 5},
+		{7, 4},
+		{8, 5},
+		{9, 5},
+		{10, 5},
+		{11, 5},
+	},
+};
+
+static const uint8 x8_orient_highquant_table[2][12][2] = {
+	{
+		/* Orient highquant table 0 */
+		{0, 2},
+		{1, 2},
+		{2, 3},
+		{3, 3},
+		{4, 3},
+		{5, 6},
+		{7, 6},
+		{6, 5},
+		{8, 6},
+		{9, 6},
+		{10, 6},
+		{11, 6},
+	},
+	{
+		/* Orient highquant table 1 */
+		{0, 1},
+		{1, 2},
+		{2, 3},
+		{3, 5},
+		{4, 5},
+		{5, 7},
+		{7, 7},
+		{6, 6},
+		{8, 7},
+		{9, 7},
+		{10, 7},
+		{11, 7},
+	},
+};
+#define MAX_OR_VLC_BITS 7
+
+static const uint8 x8_dc_quant_table[2][8][34][2] = {
+	{
+		{
+			/* DC highquant table 0 */
+			{0, 5},   {3, 5},   {1, 4},   {2, 4},   {4, 5},   {6, 5},   {5, 4},   {7, 5},   {8, 7},
+			{9, 7},   {10, 12}, {11, 12}, {12, 12}, {13, 12}, {14, 12}, {15, 12}, {16, 12}, {25, 12},
+			{26, 12}, {27, 12}, {28, 12}, {29, 12}, {30, 12}, {31, 12}, {32, 12}, {33, 12}, {24, 8},
+			{23, 7},  {17, 3},  {18, 2},  {19, 3},  {20, 4},  {21, 5},  {22, 5},
+		},
+		{
+			/* DC highquant table 1 */
+			{0, 3},   {1, 3},   {2, 3},   {3, 4},   {4, 4},   {5, 3},   {6, 4},   {7, 4},   {8, 6},
+			{9, 7},   {10, 7},  {11, 11}, {12, 11}, {13, 11}, {14, 11}, {15, 11}, {16, 11}, {25, 11},
+			{27, 11}, {28, 11}, {29, 11}, {30, 11}, {31, 11}, {32, 10}, {33, 10}, {23, 7},  {17, 6},
+			{18, 4},  {19, 5},  {20, 5},  {21, 6},  {24, 7},  {26, 7},  {22, 5},
+		},
+		{
+			/* DC highquant table 2 */
+			{0, 7},   {1, 7},   {2, 6},   {3, 7},   {5, 7},   {4, 6},   {6, 8},   {7, 8},   {8, 13},
+			{9, 13},  {10, 13}, {11, 13}, {12, 13}, {13, 13}, {14, 13}, {15, 13}, {16, 12}, {23, 12},
+			{24, 12}, {25, 12}, {26, 12}, {27, 12}, {28, 12}, {29, 12}, {30, 12}, {31, 12}, {32, 12},
+			{33, 12}, {22, 8},  {21, 6},  {20, 5},  {19, 3},  {18, 2},  {17, 1},
+		},
+		{
+			/* DC highquant table 3 */
+			{0, 4},   {3, 4},   {1, 3},   {2, 3},   {4, 4},   {8, 5},   {9, 5},   {5, 3},   {6, 3},
+			{7, 3},   {10, 7},  {11, 11}, {12, 11}, {13, 11}, {14, 11}, {15, 11}, {16, 11}, {25, 11},
+			{26, 11}, {27, 11}, {29, 11}, {30, 11}, {31, 11}, {32, 10}, {33, 10}, {18, 7},  {21, 7},
+			{17, 5},  {19, 6},  {20, 6},  {22, 7},  {23, 7},  {24, 7},  {28, 7},
+		},
+		{
+			/* DC highquant table 4 */
+			{0, 8},   {4, 9},   {6, 9},   {1, 7},   {2, 7},   {3, 7},   {5, 8},   {7, 14},  {8, 14},
+			{9, 14},  {10, 14}, {11, 14}, {12, 14}, {13, 14}, {14, 14}, {15, 13}, {16, 13}, {24, 13},
+			{25, 13}, {26, 13}, {27, 13}, {28, 13}, {29, 13}, {30, 13}, {31, 13}, {32, 13}, {33, 13},
+			{23, 9},  {22, 7},  {21, 6},  {20, 4},  {19, 3},  {17, 2},  {18, 1},
+		},
+		{
+			/* DC highquant table 5 */
+			{0, 7},  {1, 7},  {2, 6},  {3, 6},  {4, 6},  {5, 6},  {6, 6},  {7, 6},  {8, 6},  {9, 6},  {10, 6}, {11, 6},
+			{12, 6}, {13, 6}, {14, 6}, {15, 6}, {16, 6}, {17, 6}, {18, 6}, {19, 6}, {20, 6}, {21, 6}, {22, 6}, {23, 6},
+			{24, 6}, {25, 6}, {26, 6}, {28, 6}, {29, 6}, {30, 6}, {31, 6}, {32, 6}, {33, 6}, {27, 1},
+		},
+		{
+			/* DC highquant table 6 */
+			{0, 5},   {2, 5},   {1, 4},   {3, 5},   {4, 6},   {6, 6},   {5, 5},   {7, 6},   {8, 8},
+			{9, 8},   {10, 13}, {11, 13}, {12, 13}, {13, 13}, {14, 13}, {15, 13}, {16, 13}, {25, 13},
+			{26, 13}, {27, 13}, {28, 13}, {29, 13}, {30, 13}, {31, 13}, {32, 13}, {33, 13}, {24, 9},
+			{23, 8},  {17, 2},  {18, 2},  {19, 3},  {20, 4},  {21, 5},  {22, 5},
+		},
+		{
+			/* DC highquant table 7 */
+			{0, 7},  {1, 7},  {2, 7},  {3, 7},  {4, 7},  {5, 7},  {6, 7},  {7, 7},  {8, 7},  {9, 7},  {10, 7}, {11, 7},
+			{12, 7}, {13, 7}, {14, 7}, {15, 7}, {16, 7}, {19, 7}, {20, 7}, {21, 7}, {22, 7}, {23, 7}, {24, 7}, {25, 7},
+			{26, 7}, {27, 7}, {28, 7}, {29, 7}, {30, 7}, {31, 7}, {32, 7}, {33, 7}, {18, 2}, {17, 1},
+		},
+	},
+	{
+		{
+			/* DC lowquant table 0 */
+			{0, 5},   {2, 5},   {1, 4},   {3, 5},   {4, 5},   {5, 5},   {6, 6},   {7, 6},   {8, 8},
+			{9, 8},   {10, 13}, {11, 13}, {12, 13}, {13, 13}, {14, 13}, {15, 13}, {16, 13}, {25, 13},
+			{26, 13}, {27, 13}, {28, 13}, {29, 13}, {30, 13}, {31, 13}, {32, 13}, {33, 13}, {24, 9},
+			{23, 8},  {22, 6},  {21, 5},  {20, 4},  {19, 3},  {17, 2},  {18, 2},
+		},
+		{
+			/* DC lowquant table 1 */
+			{0, 4},   {3, 4},   {1, 3},   {2, 3},   {4, 4},   {6, 4},   {5, 3},   {7, 3},   {8, 4},
+			{9, 4},   {10, 5},  {11, 6},  {12, 9},  {13, 9},  {14, 13}, {15, 13}, {16, 13}, {25, 13},
+			{26, 13}, {27, 13}, {28, 12}, {29, 12}, {31, 12}, {32, 12}, {33, 12}, {21, 9},  {20, 7},
+			{17, 6},  {18, 6},  {19, 6},  {22, 7},  {23, 8},  {24, 9},  {30, 9},
+		},
+		{
+			/* DC lowquant table 2 */
+			{0, 4},   {3, 4},   {1, 3},   {2, 3},   {4, 4},   {5, 4},   {6, 4},   {7, 4},   {8, 6},
+			{9, 6},   {10, 7},  {11, 7},  {12, 12}, {13, 12}, {14, 12}, {15, 12}, {16, 12}, {25, 12},
+			{26, 12}, {27, 12}, {28, 12}, {29, 12}, {30, 12}, {31, 12}, {32, 11}, {33, 11}, {24, 8},
+			{23, 7},  {17, 4},  {18, 3},  {19, 4},  {20, 5},  {21, 6},  {22, 6},
+		},
+		{
+			/* DC lowquant table 3 */
+			{0, 4},   {6, 4},   {2, 3},   {1, 2},   {3, 3},   {4, 3},   {5, 3},   {7, 4},   {8, 6},
+			{9, 6},   {10, 7},  {11, 8},  {12, 14}, {13, 14}, {14, 14}, {15, 14}, {16, 13}, {21, 13},
+			{22, 13}, {23, 13}, {24, 13}, {25, 13}, {26, 13}, {27, 13}, {28, 13}, {29, 13}, {30, 13},
+			{31, 13}, {32, 13}, {33, 13}, {17, 9},  {18, 7},  {19, 8},  {20, 8},
+		},
+		{
+			/* DC lowquant table 4 */
+			{0, 7},  {1, 7},  {2, 7},  {3, 7},  {4, 7},  {5, 7},  {6, 7},  {7, 7},  {8, 7},  {9, 7},  {10, 7}, {11, 7},
+			{12, 7}, {13, 7}, {14, 7}, {15, 7}, {16, 7}, {19, 7}, {20, 7}, {21, 7}, {22, 7}, {23, 7}, {24, 7}, {25, 7},
+			{26, 7}, {27, 7}, {28, 7}, {29, 7}, {30, 7}, {31, 7}, {32, 7}, {33, 7}, {18, 2}, {17, 1},
+		},
+		{
+			/* DC lowquant table 5 */
+			{0, 5},   {2, 5},   {1, 4},   {3, 6},   {4, 6},   {5, 6},   {6, 7},   {8, 7},   {7, 6},
+			{9, 6},   {10, 8},  {12, 8},  {11, 7},  {13, 13}, {14, 13}, {15, 13}, {16, 13}, {23, 13},
+			{24, 13}, {25, 13}, {26, 13}, {27, 13}, {28, 13}, {29, 13}, {30, 13}, {31, 13}, {32, 13},
+			{33, 12}, {22, 9},  {21, 8},  {20, 7},  {17, 3},  {19, 3},  {18, 1},
+		},
+		{
+			/* DC lowquant table 6 */
+			{0, 4},   {4, 4},   {2, 3},   {1, 2},   {3, 3},   {5, 4},   {6, 5},   {7, 6},   {8, 7},
+			{9, 7},   {10, 8},  {11, 14}, {12, 14}, {15, 14}, {16, 14}, {23, 14}, {24, 14}, {25, 14},
+			{26, 14}, {27, 14}, {28, 14}, {29, 14}, {30, 14}, {31, 14}, {32, 14}, {33, 13}, {13, 10},
+			{14, 9},  {21, 8},  {22, 8},  {20, 6},  {19, 5},  {17, 4},  {18, 3},
+		},
+		{
+			/* DC lowquant table 7 */
+			{0, 6},   {1, 6},   {2, 6},   {3, 7},   {4, 7},   {5, 6},   {6, 6},   {7, 6},   {8, 7},
+			{9, 8},   {10, 8},  {11, 9},  {12, 10}, {13, 14}, {14, 14}, {15, 14}, {16, 14}, {24, 14},
+			{25, 14}, {26, 14}, {27, 14}, {28, 14}, {29, 14}, {30, 14}, {31, 14}, {32, 13}, {33, 13},
+			{23, 8},  {22, 7},  {21, 6},  {20, 5},  {19, 4},  {18, 2},  {17, 1},
+		},
+	},
+};
+#define MAX_DC_VLC_BITS 14
+
+static const uint8 x8_ac_quant_table[2][2][8][77][2] = {
+	{
+		{
+			{
+				/* AC highquant table group 0, table 0 */
+				{0, 3},   {1, 4},   {2, 6},   {3, 6},   {4, 7},   {6, 15},  {8, 15},  {10, 15}, {12, 15}, {13, 15},
+				{14, 15}, {15, 14}, {34, 14}, {45, 14}, {46, 14}, {47, 14}, {49, 14}, {50, 14}, {51, 14}, {52, 14},
+				{53, 14}, {54, 14}, {55, 14}, {56, 14}, {57, 14}, {58, 14}, {60, 14}, {61, 14}, {62, 14}, {63, 14},
+				{64, 14}, {65, 14}, {67, 14}, {69, 14}, {70, 14}, {71, 14}, {72, 14}, {74, 14}, {75, 14}, {76, 14},
+				{9, 9},   {7, 8},   {5, 6},   {11, 9},  {18, 9},  {19, 9},  {22, 9},  {20, 7},  {17, 6},  {16, 5},
+				{21, 7},  {29, 8},  {33, 8},  {28, 6},  {27, 5},  {24, 3},  {23, 2},  {25, 4},  {26, 4},  {30, 7},
+				{32, 7},  {31, 6},  {35, 7},  {36, 7},  {37, 7},  {38, 9},  {41, 9},  {42, 8},  {39, 5},  {40, 6},
+				{43, 9},  {44, 9},  {48, 8},  {59, 9},  {66, 9},  {68, 9},  {73, 9},
+			},
+			{
+				/* AC highquant table group 0, table 1 */
+				{0, 3},   {1, 4},   {2, 4},   {3, 5},   {4, 6},   {5, 6},   {6, 6},   {7, 6},   {8, 7},   {9, 8},
+				{10, 8},  {11, 8},  {12, 8},  {13, 14}, {44, 14}, {47, 14}, {50, 14}, {51, 14}, {54, 14}, {55, 14},
+				{56, 14}, {63, 14}, {64, 14}, {67, 14}, {68, 14}, {69, 14}, {70, 14}, {72, 14}, {76, 14}, {14, 10},
+				{15, 10}, {45, 10}, {32, 8},  {16, 4},  {17, 5},  {18, 6},  {19, 7},  {31, 7},  {20, 5},  {21, 6},
+				{26, 6},  {22, 5},  {24, 5},  {23, 4},  {25, 5},  {27, 6},  {28, 6},  {29, 6},  {30, 6},  {33, 8},
+				{38, 8},  {34, 7},  {35, 7},  {36, 7},  {37, 7},  {39, 7},  {40, 7},  {41, 8},  {42, 8},  {43, 8},
+				{46, 9},  {49, 9},  {53, 8},  {58, 8},  {57, 6},  {48, 5},  {52, 5},  {59, 7},  {60, 8},  {61, 9},
+				{66, 9},  {62, 8},  {65, 8},  {71, 9},  {75, 9},  {74, 8},  {73, 5},
+			},
+			{
+				/* AC highquant table group 0, table 2 */
+				{0, 4},   {1, 5},   {2, 12},  {3, 12},  {4, 12},  {5, 12},  {6, 12},  {7, 12},  {8, 12},  {9, 12},
+				{10, 12}, {11, 12}, {12, 11}, {13, 11}, {14, 11}, {15, 11}, {16, 11}, {17, 11}, {18, 11}, {19, 11},
+				{20, 11}, {21, 11}, {22, 11}, {28, 11}, {29, 11}, {30, 11}, {31, 11}, {32, 11}, {33, 11}, {34, 11},
+				{35, 11}, {36, 11}, {37, 11}, {38, 11}, {40, 11}, {41, 11}, {42, 11}, {43, 11}, {44, 11}, {45, 11},
+				{46, 11}, {47, 11}, {48, 11}, {49, 11}, {50, 11}, {51, 11}, {52, 11}, {53, 11}, {54, 11}, {55, 11},
+				{56, 11}, {57, 11}, {58, 11}, {59, 11}, {60, 11}, {61, 11}, {62, 11}, {63, 11}, {64, 11}, {65, 11},
+				{66, 11}, {67, 11}, {68, 11}, {69, 11}, {70, 11}, {71, 11}, {72, 11}, {73, 11}, {74, 11}, {75, 11},
+				{76, 11}, {25, 5},  {26, 5},  {27, 5},  {39, 5},  {24, 2},  {23, 1},
+			},
+			{
+				/* AC highquant table group 0, table 3 */
+				{0, 8},  {1, 8},  {2, 8},  {3, 8},  {4, 8},  {5, 8},  {6, 8},  {7, 8},  {8, 8},  {9, 8},  {10, 8},
+				{11, 8}, {12, 8}, {13, 8}, {14, 8}, {15, 8}, {16, 8}, {17, 8}, {18, 8}, {19, 8}, {20, 8}, {21, 8},
+				{22, 8}, {24, 8}, {25, 7}, {26, 7}, {27, 7}, {28, 7}, {29, 7}, {30, 7}, {31, 7}, {32, 7}, {33, 7},
+				{34, 7}, {35, 7}, {36, 7}, {37, 7}, {38, 7}, {39, 7}, {40, 7}, {41, 7}, {42, 7}, {43, 7}, {44, 7},
+				{45, 7}, {46, 7}, {47, 7}, {48, 7}, {49, 7}, {50, 7}, {51, 7}, {52, 7}, {53, 7}, {54, 7}, {55, 7},
+				{56, 7}, {57, 7}, {58, 7}, {59, 7}, {60, 7}, {61, 7}, {62, 7}, {63, 7}, {64, 7}, {65, 7}, {66, 7},
+				{67, 7}, {68, 7}, {69, 7}, {70, 7}, {71, 7}, {72, 7}, {73, 7}, {74, 7}, {75, 7}, {76, 7}, {23, 1},
+			},
+			{
+				/* AC highquant table group 0, table 4 */
+				{0, 9},  {1, 9},  {2, 9},  {3, 9},  {4, 9},  {5, 9},  {6, 9},  {7, 9},  {8, 9},  {9, 9},  {10, 9},
+				{11, 9}, {12, 9}, {13, 9}, {14, 9}, {15, 9}, {16, 9}, {17, 9}, {18, 9}, {19, 9}, {20, 9}, {21, 9},
+				{22, 8}, {25, 8}, {26, 8}, {27, 8}, {28, 8}, {29, 8}, {30, 8}, {31, 8}, {32, 8}, {33, 8}, {34, 8},
+				{35, 8}, {36, 8}, {37, 8}, {38, 8}, {39, 8}, {40, 8}, {41, 8}, {42, 8}, {43, 8}, {44, 8}, {45, 8},
+				{46, 8}, {47, 8}, {48, 8}, {49, 8}, {50, 8}, {51, 8}, {52, 8}, {53, 8}, {54, 8}, {55, 8}, {56, 8},
+				{57, 8}, {58, 8}, {59, 8}, {60, 8}, {61, 8}, {62, 8}, {63, 8}, {64, 8}, {65, 8}, {66, 8}, {67, 8},
+				{68, 8}, {69, 8}, {70, 8}, {71, 8}, {72, 8}, {73, 8}, {74, 8}, {75, 8}, {76, 8}, {23, 2}, {24, 1},
+			},
+			{
+				/* AC highquant table group 0, table 5 */
+				{0, 10},  {1, 10},  {2, 10},  {3, 10},  {4, 10},  {5, 10},  {6, 10},  {7, 10},  {8, 10},  {9, 10},
+				{10, 10}, {11, 10}, {12, 10}, {13, 10}, {14, 10}, {15, 10}, {16, 10}, {17, 10}, {18, 10}, {19, 10},
+				{20, 9},  {21, 9},  {22, 9},  {25, 9},  {26, 9},  {28, 9},  {29, 9},  {30, 9},  {31, 9},  {32, 9},
+				{33, 9},  {34, 9},  {35, 9},  {36, 9},  {37, 9},  {38, 9},  {39, 9},  {40, 9},  {41, 9},  {42, 9},
+				{43, 9},  {44, 9},  {45, 9},  {46, 9},  {47, 9},  {48, 9},  {49, 9},  {50, 9},  {51, 9},  {52, 9},
+				{53, 9},  {54, 9},  {55, 9},  {56, 9},  {57, 9},  {58, 9},  {59, 9},  {60, 9},  {61, 9},  {62, 9},
+				{63, 9},  {64, 9},  {65, 9},  {66, 9},  {67, 9},  {68, 9},  {69, 9},  {70, 9},  {71, 9},  {72, 9},
+				{73, 9},  {74, 9},  {75, 9},  {76, 9},  {24, 3},  {27, 2},  {23, 1},
+			},
+			{
+				/* AC highquant table group 0, table 6 */
+				{0, 2},   {1, 4},   {2, 5},   {3, 5},   {4, 6},   {5, 6},   {6, 7},   {7, 8},   {8, 8},   {9, 8},
+				{10, 9},  {11, 9},  {12, 10}, {14, 10}, {13, 9},  {15, 15}, {42, 15}, {46, 15}, {50, 15}, {51, 15},
+				{55, 15}, {56, 14}, {59, 14}, {61, 14}, {62, 14}, {63, 14}, {64, 14}, {68, 14}, {69, 14}, {70, 14},
+				{71, 14}, {72, 14}, {75, 14}, {76, 14}, {43, 10}, {37, 9},  {17, 5},  {18, 6},  {19, 6},  {16, 3},
+				{20, 4},  {21, 7},  {24, 7},  {25, 7},  {26, 7},  {22, 5},  {23, 5},  {27, 8},  {30, 8},  {28, 7},
+				{29, 7},  {31, 8},  {32, 8},  {33, 8},  {34, 8},  {35, 8},  {36, 8},  {38, 8},  {39, 8},  {40, 8},
+				{41, 9},  {44, 10}, {45, 10}, {47, 10}, {54, 10}, {49, 9},  {58, 8},  {60, 10}, {66, 10}, {67, 10},
+				{74, 10}, {65, 8},  {48, 6},  {52, 4},  {53, 6},  {57, 6},  {73, 5},
+			},
+			{
+				/* AC highquant table group 0, table 7 */
+				{0, 3},   {1, 4},   {2, 5},   {3, 5},   {4, 6},   {5, 8},   {9, 13},  {12, 13}, {13, 13}, {14, 13},
+				{42, 13}, {45, 13}, {46, 13}, {47, 13}, {50, 13}, {51, 13}, {53, 13}, {54, 13}, {55, 13}, {56, 13},
+				{58, 13}, {61, 13}, {62, 13}, {63, 13}, {64, 13}, {66, 13}, {67, 13}, {68, 13}, {69, 13}, {70, 13},
+				{72, 12}, {74, 12}, {75, 12}, {76, 12}, {6, 7},   {7, 6},   {8, 7},   {10, 8},  {11, 8},  {15, 8},
+				{31, 8},  {18, 7},  {19, 6},  {17, 5},  {16, 4},  {20, 6},  {21, 7},  {36, 8},  {37, 8},  {22, 6},
+				{27, 6},  {23, 3},  {24, 5},  {25, 5},  {26, 4},  {28, 6},  {29, 6},  {30, 5},  {32, 6},  {33, 6},
+				{34, 6},  {35, 6},  {38, 7},  {40, 7},  {41, 7},  {43, 7},  {39, 5},  {44, 8},  {52, 8},  {48, 7},
+				{49, 7},  {57, 8},  {60, 8},  {59, 7},  {65, 8},  {71, 8},  {73, 6},
+			},
+		},
+		{
+			{
+				/* AC highquant table group 1, table 0 */
+				{0, 3},   {1, 4},   {2, 5},   {3, 5},   {4, 5},   {5, 5},   {6, 6},   {7, 7},   {9, 7},   {8, 6},
+				{10, 8},  {13, 8},  {11, 7},  {12, 7},  {14, 8},  {15, 9},  {41, 9},  {17, 6},  {18, 6},  {19, 7},
+				{21, 8},  {42, 9},  {43, 9},  {16, 4},  {20, 5},  {22, 6},  {26, 6},  {23, 4},  {24, 4},  {25, 5},
+				{27, 6},  {28, 6},  {29, 6},  {30, 7},  {31, 7},  {32, 7},  {33, 7},  {34, 7},  {35, 7},  {36, 7},
+				{37, 7},  {38, 7},  {39, 7},  {40, 7},  {44, 11}, {54, 14}, {55, 14}, {56, 14}, {64, 14}, {69, 14},
+				{70, 14}, {72, 14}, {76, 14}, {53, 10}, {45, 9},  {47, 8},  {46, 6},  {48, 5},  {49, 7},  {50, 9},
+				{51, 9},  {58, 10}, {67, 10}, {61, 9},  {52, 7},  {57, 7},  {59, 7},  {60, 8},  {62, 8},  {63, 7},
+				{65, 7},  {66, 7},  {68, 10}, {71, 10}, {74, 9},  {75, 8},  {73, 6},
+			},
+			{
+				/* AC highquant table group 1, table 1 */
+				{0, 2},   {1, 4},   {2, 5},   {3, 5},   {4, 6},   {5, 7},   {6, 7},   {7, 7},   {8, 8},   {9, 9},
+				{10, 9},  {11, 9},  {12, 9},  {13, 15}, {42, 15}, {44, 15}, {45, 15}, {46, 15}, {47, 15}, {50, 15},
+				{51, 15}, {56, 15}, {61, 15}, {62, 15}, {63, 15}, {64, 15}, {66, 15}, {67, 14}, {15, 11}, {14, 10},
+				{30, 9},  {19, 7},  {17, 5},  {18, 6},  {23, 6},  {16, 3},  {20, 4},  {21, 5},  {24, 7},  {25, 7},
+				{26, 8},  {27, 8},  {28, 7},  {22, 4},  {29, 8},  {31, 8},  {32, 9},  {33, 9},  {34, 9},  {35, 9},
+				{36, 10}, {37, 11}, {38, 11}, {39, 9},  {40, 9},  {41, 11}, {55, 11}, {43, 10}, {49, 8},  {54, 8},
+				{48, 6},  {53, 7},  {58, 8},  {59, 11}, {68, 14}, {69, 14}, {70, 14}, {71, 14}, {72, 14}, {74, 14},
+				{75, 14}, {76, 14}, {60, 10}, {65, 9},  {52, 4},  {57, 5},  {73, 5},
+			},
+			{
+				/* AC highquant table group 1, table 2 */
+				{0, 3},   {1, 4},   {2, 4},   {3, 5},   {4, 6},   {5, 7},   {7, 7},   {6, 6},   {8, 9},   {9, 9},
+				{10, 8},  {11, 15}, {13, 15}, {14, 15}, {15, 15}, {46, 15}, {47, 15}, {50, 15}, {51, 15}, {54, 14},
+				{55, 14}, {56, 14}, {62, 14}, {63, 14}, {64, 14}, {66, 14}, {67, 14}, {69, 14}, {70, 14}, {72, 14},
+				{76, 14}, {34, 10}, {12, 9},  {31, 8},  {17, 5},  {16, 3},  {18, 7},  {19, 7},  {21, 6},  {22, 5},
+				{20, 4},  {23, 4},  {24, 4},  {25, 5},  {26, 6},  {27, 6},  {28, 6},  {29, 6},  {30, 7},  {32, 7},
+				{33, 8},  {35, 8},  {36, 9},  {37, 10}, {38, 10}, {41, 9},  {42, 9},  {39, 6},  {40, 7},  {43, 8},
+				{44, 10}, {60, 10}, {45, 9},  {48, 7},  {49, 9},  {58, 9},  {53, 8},  {57, 6},  {52, 5},  {59, 9},
+				{61, 10}, {68, 10}, {65, 8},  {71, 9},  {75, 9},  {74, 8},  {73, 6},
+			},
+			{
+				/* AC highquant table group 1, table 3 */
+				{0, 3},   {1, 4},   {2, 5},   {3, 5},   {4, 6},   {5, 6},   {6, 7},   {7, 7},   {8, 6},   {9, 6},
+				{10, 7},  {11, 7},  {12, 9},  {13, 9},  {15, 8},  {14, 7},  {17, 6},  {16, 5},  {18, 9},  {42, 9},
+				{32, 8},  {19, 7},  {20, 6},  {21, 7},  {22, 7},  {27, 6},  {25, 5},  {23, 3},  {24, 3},  {26, 5},
+				{28, 6},  {29, 6},  {30, 7},  {31, 7},  {33, 8},  {34, 8},  {35, 8},  {41, 8},  {36, 7},  {38, 7},
+				{37, 6},  {39, 7},  {43, 14}, {44, 14}, {45, 14}, {50, 14}, {51, 14}, {53, 14}, {54, 13}, {55, 13},
+				{56, 13}, {58, 13}, {64, 13}, {67, 13}, {68, 13}, {69, 13}, {70, 13}, {71, 13}, {72, 13}, {74, 13},
+				{76, 13}, {47, 9},  {49, 8},  {40, 6},  {46, 7},  {48, 7},  {52, 8},  {57, 8},  {60, 7},  {59, 6},
+				{61, 9},  {75, 9},  {73, 8},  {63, 7},  {62, 6},  {65, 7},  {66, 7},
+			},
+			{
+				/* AC highquant table group 1, table 4 */
+				{0, 2},   {1, 4},   {2, 5},   {3, 5},   {4, 6},   {5, 6},   {6, 7},   {7, 7},   {8, 7},   {9, 8},
+				{10, 9},  {11, 9},  {12, 10}, {13, 10}, {14, 10}, {15, 15}, {50, 15}, {51, 15}, {54, 15}, {55, 15},
+				{56, 15}, {61, 15}, {64, 15}, {45, 12}, {47, 12}, {58, 12}, {32, 8},  {19, 7},  {18, 6},  {17, 5},
+				{16, 3},  {20, 4},  {21, 6},  {22, 6},  {24, 5},  {23, 4},  {25, 6},  {26, 6},  {27, 6},  {28, 7},
+				{29, 7},  {30, 7},  {31, 7},  {33, 8},  {34, 8},  {35, 8},  {36, 8},  {37, 8},  {38, 10}, {43, 10},
+				{41, 9},  {39, 7},  {40, 8},  {42, 9},  {44, 10}, {46, 10}, {49, 8},  {53, 9},  {59, 10}, {60, 10},
+				{48, 6},  {52, 6},  {57, 7},  {62, 12}, {67, 15}, {69, 15}, {70, 15}, {71, 15}, {72, 14}, {76, 14},
+				{63, 11}, {68, 12}, {74, 12}, {75, 11}, {66, 9},  {65, 8},  {73, 6},
+			},
+			{
+				/* AC highquant table group 1, table 5 */
+				{0, 3},   {1, 4},   {2, 4},   {3, 5},   {4, 5},   {5, 6},   {6, 7},   {7, 8},   {8, 11},  {10, 11},
+				{11, 10}, {9, 9},   {12, 11}, {13, 15}, {14, 15}, {15, 15}, {47, 15}, {49, 15}, {50, 15}, {51, 15},
+				{54, 15}, {55, 14}, {56, 14}, {58, 14}, {63, 14}, {38, 11}, {53, 11}, {37, 9},  {32, 8},  {19, 7},
+				{18, 6},  {16, 4},  {17, 5},  {20, 5},  {21, 7},  {31, 7},  {22, 6},  {25, 5},  {24, 4},  {23, 3},
+				{26, 5},  {27, 5},  {28, 5},  {29, 6},  {30, 6},  {33, 8},  {34, 8},  {35, 7},  {36, 8},  {41, 8},
+				{40, 7},  {39, 5},  {42, 8},  {44, 10}, {60, 10}, {45, 9},  {43, 7},  {46, 9},  {59, 9},  {61, 10},
+				{64, 14}, {67, 14}, {68, 14}, {69, 14}, {70, 14}, {72, 14}, {75, 14}, {76, 14}, {66, 11}, {62, 9},
+				{48, 7},  {52, 7},  {57, 7},  {65, 8},  {71, 9},  {74, 9},  {73, 7},
+			},
+			{
+				/* AC highquant table group 1, table 6 */
+				{0, 3},   {1, 4},   {2, 4},   {3, 5},   {4, 5},   {5, 5},   {6, 5},   {7, 6},   {8, 7},   {10, 7},
+				{9, 5},   {11, 13}, {13, 13}, {15, 13}, {29, 13}, {32, 13}, {33, 13}, {34, 12}, {37, 12}, {38, 12},
+				{40, 12}, {41, 12}, {42, 12}, {43, 12}, {44, 12}, {45, 12}, {50, 12}, {53, 12}, {54, 12}, {55, 12},
+				{56, 12}, {58, 12}, {60, 12}, {61, 12}, {62, 12}, {63, 12}, {64, 12}, {66, 12}, {67, 12}, {68, 12},
+				{69, 12}, {70, 12}, {71, 12}, {72, 12}, {74, 12}, {76, 12}, {12, 7},  {14, 7},  {18, 7},  {17, 6},
+				{19, 7},  {21, 7},  {16, 4},  {20, 5},  {22, 5},  {23, 6},  {24, 6},  {25, 7},  {27, 7},  {26, 6},
+				{28, 7},  {30, 7},  {31, 7},  {35, 7},  {36, 7},  {39, 7},  {47, 6},  {46, 5},  {49, 5},  {48, 4},
+				{51, 7},  {75, 7},  {57, 6},  {52, 5},  {59, 6},  {65, 6},  {73, 5},
+			},
+			{
+				/* AC highquant table group 1, table 7 */
+				{0, 3},   {1, 4},   {2, 5},   {3, 6},   {4, 6},   {5, 8},   {6, 8},   {7, 8},   {8, 11},  {9, 15},
+				{10, 15}, {11, 15}, {12, 15}, {13, 15}, {14, 15}, {15, 15}, {38, 15}, {46, 15}, {47, 15}, {50, 15},
+				{51, 15}, {53, 15}, {54, 15}, {55, 15}, {56, 15}, {37, 11}, {58, 15}, {61, 15}, {62, 15}, {63, 15},
+				{64, 15}, {66, 15}, {67, 15}, {68, 15}, {69, 15}, {70, 15}, {72, 14}, {75, 14}, {76, 14}, {19, 9},
+				{17, 6},  {18, 7},  {21, 8},  {22, 8},  {28, 6},  {16, 4},  {20, 5},  {25, 5},  {26, 5},  {27, 5},
+				{23, 2},  {24, 3},  {29, 6},  {30, 8},  {31, 8},  {32, 9},  {36, 9},  {33, 8},  {34, 7},  {35, 8},
+				{41, 8},  {40, 7},  {42, 9},  {44, 9},  {43, 8},  {39, 5},  {45, 9},  {49, 10}, {71, 10}, {48, 8},
+				{52, 8},  {57, 9},  {60, 9},  {59, 8},  {65, 9},  {74, 9},  {73, 7},
+			},
+		},
+	},
+	{
+		{
+			{
+				/* AC lowquant table group 0, table 0 */
+				{0, 2},   {1, 3},   {2, 4},   {3, 5},   {4, 6},   {5, 7},   {6, 7},   {7, 7},   {8, 9},   {12, 10},
+				{13, 10}, {9, 8},   {10, 8},  {11, 8},  {14, 10}, {15, 10}, {18, 9},  {19, 10}, {41, 10}, {40, 9},
+				{17, 7},  {21, 7},  {20, 6},  {16, 4},  {22, 7},  {32, 7},  {28, 6},  {25, 5},  {23, 4},  {24, 4},
+				{26, 5},  {27, 5},  {29, 6},  {30, 6},  {31, 6},  {33, 7},  {34, 7},  {35, 7},  {36, 7},  {37, 7},
+				{38, 7},  {39, 8},  {42, 14}, {43, 14}, {44, 14}, {45, 14}, {47, 14}, {49, 14}, {50, 14}, {51, 14},
+				{53, 14}, {54, 14}, {55, 14}, {56, 14}, {58, 14}, {63, 14}, {64, 14}, {65, 14}, {46, 10}, {48, 9},
+				{52, 8},  {57, 10}, {66, 14}, {67, 14}, {68, 14}, {69, 14}, {70, 14}, {71, 14}, {72, 13}, {73, 13},
+				{74, 13}, {75, 13}, {76, 13}, {62, 9},  {59, 7},  {60, 8},  {61, 8},
+			},
+			{
+				/* AC lowquant table group 0, table 1 */
+				{0, 3},   {1, 5},   {2, 7},   {5, 8},   {6, 8},   {3, 6},   {4, 6},   {7, 8},   {8, 14},  {9, 14},
+				{11, 14}, {12, 14}, {13, 14}, {14, 14}, {15, 14}, {18, 14}, {20, 14}, {21, 14}, {22, 14}, {41, 14},
+				{45, 14}, {46, 14}, {47, 14}, {49, 14}, {50, 14}, {51, 14}, {52, 13}, {53, 13}, {54, 13}, {55, 13},
+				{56, 13}, {57, 13}, {58, 13}, {60, 13}, {61, 13}, {62, 13}, {63, 13}, {64, 13}, {66, 13}, {67, 13},
+				{68, 13}, {69, 13}, {70, 13}, {71, 13}, {72, 13}, {73, 13}, {74, 13}, {75, 13}, {76, 13}, {10, 7},
+				{16, 6},  {17, 8},  {19, 8},  {30, 7},  {23, 2},  {24, 3},  {25, 5},  {29, 6},  {31, 7},  {32, 7},
+				{26, 4},  {27, 4},  {28, 4},  {33, 7},  {34, 8},  {40, 8},  {35, 7},  {42, 8},  {43, 8},  {36, 6},
+				{37, 6},  {38, 6},  {39, 6},  {44, 8},  {48, 8},  {65, 7},  {59, 6},
+			},
+			{
+				/* AC lowquant table group 0, table 2 */
+				{0, 2},   {1, 3},   {2, 3},   {3, 4},   {4, 5},   {5, 5},   {6, 6},   {7, 6},   {8, 7},   {9, 7},
+				{10, 7},  {11, 8},  {12, 8},  {13, 8},  {14, 9},  {15, 10}, {39, 16}, {40, 16}, {41, 15}, {43, 15},
+				{44, 15}, {45, 15}, {50, 15}, {51, 15}, {53, 15}, {42, 12}, {49, 12}, {54, 15}, {55, 15}, {56, 15},
+				{58, 15}, {64, 15}, {65, 15}, {66, 15}, {67, 15}, {18, 8},  {19, 9},  {21, 9},  {17, 6},  {20, 6},
+				{22, 8},  {38, 8},  {27, 7},  {16, 4},  {23, 5},  {24, 6},  {25, 6},  {26, 6},  {28, 7},  {29, 7},
+				{30, 7},  {31, 7},  {32, 7},  {33, 7},  {34, 7},  {35, 7},  {36, 7},  {37, 7},  {46, 8},  {47, 10},
+				{62, 11}, {63, 12}, {68, 15}, {69, 15}, {70, 15}, {71, 15}, {72, 15}, {74, 15}, {75, 15}, {76, 15},
+				{48, 9},  {52, 8},  {57, 9},  {73, 9},  {59, 7},  {60, 8},  {61, 8},
+			},
+			{
+				/* AC lowquant table group 0, table 3 */
+				{0, 2},   {1, 3},   {2, 4},   {3, 5},   {4, 5},   {5, 6},   {6, 6},   {7, 7},   {8, 7},   {9, 8},
+				{10, 8},  {11, 9},  {12, 9},  {13, 9},  {14, 10}, {15, 10}, {17, 5},  {18, 7},  {19, 7},  {21, 7},
+				{24, 7},  {16, 3},  {20, 4},  {22, 5},  {23, 6},  {25, 7},  {26, 7},  {27, 8},  {28, 8},  {29, 8},
+				{30, 8},  {31, 8},  {32, 8},  {33, 9},  {37, 9},  {34, 8},  {35, 8},  {36, 8},  {38, 11}, {40, 11},
+				{39, 10}, {41, 15}, {43, 15}, {44, 15}, {45, 15}, {50, 15}, {51, 15}, {64, 15}, {66, 15}, {49, 12},
+				{47, 11}, {42, 10}, {46, 9},  {55, 10}, {56, 11}, {63, 12}, {67, 15}, {68, 15}, {69, 15}, {70, 15},
+				{71, 15}, {72, 15}, {74, 14}, {48, 7},  {53, 7},  {52, 5},  {54, 8},  {58, 10}, {61, 10}, {62, 10},
+				{65, 11}, {75, 12}, {76, 12}, {57, 7},  {59, 8},  {60, 8},  {73, 7},
+			},
+			{
+				/* AC lowquant table group 0, table 4 */
+				{0, 3},   {1, 4},   {2, 4},   {3, 5},   {4, 6},   {5, 6},   {6, 6},   {7, 7},   {9, 7},   {8, 6},
+				{10, 8},  {11, 8},  {12, 8},  {13, 9},  {14, 9},  {15, 8},  {37, 8},  {31, 7},  {18, 6},  {17, 5},
+				{16, 4},  {19, 6},  {21, 6},  {22, 5},  {20, 4},  {23, 5},  {24, 6},  {25, 6},  {26, 6},  {27, 6},
+				{28, 6},  {29, 6},  {30, 6},  {32, 7},  {33, 7},  {34, 7},  {35, 7},  {36, 7},  {38, 11}, {50, 15},
+				{51, 15}, {55, 15}, {56, 15}, {64, 15}, {69, 15}, {70, 14}, {71, 14}, {72, 14}, {75, 14}, {76, 14},
+				{45, 10}, {42, 9},  {41, 8},  {39, 7},  {40, 7},  {43, 9},  {44, 9},  {46, 9},  {47, 10}, {58, 10},
+				{49, 8},  {54, 9},  {62, 10}, {66, 10}, {48, 6},  {53, 7},  {59, 7},  {52, 4},  {57, 6},  {60, 8},
+				{61, 8},  {63, 9},  {65, 9},  {67, 10}, {68, 10}, {74, 9},  {73, 5},
+			},
+			{
+				/* AC lowquant table group 0, table 5 */
+				{0, 2},   {1, 4},   {2, 5},   {3, 5},   {4, 6},   {5, 6},   {6, 7},   {7, 8},   {8, 8},   {9, 8},
+				{10, 9},  {11, 11}, {14, 11}, {13, 10}, {12, 8},  {15, 15}, {42, 15}, {50, 15}, {51, 15}, {62, 15},
+				{64, 15}, {67, 15}, {68, 15}, {69, 14}, {70, 14}, {71, 14}, {72, 14}, {38, 11}, {40, 10}, {33, 9},
+				{17, 5},  {18, 6},  {19, 7},  {24, 7},  {16, 3},  {20, 4},  {21, 6},  {23, 6},  {22, 5},  {25, 8},
+				{27, 8},  {26, 7},  {28, 7},  {29, 8},  {31, 8},  {30, 7},  {32, 8},  {34, 9},  {35, 9},  {36, 9},
+				{37, 9},  {39, 9},  {41, 11}, {44, 11}, {43, 10}, {45, 11}, {47, 11}, {46, 10}, {56, 9},  {49, 8},
+				{48, 6},  {54, 7},  {55, 7},  {53, 5},  {52, 4},  {57, 6},  {58, 8},  {59, 8},  {60, 10}, {61, 11},
+				{75, 11}, {63, 10}, {65, 10}, {66, 10}, {74, 10}, {76, 9},  {73, 5},
+			},
+			{
+				/* AC lowquant table group 0, table 6 */
+				{0, 2},   {1, 4},   {2, 5},   {3, 6},   {4, 6},   {5, 8},   {6, 9},   {7, 10},  {8, 10},  {9, 9},
+				{10, 15}, {11, 15}, {13, 15}, {15, 15}, {37, 15}, {46, 15}, {47, 15}, {49, 15}, {50, 15}, {51, 15},
+				{53, 15}, {54, 15}, {55, 15}, {56, 15}, {58, 15}, {60, 15}, {61, 15}, {62, 15}, {63, 15}, {64, 15},
+				{67, 15}, {68, 15}, {69, 15}, {70, 15}, {71, 15}, {72, 15}, {74, 14}, {75, 14}, {76, 14}, {12, 10},
+				{14, 10}, {36, 10}, {21, 9},  {18, 8},  {19, 8},  {22, 8},  {32, 8},  {17, 5},  {16, 4},  {20, 5},
+				{26, 5},  {25, 4},  {23, 3},  {24, 3},  {27, 6},  {28, 6},  {29, 7},  {30, 7},  {31, 7},  {33, 8},
+				{34, 9},  {38, 9},  {35, 8},  {41, 9},  {42, 10}, {45, 10}, {43, 8},  {44, 8},  {39, 6},  {40, 6},
+				{48, 9},  {57, 9},  {52, 8},  {59, 9},  {65, 10}, {66, 10}, {73, 8},
+			},
+			{
+				/* AC lowquant table group 0, table 7 */
+				{0, 4},   {1, 11},  {2, 11},  {3, 11},  {4, 11},  {5, 11},  {6, 11},  {7, 11},  {8, 11},  {9, 11},
+				{10, 11}, {11, 11}, {12, 11}, {13, 11}, {14, 11}, {15, 11}, {16, 11}, {17, 10}, {18, 10}, {19, 10},
+				{20, 10}, {21, 10}, {22, 10}, {25, 10}, {28, 10}, {29, 10}, {30, 10}, {31, 10}, {32, 10}, {33, 10},
+				{34, 10}, {35, 10}, {36, 10}, {37, 10}, {38, 10}, {39, 10}, {40, 10}, {41, 10}, {42, 10}, {43, 10},
+				{44, 10}, {45, 10}, {46, 10}, {47, 10}, {48, 10}, {49, 10}, {50, 10}, {51, 10}, {52, 10}, {53, 10},
+				{54, 10}, {55, 10}, {56, 10}, {57, 10}, {58, 10}, {59, 10}, {60, 10}, {61, 10}, {62, 10}, {63, 10},
+				{64, 10}, {65, 10}, {66, 10}, {67, 10}, {68, 10}, {69, 10}, {70, 10}, {71, 10}, {72, 10}, {73, 10},
+				{74, 10}, {75, 10}, {76, 10}, {26, 4},  {27, 4},  {24, 2},  {23, 1},
+			},
+		},
+		{
+			{
+				/* AC lowquant table group 1, table 0 */
+				{0, 3},   {1, 4},   {2, 4},   {3, 5},   {4, 6},   {5, 7},   {7, 8},   {8, 8},   {6, 6},   {9, 9},
+				{10, 10}, {14, 15}, {47, 15}, {49, 14}, {50, 14}, {51, 14}, {54, 14}, {55, 14}, {56, 14}, {58, 14},
+				{15, 11}, {11, 9},  {12, 9},  {13, 9},  {37, 9},  {32, 8},  {17, 5},  {16, 4},  {18, 6},  {19, 7},
+				{21, 7},  {20, 5},  {22, 5},  {25, 5},  {24, 4},  {23, 3},  {26, 5},  {27, 5},  {28, 5},  {29, 6},
+				{30, 6},  {31, 7},  {33, 8},  {34, 8},  {35, 8},  {36, 8},  {38, 10}, {44, 11}, {46, 11}, {45, 10},
+				{53, 10}, {41, 8},  {39, 6},  {40, 7},  {42, 8},  {43, 8},  {48, 7},  {57, 7},  {52, 6},  {59, 8},
+				{60, 9},  {61, 11}, {63, 11}, {62, 10}, {64, 14}, {67, 14}, {68, 14}, {69, 14}, {70, 14}, {71, 14},
+				{72, 14}, {76, 14}, {75, 11}, {66, 10}, {74, 9},  {65, 8},  {73, 6},
+			},
+			{
+				/* AC lowquant table group 1, table 1 */
+				{0, 2},   {1, 3},   {2, 4},   {3, 5},   {4, 6},   {5, 6},   {6, 7},   {7, 8},   {8, 8},   {9, 8},
+				{10, 9},  {11, 9},  {12, 11}, {13, 11}, {14, 11}, {15, 11}, {24, 9},  {23, 8},  {17, 5},  {18, 6},
+				{19, 7},  {25, 10}, {27, 10}, {26, 9},  {28, 10}, {29, 12}, {35, 12}, {34, 11}, {30, 10}, {31, 10},
+				{21, 6},  {32, 10}, {33, 10}, {36, 10}, {37, 12}, {38, 12}, {39, 15}, {40, 15}, {41, 15}, {42, 15},
+				{43, 14}, {44, 14}, {45, 14}, {51, 14}, {61, 14}, {64, 14}, {46, 11}, {47, 11}, {49, 10}, {50, 12},
+				{63, 12}, {59, 11}, {56, 10}, {48, 8},  {55, 8},  {16, 3},  {20, 4},  {22, 4},  {52, 4},  {53, 6},
+				{54, 7},  {58, 8},  {60, 10}, {62, 11}, {65, 14}, {66, 14}, {67, 14}, {68, 14}, {69, 14}, {70, 14},
+				{71, 14}, {72, 14}, {74, 11}, {75, 11}, {76, 10}, {57, 6},  {73, 6},
+			},
+			{
+				/* AC lowquant table group 1, table 2 */
+				{0, 3},   {1, 4},   {2, 5},   {3, 6},   {4, 7},   {5, 8},   {6, 8},   {7, 8},   {8, 10},  {10, 10},
+				{9, 9},   {11, 10}, {12, 16}, {15, 16}, {38, 16}, {44, 16}, {46, 15}, {47, 15}, {50, 15}, {51, 15},
+				{59, 15}, {60, 15}, {61, 15}, {62, 15}, {64, 15}, {68, 15}, {69, 15}, {70, 15}, {71, 15}, {72, 15},
+				{37, 11}, {13, 10}, {14, 10}, {19, 8},  {18, 6},  {17, 5},  {21, 5},  {23, 7},  {24, 9},  {25, 9},
+				{26, 9},  {27, 9},  {28, 9},  {29, 10}, {30, 10}, {31, 10}, {32, 10}, {33, 10}, {34, 10}, {35, 9},
+				{36, 10}, {39, 10}, {40, 11}, {42, 11}, {41, 10}, {43, 10}, {45, 11}, {63, 11}, {16, 3},  {20, 3},
+				{22, 4},  {48, 7},  {49, 9},  {65, 11}, {66, 11}, {67, 11}, {74, 11}, {56, 8},  {54, 6},  {55, 6},
+				{58, 7},  {75, 8},  {76, 8},  {52, 3},  {53, 4},  {57, 5},  {73, 5},
+			},
+			{
+				/* AC lowquant table group 1, table 3 */
+				{0, 2},   {1, 3},   {2, 4},   {3, 4},   {4, 5},   {5, 5},   {6, 6},   {7, 6},   {8, 6},   {9, 6},
+				{10, 7},  {11, 7},  {12, 8},  {13, 8},  {14, 8},  {15, 9},  {19, 9},  {17, 6},  {18, 7},  {21, 8},
+				{36, 8},  {16, 4},  {20, 6},  {22, 7},  {28, 7},  {23, 6},  {24, 6},  {25, 6},  {26, 6},  {27, 6},
+				{29, 7},  {30, 7},  {31, 7},  {32, 7},  {33, 7},  {34, 7},  {35, 7},  {37, 8},  {38, 9},  {39, 11},
+				{41, 15}, {42, 15}, {43, 15}, {44, 15}, {45, 15}, {51, 15}, {54, 15}, {55, 15}, {49, 12}, {40, 10},
+				{46, 7},  {47, 8},  {48, 8},  {50, 9},  {53, 9},  {56, 15}, {67, 15}, {68, 15}, {69, 15}, {70, 14},
+				{71, 14}, {72, 14}, {74, 14}, {75, 14}, {76, 14}, {58, 11}, {65, 11}, {66, 11}, {64, 9},  {52, 7},
+				{57, 8},  {61, 8},  {60, 7},  {59, 6},  {62, 8},  {73, 8},  {63, 7},
+			},
+			{
+				/* AC lowquant table group 1, table 4 */
+				{0, 2},   {1, 4},   {2, 5},   {3, 6},   {4, 6},   {5, 7},   {6, 7},   {7, 8},   {8, 8},   {9, 8},
+				{10, 9},  {11, 9},  {12, 10}, {13, 10}, {14, 14}, {69, 14}, {70, 14}, {72, 14}, {15, 12}, {44, 11},
+				{37, 10}, {29, 8},  {19, 7},  {18, 6},  {17, 5},  {21, 6},  {24, 6},  {16, 3},  {20, 4},  {22, 5},
+				{23, 5},  {25, 6},  {26, 6},  {27, 7},  {28, 7},  {30, 7},  {31, 8},  {32, 8},  {33, 8},  {34, 8},
+				{35, 8},  {36, 9},  {38, 10}, {43, 10}, {39, 7},  {40, 8},  {41, 9},  {42, 9},  {45, 9},  {46, 9},
+				{47, 10}, {50, 12}, {51, 12}, {62, 11}, {56, 9},  {48, 7},  {49, 8},  {54, 8},  {55, 8},  {58, 8},
+				{52, 4},  {53, 6},  {57, 6},  {59, 9},  {60, 10}, {61, 10}, {63, 10}, {64, 11}, {67, 11}, {65, 9},
+				{66, 9},  {68, 11}, {71, 11}, {76, 10}, {74, 9},  {75, 9},  {73, 6},
+			},
+			{
+				/* AC lowquant table group 1, table 5 */
+				{0, 2},   {1, 3},   {2, 4},   {3, 5},   {4, 5},   {5, 6},   {6, 6},   {7, 7},   {8, 7},   {9, 7},
+				{10, 8},  {11, 8},  {12, 8},  {13, 9},  {14, 10}, {39, 11}, {40, 12}, {41, 12}, {15, 9},  {37, 9},
+				{19, 8},  {18, 7},  {21, 7},  {17, 5},  {16, 3},  {20, 5},  {22, 6},  {24, 6},  {23, 5},  {25, 7},
+				{26, 7},  {27, 7},  {28, 8},  {29, 8},  {30, 7},  {31, 8},  {32, 8},  {33, 8},  {34, 8},  {35, 8},
+				{36, 8},  {38, 9},  {42, 15}, {44, 15}, {45, 15}, {56, 15}, {43, 13}, {51, 13}, {66, 13}, {58, 11},
+				{49, 10}, {46, 8},  {47, 9},  {50, 9},  {48, 8},  {53, 7},  {54, 9},  {55, 9},  {59, 8},  {52, 5},
+				{57, 7},  {60, 8},  {61, 8},  {62, 9},  {64, 11}, {65, 12}, {67, 15}, {68, 15}, {69, 15}, {70, 15},
+				{71, 15}, {72, 15}, {74, 14}, {75, 11}, {76, 11}, {63, 8},  {73, 7},
+			},
+			{
+				/* AC lowquant table group 1, table 6 */
+				{0, 3},   {1, 4},   {2, 4},   {3, 5},   {4, 5},   {5, 6},   {6, 6},   {7, 7},   {8, 8},   {9, 8},
+				{10, 8},  {11, 9},  {12, 9},  {13, 9},  {14, 11}, {15, 12}, {45, 12}, {38, 10}, {33, 8},  {16, 3},
+				{17, 5},  {18, 6},  {19, 7},  {27, 7},  {20, 4},  {21, 6},  {25, 6},  {22, 5},  {23, 4},  {24, 5},
+				{26, 6},  {28, 7},  {29, 7},  {30, 7},  {31, 7},  {32, 7},  {34, 8},  {35, 8},  {36, 9},  {41, 9},
+				{37, 8},  {39, 7},  {40, 8},  {42, 11}, {47, 15}, {50, 15}, {51, 15}, {56, 15}, {64, 15}, {67, 15},
+				{68, 15}, {69, 15}, {70, 14}, {71, 14}, {72, 14}, {76, 14}, {44, 10}, {43, 9},  {46, 9},  {54, 9},
+				{55, 11}, {63, 11}, {61, 10}, {58, 9},  {48, 6},  {49, 7},  {53, 7},  {52, 5},  {57, 6},  {59, 8},
+				{60, 9},  {62, 10}, {74, 10}, {65, 8},  {66, 9},  {75, 9},  {73, 5},
+			},
+			{
+				/* AC lowquant table group 1, table 7 */
+				{0, 2},   {1, 4},   {2, 5},   {3, 6},   {4, 7},   {5, 7},   {6, 8},   {7, 8},   {8, 9},   {9, 9},
+				{10, 9},  {11, 10}, {12, 15}, {13, 15}, {14, 15}, {15, 15}, {32, 15}, {36, 15}, {38, 15}, {41, 15},
+				{42, 15}, {45, 15}, {47, 15}, {50, 15}, {51, 15}, {61, 15}, {62, 14}, {34, 11}, {18, 6},  {17, 5},
+				{19, 7},  {23, 8},  {24, 8},  {21, 6},  {25, 9},  {26, 10}, {28, 10}, {27, 9},  {29, 9},  {30, 10},
+				{31, 10}, {33, 10}, {35, 11}, {40, 11}, {37, 10}, {43, 11}, {44, 11}, {39, 9},  {46, 11}, {60, 11},
+				{49, 10}, {56, 9},  {59, 9},  {63, 14}, {64, 14}, {67, 14}, {68, 14}, {69, 14}, {70, 14}, {71, 14},
+				{72, 14}, {74, 11}, {76, 10}, {48, 7},  {16, 3},  {20, 4},  {22, 4},  {52, 3},  {53, 5},  {54, 7},
+				{55, 7},  {58, 7},  {65, 9},  {66, 9},  {75, 8},  {57, 5},  {73, 5},
+			},
+		},
+	},
+};
+#define MAX_AC_VLC_BITS 16
+
+#define W0 2048
+#define W1 2841 /* 2048*sqrt (2)*cos (1*pi/16) */
+#define W2 2676 /* 2048*sqrt (2)*cos (2*pi/16) */
+#define W3 2408 /* 2048*sqrt (2)*cos (3*pi/16) */
+#define W4 2048 /* 2048*sqrt (2)*cos (4*pi/16) */
+#define W5 1609 /* 2048*sqrt (2)*cos (5*pi/16) */
+#define W6 1108 /* 2048*sqrt (2)*cos (6*pi/16) */
+#define W7 565  /* 2048*sqrt (2)*cos (7*pi/16) */
+
+static void wmv2_idct_row(short *b) {
+	int s1, s2;
+	int a0, a1, a2, a3, a4, a5, a6, a7;
+
+	/* step 1 */
+	a1 = W1 * b[1] + W7 * b[7];
+	a7 = W7 * b[1] - W1 * b[7];
+	a5 = W5 * b[5] + W3 * b[3];
+	a3 = W3 * b[5] - W5 * b[3];
+	a2 = W2 * b[2] + W6 * b[6];
+	a6 = W6 * b[2] - W2 * b[6];
+	a0 = W0 * b[0] + W0 * b[4];
+	a4 = W0 * b[0] - W0 * b[4];
+
+	/* step 2 */
+	s1 = (int)(181U * (a1 - a5 + a7 - a3) + 128) >> 8; // 1, 3, 5, 7
+	s2 = (int)(181U * (a1 - a5 - a7 + a3) + 128) >> 8;
+
+	/* step 3 */
+	b[0] = (a0 + a2 + a1 + a5 + (1 << 7)) >> 8;
+	b[1] = (a4 + a6 + s1 + (1 << 7)) >> 8;
+	b[2] = (a4 - a6 + s2 + (1 << 7)) >> 8;
+	b[3] = (a0 - a2 + a7 + a3 + (1 << 7)) >> 8;
+	b[4] = (a0 - a2 - a7 - a3 + (1 << 7)) >> 8;
+	b[5] = (a4 - a6 - s2 + (1 << 7)) >> 8;
+	b[6] = (a4 + a6 - s1 + (1 << 7)) >> 8;
+	b[7] = (a0 + a2 - a1 - a5 + (1 << 7)) >> 8;
+}
+
+static void wmv2_idct_col(short *b) {
+	int s1, s2;
+	int a0, a1, a2, a3, a4, a5, a6, a7;
+
+	/* step 1, with extended precision */
+	a1 = (W1 * b[8 * 1] + W7 * b[8 * 7] + 4) >> 3;
+	a7 = (W7 * b[8 * 1] - W1 * b[8 * 7] + 4) >> 3;
+	a5 = (W5 * b[8 * 5] + W3 * b[8 * 3] + 4) >> 3;
+	a3 = (W3 * b[8 * 5] - W5 * b[8 * 3] + 4) >> 3;
+	a2 = (W2 * b[8 * 2] + W6 * b[8 * 6] + 4) >> 3;
+	a6 = (W6 * b[8 * 2] - W2 * b[8 * 6] + 4) >> 3;
+	a0 = (W0 * b[8 * 0] + W0 * b[8 * 4]) >> 3;
+	a4 = (W0 * b[8 * 0] - W0 * b[8 * 4]) >> 3;
+
+	/* step 2 */
+	s1 = (int)(181U * (a1 - a5 + a7 - a3) + 128) >> 8;
+	s2 = (int)(181U * (a1 - a5 - a7 + a3) + 128) >> 8;
+
+	/* step 3 */
+	b[8 * 0] = (a0 + a2 + a1 + a5 + (1 << 13)) >> 14;
+	b[8 * 1] = (a4 + a6 + s1 + (1 << 13)) >> 14;
+	b[8 * 2] = (a4 - a6 + s2 + (1 << 13)) >> 14;
+	b[8 * 3] = (a0 - a2 + a7 + a3 + (1 << 13)) >> 14;
+
+	b[8 * 4] = (a0 - a2 - a7 - a3 + (1 << 13)) >> 14;
+	b[8 * 5] = (a4 - a6 - s2 + (1 << 13)) >> 14;
+	b[8 * 6] = (a4 + a6 - s1 + (1 << 13)) >> 14;
+	b[8 * 7] = (a0 + a2 - a1 - a5 + (1 << 13)) >> 14;
+}
+
+static void wmv2_idct_add_c(uint8 *dest, ptrdiff_t line_size, int16 *block) {
+	int i;
+
+	for (i = 0; i < 64; i += 8)
+		wmv2_idct_row(block + i);
+	for (i = 0; i < 8; i++)
+		wmv2_idct_col(block + i);
+
+	for (i = 0; i < 8; i++) {
+		dest[0] = av_clip_uint8(dest[0] + block[0]);
+		dest[1] = av_clip_uint8(dest[1] + block[1]);
+		dest[2] = av_clip_uint8(dest[2] + block[2]);
+		dest[3] = av_clip_uint8(dest[3] + block[3]);
+		dest[4] = av_clip_uint8(dest[4] + block[4]);
+		dest[5] = av_clip_uint8(dest[5] + block[5]);
+		dest[6] = av_clip_uint8(dest[6] + block[6]);
+		dest[7] = av_clip_uint8(dest[7] + block[7]);
+		dest += line_size;
+		block += 8;
+	}
+}
+
+static const VLC *makeCanonicalVLC(int count, const uint8 table[][2]) {
+	uint32 codes[256], lengths[256];
+	uint64 code = 0;
+	for (int i = 0; i < count; ++i) {
+		int n = table[i][1];
+		codes[i] = code >> (32 - n);
+		lengths[i] = n;
+		code += uint64(1) << (32 - n);
+	}
+	VLC *v = const_cast<VLC *>(makeVLC(count, lengths, 4, 4, codes, 4, 4));
+	for (uint i = 0; i < v->nodes.size(); ++i)
+		if (v->nodes[i].symbol >= 0)
+			v->nodes[i].symbol = table[v->nodes[i].symbol][0];
+	return v;
+}
+#define VLC_BUFFER_SIZE 28150
+
+#define MAX_TABLE_DEPTH(table_bits, max_bits) ((max_bits + table_bits - 1) / table_bits)
+
+#define DC_VLC_BITS 9
+#define OR_VLC_BITS 7
+
+#define DC_VLC_MTD MAX_TABLE_DEPTH(DC_VLC_BITS, MAX_DC_VLC_BITS)
+#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 const VLC *j_ac_vlc[2][2][8];  // [quant < 13], [intra / inter], [select]
+static const VLC *j_dc_vlc[2][8];     // [quant], [select]
+static const VLC *j_orient_vlc[2][4]; // [quant], [select]
+
+static const VLC *x8_init_vlc(int nb_bits, int nb_codes, const uint8 table[][2]) {
+	return makeCanonicalVLC(nb_codes, table);
+}
+
+static void x8_vlc_init(void) {
+
+	int i;
+
+	// set ac tables
+	for (int i = 0; i < 2; i++)
+		for (int j = 0; j < 2; j++)
+			for (int k = 0; k < 8; k++)
+				j_ac_vlc[i][j][k] = x8_init_vlc(AC_VLC_BITS, 77, x8_ac_quant_table[i][j][k]);
+
+	// set dc tables
+	for (int i = 0; i < 2; i++)
+		for (int j = 0; j < 8; j++)
+			j_dc_vlc[i][j] = x8_init_vlc(DC_VLC_BITS, 34, x8_dc_quant_table[i][j]);
+
+	// set orient tables
+	for (i = 0; i < 2; i++)
+		j_orient_vlc[0][i] = x8_init_vlc(OR_VLC_BITS, 12, x8_orient_highquant_table[i]);
+	for (i = 0; i < 4; i++)
+		j_orient_vlc[1][i] = x8_init_vlc(OR_VLC_BITS, 12, x8_orient_lowquant_table[i]);
+}
+
+static void x8_reset_vlc_tables(IntraX8Context *w) {
+	memset(w->j_dc_vlc_table, 0, sizeof(w->j_dc_vlc_table));
+	memset(w->j_ac_vlc_table, 0, sizeof(w->j_ac_vlc_table));
+	w->j_orient_vlc_table = NULL;
+}
+
+static inline void x8_select_ac_table(IntraX8Context *const w, int mode) {
+	int table_index;
+
+	assert(mode < 4);
+
+	if (w->j_ac_vlc_table[mode])
+		return;
+
+	table_index = get_bits(w->gb, 3);
+	// 2 modes use same tables
+	w->j_ac_vlc_table[mode] = j_ac_vlc[w->quant < 13][mode >> 1][table_index];
+	assert(w->j_ac_vlc_table[mode]);
+}
+
+static inline int x8_get_orient_vlc(IntraX8Context *w) {
+	if (!w->j_orient_vlc_table) {
+		int table_index = get_bits(w->gb, 1 + (w->quant < 13));
+		w->j_orient_vlc_table = j_orient_vlc[w->quant < 13][table_index];
+	}
+
+	return get_vlc2(w->gb, w->j_orient_vlc_table);
+}
+
+#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 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),
+};
+#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) {
+	int i, e;
+
+	//    x8_select_ac_table(w, mode);
+	i = get_vlc2(w->gb, w->j_ac_vlc_table[mode]);
+
+	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;
+		}
+
+		/*
+		 * 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 sm;
+		uint32 mask;
+
+		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 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 dc_extra_sbits[] = {
+ *     0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
+ * }; */
+static const uint8 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, const int mode, int *const level, int *const final) {
+	int i, e, c;
+
+	assert(mode < 3);
+	if (!w->j_dc_vlc_table[mode]) {
+		int table_index = get_bits(w->gb, 3);
+		// 4 modes, same table
+		w->j_dc_vlc_table[mode] = j_dc_vlc[w->quant < 13][table_index];
+	}
+
+	i = get_vlc2(w->gb, w->j_dc_vlc_table[mode]);
+
+	/* (i >= 17) { i -= 17; final =1; } */
+	c = i > 16;
+	*final = c;
+	i -= 17 * c;
+
+	if (i <= 0) {
+		*level = 0;
+		return -i;
+	}
+	c = (i + 1) >> 1; // hackish way to calculate dc_extra_sbits[]
+	c -= c > 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)
+	return 0;
+}
+
+// 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(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;
+	}
+
+	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)
+		return 0;
+
+	assert(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;
+		}
+		w->raw_orient = 0;
+	} else {
+		static const uint8 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;
+		assert(w->raw_orient < 12);
+		assert(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) {
+	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
+	 */
+}
+
+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;
+	}
+	// 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) {
+	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 * 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 = MIN(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 ((w->mb_x & w->mb_y) != 0)
+		w->est_run = MIN(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
+	 */
+}
+
+static void x8_ac_compensation(IntraX8Context *const w, const int direction, const int dc_level) {
+	int t;
+#define B(x, y) w->block[(x) + (y) * 8]
+#define T(x) ((x) * dc_level + 0x8000) >> 16;
+	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;
+		break;
+	case 1:
+		B(0, 1) -= T(6269);
+		B(0, 3) -= T(708);
+		B(0, 5) -= T(172);
+		B(0, 7) -= T(73);
+		break;
+	case 2:
+		B(1, 0) -= T(6269);
+		B(3, 0) -= T(708);
+		B(5, 0) -= T(172);
+		B(7, 0) -= T(73);
+		break;
+	}
+#undef B
+#undef T
+}
+
+static void dsp_x8_put_solidcolor(const uint8 pix, uint8 *dst, const ptrdiff_t linesize) {
+	int k;
+	for (k = 0; k < 8; k++) {
+		memset(dst, pix, 8);
+		dst += linesize;
+	}
+}
+
+static const int16 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,
+};
+
+static int x8_decode_intra_mb(IntraX8Context *const w, const int chroma) {
+	uint8 *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;
+
+	assert(w->orient < 12);
+	w->bdsp.clear_block(w->block);
+
+	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)
+				use_quant_matrix = 0;
+
+			if (w->raw_orient > 4) {
+				ac_mode = 0;
+				est_run = 64;
+			} else {
+				if (w->est_run > 1) {
+					ac_mode = 2;
+					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->permutated_scantable[(0x928548 >> (2 * w->orient)) & 3];
+		pos = 0;
+		do {
+			n++;
+			if (n >= est_run) {
+				ac_mode = 3;
+				x8_select_ac_table(w, 3);
+			}
+
+			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
+				return -1;
+			}
+			level = (level + 1) * w->dquant;
+			level += w->qsum;
+
+			sign = -get_bits1(w->gb);
+			level = (level ^ sign) - sign;
+
+			if (use_quant_matrix)
+				level = (level * quant_table[pos]) >> 8;
+
+			w->block[scantable[pos]] = level;
+		} while (!final);
+	} else {                                                // DC only
+		if (w->flat_dc && ((unsigned)(dc_level + 1)) < 3) { // [-1; 1]
+			int32 divide_quant = !chroma ? w->divide_quant_dc_luma : w->divide_quant_dc_chroma;
+			int32 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;
+
+			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)
+		w->block[0] = dc_level * w->quant;
+	else
+		w->block[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) {
+		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, w->block[0]);
+		}
+	}
+
+	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->idsp.idct_add(w->dest[chroma], w->frame->linesize[!!chroma], w->block);
+
+block_placed:
+	if (!chroma)
+		x8_update_predictions(w, w->orient, n);
+
+	if (w->loopfilter) {
+		uint8 *ptr = w->dest[chroma];
+		ptrdiff_t linesize = w->frame->linesize[!!chroma];
+
+		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)))
+			w->dsp.v_loop_filter(ptr, linesize, w->quant);
+	}
+	return 0;
+}
+
+// FIXME maybe merge with ff_*
+static void x8_init_block_index(IntraX8Context *w, Planes *frame) {
+	// not parent codec linesize as this would be wrong for field pics
+	// not that IntraX8 has interlacing support ;)
+	const ptrdiff_t linesize = frame->linesize[0];
+	const ptrdiff_t 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;
+}
+
+int initX8(IntraX8Context *w, int16 block[64], int mb_width, int mb_height) {
+	w->mb_width = mb_width;
+	w->mb_height = mb_height;
+	w->block = block;
+	w->prediction_table = new uint8[mb_width * 4]();
+	w->idsp.idct_add = wmv2_idct_add_c;
+	memcpy(w->permutated_scantable[0], ff_wmv1_scantable[0], 64);
+	memcpy(w->permutated_scantable[1], ff_wmv1_scantable[2], 64);
+	memcpy(w->permutated_scantable[2], ff_wmv1_scantable[3], 64);
+	ff_intrax8dsp_init(&w->dsp);
+	PictureState state = {};
+	ChromaDSP chroma;
+	initSupport(&state, &chroma);
+	w->bdsp = state.bdsp;
+	static const bool initialized = (x8_vlc_init(), true);
+	(void)initialized;
+	return 0;
+}
+
+void endX8(IntraX8Context *w) {
+	delete[] w->prediction_table;
+}
+
+int ff_intrax8_decode_picture(IntraX8Context *w, Picture *pict, Bits *gb, int *mb_x, int *mb_y, int dquant,
+							  int quant_offset, int loopfilter, int lowdelay) {
+	int mb_xy;
+
+	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->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;
+	}
+	x8_reset_vlc_tables(w);
+
+	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);
+		if (get_bits_left(gb) < 1)
+			goto error;
+		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 (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;
+
+				x8_setup_spatial_predictor(w, 2);
+				if (x8_decode_intra_mb(w, 2))
+					goto error;
+
+				w->dest[1] += 8;
+				w->dest[2] += 8;
+
+				pict->qscale_table[mb_xy] = w->quant;
+				mb_xy++;
+			}
+			w->dest[0] += 8;
+		}
+	}
+
+error:
+	*mb_x = w->mb_x;
+	*mb_y = w->mb_y;
+
+	return 0;
+}
+
+#undef AC_VLC_MTD
+#undef DC_VLC_BITS
+#undef DC_VLC_MTD
+#undef MAX_AC_VLC_BITS
+#undef MAX_DC_VLC_BITS
+#undef MAX_OR_VLC_BITS
+#undef MAX_TABLE_DEPTH
+#undef OR_VLC_BITS
+#undef OR_VLC_MTD
+#undef VLC_BUFFER_SIZE
+#undef W0
+#undef W1
+#undef W2
+#undef W3
+#undef W4
+#undef W5
+#undef W6
+#undef W7
+
+static int bitplane_decoding(uint8 *data, int *raw, VC1Context *v) {
+	VC1Bitplane decoder;
+	int result =
+		decoder.decode(data, raw, v->s.mb_width, v->s.mb_height >> v->field_mode, v->s.mb_stride, v->gb.stream);
+	return result;
+}
+
+static int vop_dquant_decoding(VC1Context *v) {
+	Bits *const gb = &v->gb;
+	int pqdiff;
+
+	// variable size
+	if (v->dquant != 2) {
+		v->dquantfrm = get_bits1(gb);
+		if (!v->dquantfrm)
+			return 0;
+
+		v->dqprofile = get_bits(gb, 2);
+		switch (v->dqprofile) {
+		case DQPROFILE_SINGLE_EDGE:
+		case DQPROFILE_DOUBLE_EDGES:
+			v->dqsbedge = get_bits(gb, 2);
+			break;
+		case DQPROFILE_ALL_MBS:
+			v->dqbilevel = get_bits1(gb);
+			if (!v->dqbilevel) {
+				v->halfpq = 0;
+				return 0;
+			}
+			break;
+		default:
+			break; // Forbidden ?
+		}
+	}
+
+	pqdiff = get_bits(gb, 3);
+	if (pqdiff == 7)
+		v->altpq = get_bits(gb, 5);
+	else
+		v->altpq = v->pq + pqdiff + 1;
+
+	return 0;
+}
+
+/* fill lookup tables for intensity compensation */
+#define INIT_LUT(lumscale, lumshift, luty, lutuv, chain)                                                               \
+	do {                                                                                                               \
+		int scale, shift, i;                                                                                           \
+		if (!lumscale) {                                                                                               \
+			scale = -64;                                                                                               \
+			shift = (255 - lumshift * 2) * 64;                                                                         \
+			if (lumshift > 31)                                                                                         \
+				shift += 128 << 6;                                                                                     \
+		} else {                                                                                                       \
+			scale = lumscale + 32;                                                                                     \
+			if (lumshift > 31)                                                                                         \
+				shift = (lumshift - 64) * 64;                                                                          \
+			else                                                                                                       \
+				shift = lumshift << 6;                                                                                 \
+		}                                                                                                              \
+		for (i = 0; i < 256; i++) {                                                                                    \
+			int iy = chain ? luty[i] : i;                                                                              \
+			int iu = chain ? lutuv[i] : i;                                                                             \
+			luty[i] = av_clip_uint8((scale * iy + shift + 32) >> 6);                                                   \
+			lutuv[i] = av_clip_uint8((scale * (iu - 128) + 128 * 64 + 32) >> 6);                                       \
+		}                                                                                                              \
+	} while (0)
+
+static void rotate_luts(VC1Context *v) {
+	if (v->s.pict_type == AV_PICTURE_TYPE_BI || v->s.pict_type == AV_PICTURE_TYPE_B) {
+		v->curr_use_ic = &v->aux_use_ic;
+		v->curr_luty = v->aux_luty;
+		v->curr_lutuv = v->aux_lutuv;
+	} else {
+#define ROTATE(DEF, L, N, C)                                                                                           \
+	do {                                                                                                               \
+		DEF;                                                                                                           \
+		memcpy(&tmp, L, sizeof(tmp));                                                                                  \
+		memcpy(L, N, sizeof(tmp));                                                                                     \
+		memcpy(N, &tmp, sizeof(tmp));                                                                                  \
+		C = N;                                                                                                         \
+	} while (0)
+
+		ROTATE(int tmp, &v->last_use_ic, &v->next_use_ic, v->curr_use_ic);
+		ROTATE(uint8 tmp[2][256], v->last_luty, v->next_luty, v->curr_luty);
+		ROTATE(uint8 tmp[2][256], v->last_lutuv, v->next_lutuv, v->curr_lutuv);
+	}
+
+	INIT_LUT(32, 0, v->curr_luty[0], v->curr_lutuv[0], 0);
+	INIT_LUT(32, 0, v->curr_luty[1], v->curr_lutuv[1], 0);
+	*v->curr_use_ic = 0;
+}
+
+static int read_bfraction(VC1Context *v, Bits *gb) {
+	int bfraction_lut_index = get_bits(gb, 3);
+
+	if (bfraction_lut_index == 7)
+		bfraction_lut_index = 7 + get_bits(gb, 4);
+
+	if (bfraction_lut_index == 21) {
+		warning("bfraction invalid\n");
+		return (-1);
+	}
+	v->bfraction_lut_index = bfraction_lut_index;
+	v->bfraction = ff_vc1_bfraction_lut[v->bfraction_lut_index];
+	return 0;
+}
+
+int ff_vc1_parse_frame_header(VC1Context *v, Bits *gb) {
+	int pqindex, lowquant, status;
+
+	v->field_mode = 0;
+	v->fcm = PROGRESSIVE;
+	if (v->finterpflag)
+		v->interpfrm = get_bits1(gb);
+	skip_bits(gb, 2); // framecnt unused
+	v->rangeredfrm = 0;
+	if (v->rangered)
+		v->rangeredfrm = get_bits1(gb);
+	if (get_bits1(gb)) {
+		v->s.pict_type = AV_PICTURE_TYPE_P;
+	} else {
+		if (v->max_b_frames && !get_bits1(gb)) {
+			v->s.pict_type = AV_PICTURE_TYPE_B;
+		} else
+			v->s.pict_type = AV_PICTURE_TYPE_I;
+	}
+
+	v->bi_type = 0;
+	if (v->s.pict_type == AV_PICTURE_TYPE_B) {
+		if (read_bfraction(v, gb) < 0)
+			return (-1);
+		if (v->bfraction == 0) {
+			v->s.pict_type = AV_PICTURE_TYPE_BI;
+		}
+	}
+	if (v->s.pict_type == AV_PICTURE_TYPE_I || v->s.pict_type == AV_PICTURE_TYPE_BI)
+		skip_bits(gb, 7); // skip buffer fullness
+
+	if (v->parse_only)
+		return 0;
+
+	/* calculate RND */
+	if (v->s.pict_type == AV_PICTURE_TYPE_I || v->s.pict_type == AV_PICTURE_TYPE_BI)
+		v->rnd = 1;
+	if (v->s.pict_type == AV_PICTURE_TYPE_P)
+		v->rnd ^= 1;
+
+	if (get_bits_left(gb) < 5)
+		return (-1);
+	/* Quantizer stuff */
+	pqindex = get_bits(gb, 5);
+	if (!pqindex)
+		return -1;
+	if (v->quantizer_mode == QUANT_FRAME_IMPLICIT)
+		v->pq = ff_vc1_pquant_table[0][pqindex];
+	else
+		v->pq = ff_vc1_pquant_table[1][pqindex];
+	v->pqindex = pqindex;
+	if (pqindex < 9)
+		v->halfpq = get_bits1(gb);
+	else
+		v->halfpq = 0;
+	switch (v->quantizer_mode) {
+	case QUANT_FRAME_IMPLICIT:
+		v->pquantizer = pqindex < 9;
+		break;
+	case QUANT_NON_UNIFORM:
+		v->pquantizer = 0;
+		break;
+	case QUANT_FRAME_EXPLICIT:
+		v->pquantizer = get_bits1(gb);
+		break;
+	default:
+		v->pquantizer = 1;
+		break;
+	}
+	v->dquantfrm = 0;
+	if (v->extended_mv == 1)
+		v->mvrange = get_unary(gb, 0, 3);
+	v->k_x = v->mvrange + 9 + (v->mvrange >> 1); // k_x can be 9 10 12 13
+	v->k_y = v->mvrange + 8;                     // k_y can be 8 9 10 11
+	v->range_x = 1 << (v->k_x - 1);
+	v->range_y = 1 << (v->k_y - 1);
+	if (v->multires && v->s.pict_type != AV_PICTURE_TYPE_B)
+		v->respic = get_bits(gb, 2);
+
+	if (v->res_x8 && (v->s.pict_type == AV_PICTURE_TYPE_I || v->s.pict_type == AV_PICTURE_TYPE_BI)) {
+		v->x8_type = get_bits1(gb);
+	} else
+		v->x8_type = 0;
+
+	if (v->first_pic_header_flag)
+		rotate_luts(v);
+
+	switch (v->s.pict_type) {
+	case AV_PICTURE_TYPE_P:
+		v->tt_index = (v->pq > 4) + (v->pq > 12);
+
+		lowquant = (v->pq > 12) ? 0 : 1;
+		v->mv_mode = ff_vc1_mv_pmode_table[lowquant][get_unary(gb, 1, 4)];
+		if (v->mv_mode == MV_PMODE_INTENSITY_COMP) {
+			v->mv_mode2 = ff_vc1_mv_pmode_table2[lowquant][get_unary(gb, 1, 3)];
+			v->lumscale = get_bits(gb, 6);
+			v->lumshift = get_bits(gb, 6);
+			v->last_use_ic = 1;
+			/* fill lookup tables for intensity compensation */
+			INIT_LUT(v->lumscale, v->lumshift, v->last_luty[0], v->last_lutuv[0], 1);
+			INIT_LUT(v->lumscale, v->lumshift, v->last_luty[1], v->last_lutuv[1], 1);
+		}
+		if (v->mv_mode == MV_PMODE_INTENSITY_COMP) {
+			v->s.quarter_sample = (v->mv_mode2 != MV_PMODE_1MV_HPEL && v->mv_mode2 != MV_PMODE_1MV_HPEL_BILIN);
+			v->s.mspel = (v->mv_mode2 != MV_PMODE_1MV_HPEL_BILIN);
+		} else {
+			v->s.quarter_sample = (v->mv_mode != MV_PMODE_1MV_HPEL && v->mv_mode != MV_PMODE_1MV_HPEL_BILIN);
+			v->s.mspel = (v->mv_mode != MV_PMODE_1MV_HPEL_BILIN);
+		}
+
+		if ((v->mv_mode == MV_PMODE_INTENSITY_COMP && v->mv_mode2 == MV_PMODE_MIXED_MV) ||
+			v->mv_mode == MV_PMODE_MIXED_MV) {
+			status = bitplane_decoding(v->mv_type_mb_plane, &v->mv_type_is_raw, v);
+			if (status < 0)
+				return -1;
+
+		} else {
+			v->mv_type_is_raw = 0;
+			memset(v->mv_type_mb_plane, 0, v->s.mb_stride * v->s.mb_height);
+		}
+		status = bitplane_decoding(v->s.mbskip_table, &v->skip_is_raw, v);
+		if (status < 0)
+			return -1;
+
+		if (get_bits_left(gb) < 4)
+			return (-1);
+
+		/* Hopefully this is correct for P-frames */
+		v->mv_table_index = get_bits(gb, 2); // but using ff_vc1_ tables
+		v->cbptab = get_bits(gb, 2);
+		v->cbpcy_vlc = ff_vc1_cbpcy_p_vlc[v->cbptab];
+
+		if (v->dquant) {
+
+			vop_dquant_decoding(v);
+		}
+
+		if (v->vstransform) {
+			v->ttmbf = get_bits1(gb);
+			if (v->ttmbf) {
+				v->ttfrm = ff_vc1_ttfrm_to_tt[get_bits(gb, 2)];
+			} else
+				v->ttfrm = 0; // FIXME Is that so ?
+		} else {
+			v->ttmbf = 1;
+			v->ttfrm = TT_8X8;
+		}
+		break;
+	case AV_PICTURE_TYPE_B:
+		v->tt_index = (v->pq > 4) + (v->pq > 12);
+
+		v->mv_mode = get_bits1(gb) ? MV_PMODE_1MV : MV_PMODE_1MV_HPEL_BILIN;
+		v->s.quarter_sample = (v->mv_mode == MV_PMODE_1MV);
+		v->s.mspel = v->s.quarter_sample;
+
+		status = bitplane_decoding(v->direct_mb_plane, &v->dmb_is_raw, v);
+		if (status < 0)
+			return -1;
+
+		status = bitplane_decoding(v->s.mbskip_table, &v->skip_is_raw, v);
+		if (status < 0)
+			return -1;
+
+		v->mv_table_index = get_bits(gb, 2);
+		v->cbptab = get_bits(gb, 2);
+		v->cbpcy_vlc = ff_vc1_cbpcy_p_vlc[v->cbptab];
+
+		if (v->dquant) {
+
+			vop_dquant_decoding(v);
+		}
+
+		if (v->vstransform) {
+			v->ttmbf = get_bits1(gb);
+			if (v->ttmbf) {
+				v->ttfrm = ff_vc1_ttfrm_to_tt[get_bits(gb, 2)];
+			} else
+				v->ttfrm = 0;
+		} else {
+			v->ttmbf = 1;
+			v->ttfrm = TT_8X8;
+		}
+		break;
+	}
+
+	if (!v->x8_type) {
+		/* AC Syntax */
+		v->c_ac_table_index = decode012(gb);
+		if (v->s.pict_type == AV_PICTURE_TYPE_I || v->s.pict_type == AV_PICTURE_TYPE_BI) {
+			v->y_ac_table_index = decode012(gb);
+		}
+		/* DC Syntax */
+		v->dc_table_index = get_bits1(gb);
+	}
+
+	if (v->s.pict_type == AV_PICTURE_TYPE_BI) {
+		v->s.pict_type = AV_PICTURE_TYPE_B;
+		v->bi_type = 1;
+	}
+	return 0;
+}
+
+int ff_vc1_parse_frame_header_adv(VC1Context *v, Bits *gb) {
+	int pqindex, lowquant;
+	int status;
+	int field_mode, fcm;
+
+	v->numref = 0;
+	v->p_frame_skipped = 0;
+	if (v->second_field) {
+		if (v->fcm != ILACE_FIELD || v->field_mode != 1)
+			return -1;
+		if (v->fptype & 4)
+			v->s.pict_type = (v->fptype & 1) ? AV_PICTURE_TYPE_BI : AV_PICTURE_TYPE_B;
+		else
+			v->s.pict_type = (v->fptype & 1) ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I;
+		v->s.cur_pic.ptr->f->pict_type = v->s.pict_type;
+		if (!v->pic_header_flag)
+			goto parse_common_info;
+	}
+
+	field_mode = 0;
+	if (v->interlace) {
+		fcm = decode012(gb);
+		if (fcm) {
+			if (fcm == ILACE_FIELD)
+				field_mode = 1;
+		}
+	} else {
+		fcm = PROGRESSIVE;
+	}
+	if (!v->first_pic_header_flag && v->field_mode != field_mode)
+		return (-1);
+	v->field_mode = field_mode;
+	v->fcm = fcm;
+
+	assert(v->s.mb_height == v->s.height + 15 >> 4 || v->s.mb_height == FFALIGN(v->s.height + 15 >> 4, 2));
+	if (v->field_mode) {
+		v->s.mb_height = FFALIGN(v->s.height + 15 >> 4, 2);
+		v->fptype = get_bits(gb, 3);
+		if (v->fptype & 4) // B-picture
+			v->s.pict_type = (v->fptype & 2) ? AV_PICTURE_TYPE_BI : AV_PICTURE_TYPE_B;
+		else
+			v->s.pict_type = (v->fptype & 2) ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I;
+	} else {
+		v->s.mb_height = v->s.height + 15 >> 4;
+		switch (get_unary(gb, 0, 4)) {
+		case 0:
+			v->s.pict_type = AV_PICTURE_TYPE_P;
+			break;
+		case 1:
+			v->s.pict_type = AV_PICTURE_TYPE_B;
+			break;
+		case 2:
+			v->s.pict_type = AV_PICTURE_TYPE_I;
+			break;
+		case 3:
+			v->s.pict_type = AV_PICTURE_TYPE_BI;
+			break;
+		case 4:
+			v->s.pict_type = AV_PICTURE_TYPE_P; // skipped pic
+			v->p_frame_skipped = 1;
+			break;
+		}
+	}
+	if (v->tfcntrflag)
+		skip_bits(gb, 8);
+	if (v->broadcast) {
+		if (!v->interlace || v->psf) {
+			v->rptfrm = get_bits(gb, 2);
+		} else {
+			v->tff = get_bits1(gb);
+			v->rff = get_bits1(gb);
+		}
+	} else {
+		v->tff = 1;
+	}
+	if (v->panscanflag) {
+		warning("Pan-scan");
+		//...
+	}
+	if (v->p_frame_skipped) {
+		return 0;
+	}
+	v->rnd = get_bits1(gb);
+	if (v->interlace)
+		v->uvsamp = get_bits1(gb);
+	if (v->field_mode) {
+		if (!v->refdist_flag)
+			v->refdist = 0;
+		else if ((v->s.pict_type != AV_PICTURE_TYPE_B) && (v->s.pict_type != AV_PICTURE_TYPE_BI)) {
+			v->refdist = get_bits(gb, 2);
+			if (v->refdist == 3)
+				v->refdist += get_unary(gb, 0, 14);
+			if (v->refdist > 16)
+				return (-1);
+		}
+		if ((v->s.pict_type == AV_PICTURE_TYPE_B) || (v->s.pict_type == AV_PICTURE_TYPE_BI)) {
+			if (read_bfraction(v, gb) < 0)
+				return (-1);
+			v->frfd = (v->bfraction * v->refdist) >> 8;
+			v->brfd = v->refdist - v->frfd - 1;
+			if (v->brfd < 0)
+				v->brfd = 0;
+		}
+		goto parse_common_info;
+	}
+	if (v->fcm == PROGRESSIVE) {
+		if (v->finterpflag)
+			v->interpfrm = get_bits1(gb);
+		if (v->s.pict_type == AV_PICTURE_TYPE_B) {
+			if (read_bfraction(v, gb) < 0)
+				return (-1);
+			if (v->bfraction == 0) {
+				v->s.pict_type = AV_PICTURE_TYPE_BI; /* XXX: should not happen here */
+			}
+		}
+	}
+
+parse_common_info:
+	if (v->field_mode)
+		v->cur_field_type = !(v->tff ^ v->second_field);
+	pqindex = get_bits(gb, 5);
+	if (!pqindex)
+		return -1;
+	if (v->quantizer_mode == QUANT_FRAME_IMPLICIT)
+		v->pq = ff_vc1_pquant_table[0][pqindex];
+	else
+		v->pq = ff_vc1_pquant_table[1][pqindex];
+	v->pqindex = pqindex;
+	if (pqindex < 9)
+		v->halfpq = get_bits1(gb);
+	else
+		v->halfpq = 0;
+	switch (v->quantizer_mode) {
+	case QUANT_FRAME_IMPLICIT:
+		v->pquantizer = pqindex < 9;
+		break;
+	case QUANT_NON_UNIFORM:
+		v->pquantizer = 0;
+		break;
+	case QUANT_FRAME_EXPLICIT:
+		v->pquantizer = get_bits1(gb);
+		break;
+	default:
+		v->pquantizer = 1;
+		break;
+	}
+	v->dquantfrm = 0;
+	if (v->postprocflag)
+		v->postproc = get_bits(gb, 2);
+
+	if (v->parse_only)
+		return 0;
+
+	if (v->first_pic_header_flag)
+		rotate_luts(v);
+
+	switch (v->s.pict_type) {
+	case AV_PICTURE_TYPE_I:
+	case AV_PICTURE_TYPE_BI:
+		if (v->fcm == ILACE_FRAME) { // interlace frame picture
+			status = bitplane_decoding(v->fieldtx_plane, &v->fieldtx_is_raw, v);
+			if (status < 0)
+				return -1;
+
+		} else
+			v->fieldtx_is_raw = 0;
+		status = bitplane_decoding(v->acpred_plane, &v->acpred_is_raw, v);
+		if (status < 0)
+			return -1;
+
+		v->condover = CONDOVER_NONE;
+		if (v->overlap && v->pq <= 8) {
+			v->condover = decode012(gb);
+			if (v->condover == CONDOVER_SELECT) {
+				status = bitplane_decoding(v->over_flags_plane, &v->overflg_is_raw, v);
+				if (status < 0)
+					return -1;
+			}
+		}
+		break;
+	case AV_PICTURE_TYPE_P:
+		if (v->field_mode) {
+			v->numref = get_bits1(gb);
+			if (!v->numref) {
+				v->reffield = get_bits1(gb);
+				v->ref_field_type[0] = v->reffield ^ !v->cur_field_type;
+			}
+		}
+		if (v->extended_mv)
+			v->mvrange = get_unary(gb, 0, 3);
+		else
+			v->mvrange = 0;
+		if (v->interlace) {
+			if (v->extended_dmv)
+				v->dmvrange = get_unary(gb, 0, 3);
+			else
+				v->dmvrange = 0;
+			if (v->fcm == ILACE_FRAME) { // interlaced frame picture
+				v->fourmvswitch = get_bits1(gb);
+				v->intcomp = get_bits1(gb);
+				if (v->intcomp) {
+					v->lumscale = get_bits(gb, 6);
+					v->lumshift = get_bits(gb, 6);
+					INIT_LUT(v->lumscale, v->lumshift, v->last_luty[0], v->last_lutuv[0], 1);
+					INIT_LUT(v->lumscale, v->lumshift, v->last_luty[1], v->last_lutuv[1], 1);
+					v->last_use_ic = 1;
+				}
+				status = bitplane_decoding(v->s.mbskip_table, &v->skip_is_raw, v);
+				if (status < 0)
+					return -1;
+
+				v->mbmodetab = get_bits(gb, 2);
+				if (v->fourmvswitch)
+					v->mbmode_vlc = ff_vc1_intfr_4mv_mbmode_vlc[v->mbmodetab];
+				else
+					v->mbmode_vlc = ff_vc1_intfr_non4mv_mbmode_vlc[v->mbmodetab];
+				v->imvtab = get_bits(gb, 2);
+				v->imv_vlc = ff_vc1_1ref_mvdata_vlc[v->imvtab];
+				// interlaced p-picture cbpcy range is [1, 63]
+				v->icbptab = get_bits(gb, 3);
+				v->cbpcy_vlc = ff_vc1_icbpcy_vlc[v->icbptab];
+				v->twomvbptab = get_bits(gb, 2);
+				v->twomvbp_vlc = ff_vc1_2mv_block_pattern_vlc[v->twomvbptab];
+				if (v->fourmvswitch) {
+					v->fourmvbptab = get_bits(gb, 2);
+					v->fourmvbp_vlc = ff_vc1_4mv_block_pattern_vlc[v->fourmvbptab];
+				}
+			}
+		}
+		v->k_x = v->mvrange + 9 + (v->mvrange >> 1); // k_x can be 9 10 12 13
+		v->k_y = v->mvrange + 8;                     // k_y can be 8 9 10 11
+		v->range_x = 1 << (v->k_x - 1);
+		v->range_y = 1 << (v->k_y - 1);
+
+		v->tt_index = (v->pq > 4) + (v->pq > 12);
+		if (v->fcm != ILACE_FRAME) {
+			int mvmode;
+			mvmode = get_unary(gb, 1, 4);
+			lowquant = (v->pq > 12) ? 0 : 1;
+			v->mv_mode = ff_vc1_mv_pmode_table[lowquant][mvmode];
+			if (v->mv_mode == MV_PMODE_INTENSITY_COMP) {
+				int mvmode2;
+				mvmode2 = get_unary(gb, 1, 3);
+				v->mv_mode2 = ff_vc1_mv_pmode_table2[lowquant][mvmode2];
+				if (v->field_mode) {
+					v->intcompfield = decode210(gb) ^ 3;
+				} else
+					v->intcompfield = 3;
+
+				v->lumscale2 = v->lumscale = 32;
+				v->lumshift2 = v->lumshift = 0;
+				if (v->intcompfield & 1) {
+					v->lumscale = get_bits(gb, 6);
+					v->lumshift = get_bits(gb, 6);
+				}
+				if ((v->intcompfield & 2) && v->field_mode) {
+					v->lumscale2 = get_bits(gb, 6);
+					v->lumshift2 = get_bits(gb, 6);
+				} else if (!v->field_mode) {
+					v->lumscale2 = v->lumscale;
+					v->lumshift2 = v->lumshift;
+				}
+				if (v->field_mode && v->second_field) {
+					if (v->cur_field_type) {
+						INIT_LUT(v->lumscale, v->lumshift, v->curr_luty[v->cur_field_type ^ 1],
+								 v->curr_lutuv[v->cur_field_type ^ 1], 0);
+						INIT_LUT(v->lumscale2, v->lumshift2, v->last_luty[v->cur_field_type],
+								 v->last_lutuv[v->cur_field_type], 1);
+					} else {
+						INIT_LUT(v->lumscale2, v->lumshift2, v->curr_luty[v->cur_field_type ^ 1],
+								 v->curr_lutuv[v->cur_field_type ^ 1], 0);
+						INIT_LUT(v->lumscale, v->lumshift, v->last_luty[v->cur_field_type],
+								 v->last_lutuv[v->cur_field_type], 1);
+					}
+					v->next_use_ic = *v->curr_use_ic = 1;
+				} else {
+					INIT_LUT(v->lumscale, v->lumshift, v->last_luty[0], v->last_lutuv[0], 1);
+					INIT_LUT(v->lumscale2, v->lumshift2, v->last_luty[1], v->last_lutuv[1], 1);
+				}
+				v->last_use_ic = 1;
+			}
+			if (v->mv_mode == MV_PMODE_INTENSITY_COMP) {
+				v->s.quarter_sample = (v->mv_mode2 != MV_PMODE_1MV_HPEL && v->mv_mode2 != MV_PMODE_1MV_HPEL_BILIN);
+				v->s.mspel = (v->mv_mode2 != MV_PMODE_1MV_HPEL_BILIN);
+			} else {
+				v->s.quarter_sample = (v->mv_mode != MV_PMODE_1MV_HPEL && v->mv_mode != MV_PMODE_1MV_HPEL_BILIN);
+				v->s.mspel = (v->mv_mode != MV_PMODE_1MV_HPEL_BILIN);
+			}
+		}
+		if (v->fcm == PROGRESSIVE) { // progressive
+			if ((v->mv_mode == MV_PMODE_INTENSITY_COMP && v->mv_mode2 == MV_PMODE_MIXED_MV) ||
+				v->mv_mode == MV_PMODE_MIXED_MV) {
+				status = bitplane_decoding(v->mv_type_mb_plane, &v->mv_type_is_raw, v);
+				if (status < 0)
+					return -1;
+
+			} else {
+				v->mv_type_is_raw = 0;
+				memset(v->mv_type_mb_plane, 0, v->s.mb_stride * v->s.mb_height);
+			}
+			status = bitplane_decoding(v->s.mbskip_table, &v->skip_is_raw, v);
+			if (status < 0)
+				return -1;
+
+			/* Hopefully this is correct for P-frames */
+			v->mv_table_index = get_bits(gb, 2); // but using ff_vc1_ tables
+			v->cbptab = get_bits(gb, 2);
+			v->cbpcy_vlc = ff_vc1_cbpcy_p_vlc[v->cbptab];
+		} else if (v->fcm == ILACE_FRAME) { // frame interlaced
+			v->s.quarter_sample = 1;
+			v->s.mspel = 1;
+		} else { // field interlaced
+			v->mbmodetab = get_bits(gb, 3);
+			v->imvtab = get_bits(gb, 2 + v->numref);
+			if (!v->numref)
+				v->imv_vlc = ff_vc1_1ref_mvdata_vlc[v->imvtab];
+			else
+				v->imv_vlc = ff_vc1_2ref_mvdata_vlc[v->imvtab];
+			v->icbptab = get_bits(gb, 3);
+			v->cbpcy_vlc = ff_vc1_icbpcy_vlc[v->icbptab];
+			if ((v->mv_mode == MV_PMODE_INTENSITY_COMP && v->mv_mode2 == MV_PMODE_MIXED_MV) ||
+				v->mv_mode == MV_PMODE_MIXED_MV) {
+				v->fourmvbptab = get_bits(gb, 2);
+				v->fourmvbp_vlc = ff_vc1_4mv_block_pattern_vlc[v->fourmvbptab];
+				v->mbmode_vlc = ff_vc1_if_mmv_mbmode_vlc[v->mbmodetab];
+			} else {
+				v->mbmode_vlc = ff_vc1_if_1mv_mbmode_vlc[v->mbmodetab];
+			}
+		}
+		if (v->dquant) {
+
+			vop_dquant_decoding(v);
+		}
+
+		if (v->vstransform) {
+			v->ttmbf = get_bits1(gb);
+			if (v->ttmbf) {
+				v->ttfrm = ff_vc1_ttfrm_to_tt[get_bits(gb, 2)];
+			} else
+				v->ttfrm = 0; // FIXME Is that so ?
+		} else {
+			v->ttmbf = 1;
+			v->ttfrm = TT_8X8;
+		}
+		break;
+	case AV_PICTURE_TYPE_B:
+		if (v->fcm == ILACE_FRAME) {
+			if (read_bfraction(v, gb) < 0)
+				return (-1);
+			if (v->bfraction == 0) {
+				return -1;
+			}
+		}
+		if (v->extended_mv)
+			v->mvrange = get_unary(gb, 0, 3);
+		else
+			v->mvrange = 0;
+		v->k_x = v->mvrange + 9 + (v->mvrange >> 1); // k_x can be 9 10 12 13
+		v->k_y = v->mvrange + 8;                     // k_y can be 8 9 10 11
+		v->range_x = 1 << (v->k_x - 1);
+		v->range_y = 1 << (v->k_y - 1);
+
+		v->tt_index = (v->pq > 4) + (v->pq > 12);
+
+		if (v->field_mode) {
+			int mvmode;
+
+			if (v->extended_dmv)
+				v->dmvrange = get_unary(gb, 0, 3);
+			mvmode = get_unary(gb, 1, 3);
+			lowquant = (v->pq > 12) ? 0 : 1;
+			v->mv_mode = ff_vc1_mv_pmode_table2[lowquant][mvmode];
+			v->s.quarter_sample = (v->mv_mode == MV_PMODE_1MV || v->mv_mode == MV_PMODE_MIXED_MV);
+			v->s.mspel = (v->mv_mode != MV_PMODE_1MV_HPEL_BILIN);
+			status = bitplane_decoding(v->forward_mb_plane, &v->fmb_is_raw, v);
+			if (status < 0)
+				return -1;
+
+			v->mbmodetab = get_bits(gb, 3);
+			if (v->mv_mode == MV_PMODE_MIXED_MV)
+				v->mbmode_vlc = ff_vc1_if_mmv_mbmode_vlc[v->mbmodetab];
+			else
+				v->mbmode_vlc = ff_vc1_if_1mv_mbmode_vlc[v->mbmodetab];
+			v->imvtab = get_bits(gb, 3);
+			v->imv_vlc = ff_vc1_2ref_mvdata_vlc[v->imvtab];
+			v->icbptab = get_bits(gb, 3);
+			v->cbpcy_vlc = ff_vc1_icbpcy_vlc[v->icbptab];
+			if (v->mv_mode == MV_PMODE_MIXED_MV) {
+				v->fourmvbptab = get_bits(gb, 2);
+				v->fourmvbp_vlc = ff_vc1_4mv_block_pattern_vlc[v->fourmvbptab];
+			}
+			v->numref = 1; // interlaced field B pictures are always 2-ref
+		} else if (v->fcm == ILACE_FRAME) {
+			if (v->extended_dmv)
+				v->dmvrange = get_unary(gb, 0, 3);
+			if (get_bits1(gb)) /* intcomp - present but shall always be 0 */
+				warning("Intensity compensation set for B picture\n");
+			v->intcomp = 0;
+			v->mv_mode = MV_PMODE_1MV;
+			v->fourmvswitch = 0;
+			v->s.quarter_sample = 1;
+			v->s.mspel = 1;
+			status = bitplane_decoding(v->direct_mb_plane, &v->dmb_is_raw, v);
+			if (status < 0)
+				return -1;
+
+			status = bitplane_decoding(v->s.mbskip_table, &v->skip_is_raw, v);
+			if (status < 0)
+				return -1;
+
+			v->mbmodetab = get_bits(gb, 2);
+			v->mbmode_vlc = ff_vc1_intfr_non4mv_mbmode_vlc[v->mbmodetab];
+			v->imvtab = get_bits(gb, 2);
+			v->imv_vlc = ff_vc1_1ref_mvdata_vlc[v->imvtab];
+			// interlaced p/b-picture cbpcy range is [1, 63]
+			v->icbptab = get_bits(gb, 3);
+			v->cbpcy_vlc = ff_vc1_icbpcy_vlc[v->icbptab];
+			v->twomvbptab = get_bits(gb, 2);
+			v->twomvbp_vlc = ff_vc1_2mv_block_pattern_vlc[v->twomvbptab];
+			v->fourmvbptab = get_bits(gb, 2);
+			v->fourmvbp_vlc = ff_vc1_4mv_block_pattern_vlc[v->fourmvbptab];
+		} else {
+			v->mv_mode = get_bits1(gb) ? MV_PMODE_1MV : MV_PMODE_1MV_HPEL_BILIN;
+			v->s.quarter_sample = (v->mv_mode == MV_PMODE_1MV);
+			v->s.mspel = v->s.quarter_sample;
+			status = bitplane_decoding(v->direct_mb_plane, &v->dmb_is_raw, v);
+			if (status < 0)
+				return -1;
+
+			status = bitplane_decoding(v->s.mbskip_table, &v->skip_is_raw, v);
+			if (status < 0)
+				return -1;
+
+			v->mv_table_index = get_bits(gb, 2);
+			v->cbptab = get_bits(gb, 2);
+			v->cbpcy_vlc = ff_vc1_cbpcy_p_vlc[v->cbptab];
+		}
+
+		if (v->dquant) {
+
+			vop_dquant_decoding(v);
+		}
+
+		if (v->vstransform) {
+			v->ttmbf = get_bits1(gb);
+			if (v->ttmbf) {
+				v->ttfrm = ff_vc1_ttfrm_to_tt[get_bits(gb, 2)];
+			} else
+				v->ttfrm = 0;
+		} else {
+			v->ttmbf = 1;
+			v->ttfrm = TT_8X8;
+		}
+		break;
+	}
+
+	/* AC Syntax */
+	v->c_ac_table_index = decode012(gb);
+	if (v->s.pict_type == AV_PICTURE_TYPE_I || v->s.pict_type == AV_PICTURE_TYPE_BI) {
+		v->y_ac_table_index = decode012(gb);
+	} else if (v->fcm != PROGRESSIVE && !v->s.quarter_sample) {
+		v->range_x <<= 1;
+		v->range_y <<= 1;
+	}
+
+	/* DC Syntax */
+	v->dc_table_index = get_bits1(gb);
+	if ((v->s.pict_type == AV_PICTURE_TYPE_I || v->s.pict_type == AV_PICTURE_TYPE_BI) && v->dquant) {
+
+		vop_dquant_decoding(v);
+	}
+
+	v->bi_type = (v->s.pict_type == AV_PICTURE_TYPE_BI);
+	if (v->bi_type)
+		v->s.pict_type = AV_PICTURE_TYPE_B;
+
+	return 0;
+}
+
+#undef INIT_LUT
+#undef ROTATE
+
+static inline int scaleforsame_x(const VC1Context *v, int n /* MV */, int dir) {
+	int scaledvalue, refdist;
+	int scalesame1, scalesame2;
+	int scalezone1_x, zone1offset_x;
+	int table_index = dir ^ v->second_field;
+
+	if (v->s.pict_type != AV_PICTURE_TYPE_B)
+		refdist = v->refdist;
+	else
+		refdist = dir ? v->brfd : v->frfd;
+	if (refdist > 3)
+		refdist = 3;
+	scalesame1 = ff_vc1_field_mvpred_scales[table_index][1][refdist];
+	scalesame2 = ff_vc1_field_mvpred_scales[table_index][2][refdist];
+	scalezone1_x = ff_vc1_field_mvpred_scales[table_index][3][refdist];
+	zone1offset_x = ff_vc1_field_mvpred_scales[table_index][5][refdist];
+
+	if (ABS(n) > 255)
+		scaledvalue = n;
+	else {
+		if (ABS(n) < scalezone1_x)
+			scaledvalue = (n * scalesame1) >> 8;
+		else {
+			if (n < 0)
+				scaledvalue = ((n * scalesame2) >> 8) - zone1offset_x;
+			else
+				scaledvalue = ((n * scalesame2) >> 8) + zone1offset_x;
+		}
+	}
+	return av_clip(scaledvalue, -v->range_x, v->range_x - 1);
+}
+
+static inline int scaleforsame_y(const VC1Context *v, int n /* MV */, int dir) {
+	int scaledvalue, refdist;
+	int scalesame1, scalesame2;
+	int scalezone1_y, zone1offset_y;
+	int table_index = dir ^ v->second_field;
+
+	if (v->s.pict_type != AV_PICTURE_TYPE_B)
+		refdist = v->refdist;
+	else
+		refdist = dir ? v->brfd : v->frfd;
+	if (refdist > 3)
+		refdist = 3;
+	scalesame1 = ff_vc1_field_mvpred_scales[table_index][1][refdist];
+	scalesame2 = ff_vc1_field_mvpred_scales[table_index][2][refdist];
+	scalezone1_y = ff_vc1_field_mvpred_scales[table_index][4][refdist];
+	zone1offset_y = ff_vc1_field_mvpred_scales[table_index][6][refdist];
+
+	if (ABS(n) > 63)
+		scaledvalue = n;
+	else {
+		if (ABS(n) < scalezone1_y)
+			scaledvalue = (n * scalesame1) >> 8;
+		else {
+			if (n < 0)
+				scaledvalue = ((n * scalesame2) >> 8) - zone1offset_y;
+			else
+				scaledvalue = ((n * scalesame2) >> 8) + zone1offset_y;
+		}
+	}
+
+	if (v->cur_field_type && !v->ref_field_type[dir])
+		return av_clip(scaledvalue, -v->range_y / 2 + 1, v->range_y / 2);
+	else
+		return av_clip(scaledvalue, -v->range_y / 2, v->range_y / 2 - 1);
+}
+
+static inline int scaleforopp_x(const VC1Context *v, int n /* MV */) {
+	int scalezone1_x, zone1offset_x;
+	int scaleopp1, scaleopp2, brfd;
+	int scaledvalue;
+
+	brfd = MIN(v->brfd, 3);
+	scalezone1_x = ff_vc1_b_field_mvpred_scales[3][brfd];
+	zone1offset_x = ff_vc1_b_field_mvpred_scales[5][brfd];
+	scaleopp1 = ff_vc1_b_field_mvpred_scales[1][brfd];
+	scaleopp2 = ff_vc1_b_field_mvpred_scales[2][brfd];
+
+	if (ABS(n) > 255)
+		scaledvalue = n;
+	else {
+		if (ABS(n) < scalezone1_x)
+			scaledvalue = (n * scaleopp1) >> 8;
+		else {
+			if (n < 0)
+				scaledvalue = ((n * scaleopp2) >> 8) - zone1offset_x;
+			else
+				scaledvalue = ((n * scaleopp2) >> 8) + zone1offset_x;
+		}
+	}
+	return av_clip(scaledvalue, -v->range_x, v->range_x - 1);
+}
+
+static inline int scaleforopp_y(const VC1Context *v, int n /* MV */, int dir) {
+	int scalezone1_y, zone1offset_y;
+	int scaleopp1, scaleopp2, brfd;
+	int scaledvalue;
+
+	brfd = MIN(v->brfd, 3);
+	scalezone1_y = ff_vc1_b_field_mvpred_scales[4][brfd];
+	zone1offset_y = ff_vc1_b_field_mvpred_scales[6][brfd];
+	scaleopp1 = ff_vc1_b_field_mvpred_scales[1][brfd];
+	scaleopp2 = ff_vc1_b_field_mvpred_scales[2][brfd];
+
+	if (ABS(n) > 63)
+		scaledvalue = n;
+	else {
+		if (ABS(n) < scalezone1_y)
+			scaledvalue = (n * scaleopp1) >> 8;
+		else {
+			if (n < 0)
+				scaledvalue = ((n * scaleopp2) >> 8) - zone1offset_y;
+			else
+				scaledvalue = ((n * scaleopp2) >> 8) + zone1offset_y;
+		}
+	}
+	if (v->cur_field_type && !v->ref_field_type[dir]) {
+		return av_clip(scaledvalue, -v->range_y / 2 + 1, v->range_y / 2);
+	} else {
+		return av_clip(scaledvalue, -v->range_y / 2, v->range_y / 2 - 1);
+	}
+}
+
+static inline int scaleforsame(const VC1Context *v, int n /* MV */, int dim, int dir) {
+	int brfd, scalesame;
+	int hpel = 1 - v->s.quarter_sample;
+
+	n >>= hpel;
+	if (v->s.pict_type != AV_PICTURE_TYPE_B || v->second_field || !dir) {
+		if (dim)
+			n = scaleforsame_y(v, n, dir) * (1 << hpel);
+		else
+			n = scaleforsame_x(v, n, dir) * (1 << hpel);
+		return n;
+	}
+	brfd = MIN(v->brfd, 3);
+	scalesame = ff_vc1_b_field_mvpred_scales[0][brfd];
+
+	n = (n * scalesame >> 8) * (1 << hpel);
+	return n;
+}
+
+static inline int scaleforopp(const VC1Context *v, int n /* MV */, int dim, int dir) {
+	int refdist, scaleopp;
+	int hpel = 1 - v->s.quarter_sample;
+
+	n >>= hpel;
+	if (v->s.pict_type == AV_PICTURE_TYPE_B && !v->second_field && dir == 1) {
+		if (dim)
+			n = scaleforopp_y(v, n, dir) * (1 << hpel);
+		else
+			n = scaleforopp_x(v, n) * (1 << hpel);
+		return n;
+	}
+	if (v->s.pict_type != AV_PICTURE_TYPE_B)
+		refdist = v->refdist;
+	else
+		refdist = dir ? v->brfd : v->frfd;
+	refdist = MIN(refdist, 3);
+	scaleopp = ff_vc1_field_mvpred_scales[dir ^ v->second_field][0][refdist];
+
+	n = (n * scaleopp >> 8) * (1 << hpel);
+	return n;
+}
+
+/** Predict and set motion vector
+ */
+void ff_vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y, int mv1, int r_x, int r_y, uint8 *is_intra,
+					int pred_flag, int dir) {
+	PictureState *s = &v->s;
+	int xy, wrap, off = 0;
+	int px, py;
+	int sum;
+	int mixedmv_pic, num_samefield = 0, num_oppfield = 0;
+	int opposite, a_f, b_f, c_f;
+	int16 field_predA[2];
+	int16 field_predB[2];
+	int16 field_predC[2];
+	int a_valid, b_valid, c_valid;
+	int hybridmv_thresh, y_bias = 0;
+
+	if (v->mv_mode == MV_PMODE_MIXED_MV ||
+		((v->mv_mode == MV_PMODE_INTENSITY_COMP) && (v->mv_mode2 == MV_PMODE_MIXED_MV)))
+		mixedmv_pic = 1;
+	else
+		mixedmv_pic = 0;
+	/* scale MV difference to be quad-pel */
+	if (!s->quarter_sample) {
+		dmv_x *= 2;
+		dmv_y *= 2;
+	}
+
+	wrap = s->b8_stride;
+	xy = s->block_index[n];
+
+	if (s->mb_intra) {
+		s->mv[0][n][0] = s->cur_pic.motion_val[0][xy + v->blocks_off][0] = 0;
+		s->mv[0][n][1] = s->cur_pic.motion_val[0][xy + v->blocks_off][1] = 0;
+		s->cur_pic.motion_val[1][xy + v->blocks_off][0] = 0;
+		s->cur_pic.motion_val[1][xy + v->blocks_off][1] = 0;
+		if (mv1) { /* duplicate motion data for 1-MV block */
+			s->cur_pic.motion_val[0][xy + 1 + v->blocks_off][0] = 0;
+			s->cur_pic.motion_val[0][xy + 1 + v->blocks_off][1] = 0;
+			s->cur_pic.motion_val[0][xy + wrap + v->blocks_off][0] = 0;
+			s->cur_pic.motion_val[0][xy + wrap + v->blocks_off][1] = 0;
+			s->cur_pic.motion_val[0][xy + wrap + 1 + v->blocks_off][0] = 0;
+			s->cur_pic.motion_val[0][xy + wrap + 1 + v->blocks_off][1] = 0;
+			v->luma_mv[s->mb_x][0] = v->luma_mv[s->mb_x][1] = 0;
+			s->cur_pic.motion_val[1][xy + 1 + v->blocks_off][0] = 0;
+			s->cur_pic.motion_val[1][xy + 1 + v->blocks_off][1] = 0;
+			s->cur_pic.motion_val[1][xy + wrap + v->blocks_off][0] = 0;
+			s->cur_pic.motion_val[1][xy + wrap + v->blocks_off][1] = 0;
+			s->cur_pic.motion_val[1][xy + wrap + 1 + v->blocks_off][0] = 0;
+			s->cur_pic.motion_val[1][xy + wrap + 1 + v->blocks_off][1] = 0;
+		}
+		return;
+	}
+
+	a_valid = !s->first_slice_line || (n == 2 || n == 3);
+	b_valid = a_valid;
+	c_valid = s->mb_x || (n == 1 || n == 3);
+	if (mv1) {
+		if (v->field_mode && mixedmv_pic)
+			off = (s->mb_x == (s->mb_width - 1)) ? -2 : 2;
+		else
+			off = (s->mb_x == (s->mb_width - 1)) ? -1 : 2;
+		b_valid = b_valid && s->mb_width > 1;
+	} else {
+		// in 4-MV mode different blocks have different B predictor position
+		switch (n) {
+		case 0:
+			if (v->res_rtm_flag)
+				off = s->mb_x ? -1 : 1;
+			else
+				off = s->mb_x ? -1 : 2 * s->mb_width - wrap - 1;
+			break;
+		case 1:
+			off = (s->mb_x == (s->mb_width - 1)) ? -1 : 1;
+			break;
+		case 2:
+			off = 1;
+			break;
+		case 3:
+			off = -1;
+		}
+		if (v->field_mode && s->mb_width == 1)
+			b_valid = b_valid && c_valid;
+	}
+
+	if (v->field_mode) {
+		a_valid = a_valid && !is_intra[xy - wrap];
+		b_valid = b_valid && !is_intra[xy - wrap + off];
+		c_valid = c_valid && !is_intra[xy - 1];
+	}
+
+	if (a_valid) {
+		const int16 *A = s->cur_pic.motion_val[dir][xy - wrap + v->blocks_off];
+		a_f = v->mv_f[dir][xy - wrap + v->blocks_off];
+		num_oppfield += a_f;
+		num_samefield += 1 - a_f;
+		field_predA[0] = A[0];
+		field_predA[1] = A[1];
+	} else {
+		field_predA[0] = field_predA[1] = 0;
+		a_f = 0;
+	}
+	if (b_valid) {
+		const int16 *B = s->cur_pic.motion_val[dir][xy - wrap + off + v->blocks_off];
+		b_f = v->mv_f[dir][xy - wrap + off + v->blocks_off];
+		num_oppfield += b_f;
+		num_samefield += 1 - b_f;
+		field_predB[0] = B[0];
+		field_predB[1] = B[1];
+	} else {
+		field_predB[0] = field_predB[1] = 0;
+		b_f = 0;
+	}
+	if (c_valid) {
+		const int16 *C = s->cur_pic.motion_val[dir][xy - 1 + v->blocks_off];
+		c_f = v->mv_f[dir][xy - 1 + v->blocks_off];
+		num_oppfield += c_f;
+		num_samefield += 1 - c_f;
+		field_predC[0] = C[0];
+		field_predC[1] = C[1];
+	} else {
+		field_predC[0] = field_predC[1] = 0;
+		c_f = 0;
+	}
+
+	if (v->field_mode) {
+		if (!v->numref)
+			// REFFIELD determines if the last field or the second-last field is
+			// to be used as reference
+			opposite = 1 - v->reffield;
+		else {
+			if (num_samefield <= num_oppfield)
+				opposite = 1 - pred_flag;
+			else
+				opposite = pred_flag;
+		}
+	} else
+		opposite = 0;
+	if (opposite) {
+		v->mv_f[dir][xy + v->blocks_off] = 1;
+		v->ref_field_type[dir] = !v->cur_field_type;
+		if (a_valid && !a_f) {
+			field_predA[0] = scaleforopp(v, field_predA[0], 0, dir);
+			field_predA[1] = scaleforopp(v, field_predA[1], 1, dir);
+		}
+		if (b_valid && !b_f) {
+			field_predB[0] = scaleforopp(v, field_predB[0], 0, dir);
+			field_predB[1] = scaleforopp(v, field_predB[1], 1, dir);
+		}
+		if (c_valid && !c_f) {
+			field_predC[0] = scaleforopp(v, field_predC[0], 0, dir);
+			field_predC[1] = scaleforopp(v, field_predC[1], 1, dir);
+		}
+	} else {
+		v->mv_f[dir][xy + v->blocks_off] = 0;
+		v->ref_field_type[dir] = v->cur_field_type;
+		if (a_valid && a_f) {
+			field_predA[0] = scaleforsame(v, field_predA[0], 0, dir);
+			field_predA[1] = scaleforsame(v, field_predA[1], 1, dir);
+		}
+		if (b_valid && b_f) {
+			field_predB[0] = scaleforsame(v, field_predB[0], 0, dir);
+			field_predB[1] = scaleforsame(v, field_predB[1], 1, dir);
+		}
+		if (c_valid && c_f) {
+			field_predC[0] = scaleforsame(v, field_predC[0], 0, dir);
+			field_predC[1] = scaleforsame(v, field_predC[1], 1, dir);
+		}
+	}
+
+	if (a_valid) {
+		px = field_predA[0];
+		py = field_predA[1];
+	} else if (c_valid) {
+		px = field_predC[0];
+		py = field_predC[1];
+	} else if (b_valid) {
+		px = field_predB[0];
+		py = field_predB[1];
+	} else {
+		px = 0;
+		py = 0;
+	}
+
+	if (num_samefield + num_oppfield > 1) {
+		px = mid_pred(field_predA[0], field_predB[0], field_predC[0]);
+		py = mid_pred(field_predA[1], field_predB[1], field_predC[1]);
+	}
+
+	/* Pullback MV as specified in 8.3.5.3.4 */
+	if (!v->field_mode) {
+		int qx, qy, X, Y;
+		int MV = mv1 ? -60 : -28;
+		qx = (s->mb_x << 6) + ((n == 1 || n == 3) ? 32 : 0);
+		qy = (s->mb_y << 6) + ((n == 2 || n == 3) ? 32 : 0);
+		X = (s->mb_width << 6) - 4;
+		Y = (s->mb_height << 6) - 4;
+		if (qx + px < MV)
+			px = MV - qx;
+		if (qy + py < MV)
+			py = MV - qy;
+		if (qx + px > X)
+			px = X - qx;
+		if (qy + py > Y)
+			py = Y - qy;
+	}
+
+	if (!v->field_mode || s->pict_type != AV_PICTURE_TYPE_B) {
+		/* Calculate hybrid prediction as specified in 8.3.5.3.5 (also 10.3.5.4.3.5) */
+		hybridmv_thresh = 32;
+		if (a_valid && c_valid) {
+			if (is_intra[xy - wrap])
+				sum = ABS(px) + ABS(py);
+			else
+				sum = ABS(px - field_predA[0]) + ABS(py - field_predA[1]);
+			if (sum > hybridmv_thresh) {
+				if (get_bits1(&v->gb)) { // read HYBRIDPRED bit
+					px = field_predA[0];
+					py = field_predA[1];
+				} else {
+					px = field_predC[0];
+					py = field_predC[1];
+				}
+			} else {
+				if (is_intra[xy - 1])
+					sum = ABS(px) + ABS(py);
+				else
+					sum = ABS(px - field_predC[0]) + ABS(py - field_predC[1]);
+				if (sum > hybridmv_thresh) {
+					if (get_bits1(&v->gb)) {
+						px = field_predA[0];
+						py = field_predA[1];
+					} else {
+						px = field_predC[0];
+						py = field_predC[1];
+					}
+				}
+			}
+		}
+	}
+
+	if (v->field_mode && v->numref)
+		r_y >>= 1;
+	if (v->field_mode && v->cur_field_type && v->ref_field_type[dir] == 0)
+		y_bias = 1;
+	/* store MV using signed modulus of MV range defined in 4.11 */
+	s->mv[dir][n][0] = s->cur_pic.motion_val[dir][xy + v->blocks_off][0] =
+		((px + dmv_x + r_x) & ((r_x << 1) - 1)) - r_x;
+	s->mv[dir][n][1] = s->cur_pic.motion_val[dir][xy + v->blocks_off][1] =
+		((py + dmv_y + r_y - y_bias) & ((r_y << 1) - 1)) - r_y + y_bias;
+	if (mv1) { /* duplicate motion data for 1-MV block */
+		s->cur_pic.motion_val[dir][xy + 1 + v->blocks_off][0] = s->cur_pic.motion_val[dir][xy + v->blocks_off][0];
+		s->cur_pic.motion_val[dir][xy + 1 + v->blocks_off][1] = s->cur_pic.motion_val[dir][xy + v->blocks_off][1];
+		s->cur_pic.motion_val[dir][xy + wrap + v->blocks_off][0] = s->cur_pic.motion_val[dir][xy + v->blocks_off][0];
+		s->cur_pic.motion_val[dir][xy + wrap + v->blocks_off][1] = s->cur_pic.motion_val[dir][xy + v->blocks_off][1];
+		s->cur_pic.motion_val[dir][xy + wrap + 1 + v->blocks_off][0] =
+			s->cur_pic.motion_val[dir][xy + v->blocks_off][0];
+		s->cur_pic.motion_val[dir][xy + wrap + 1 + v->blocks_off][1] =
+			s->cur_pic.motion_val[dir][xy + v->blocks_off][1];
+		v->mv_f[dir][xy + 1 + v->blocks_off] = v->mv_f[dir][xy + v->blocks_off];
+		v->mv_f[dir][xy + wrap + v->blocks_off] = v->mv_f[dir][xy + wrap + 1 + v->blocks_off] =
+			v->mv_f[dir][xy + v->blocks_off];
+	}
+}
+
+/** Predict and set motion vector for interlaced frame picture MBs
+ */
+void ff_vc1_pred_mv_intfr(VC1Context *v, int n, int dmv_x, int dmv_y, int mvn, int r_x, int r_y, int dir) {
+	PictureState *s = &v->s;
+	int xy, wrap, off = 0;
+	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: opposite
+	int total_valid, num_samefield, num_oppfield;
+	int pos_c, pos_b, n_adj;
+
+	wrap = s->b8_stride;
+	xy = s->block_index[n];
+
+	if (s->mb_intra) {
+		s->mv[0][n][0] = s->cur_pic.motion_val[0][xy][0] = 0;
+		s->mv[0][n][1] = s->cur_pic.motion_val[0][xy][1] = 0;
+		s->cur_pic.motion_val[1][xy][0] = 0;
+		s->cur_pic.motion_val[1][xy][1] = 0;
+		if (mvn == 1) { /* duplicate motion data for 1-MV block */
+			s->cur_pic.motion_val[0][xy + 1][0] = 0;
+			s->cur_pic.motion_val[0][xy + 1][1] = 0;
+			s->cur_pic.motion_val[0][xy + wrap][0] = 0;
+			s->cur_pic.motion_val[0][xy + wrap][1] = 0;
+			s->cur_pic.motion_val[0][xy + wrap + 1][0] = 0;
+			s->cur_pic.motion_val[0][xy + wrap + 1][1] = 0;
+			v->luma_mv[s->mb_x][0] = v->luma_mv[s->mb_x][1] = 0;
+			s->cur_pic.motion_val[1][xy + 1][0] = 0;
+			s->cur_pic.motion_val[1][xy + 1][1] = 0;
+			s->cur_pic.motion_val[1][xy + wrap][0] = 0;
+			s->cur_pic.motion_val[1][xy + wrap][1] = 0;
+			s->cur_pic.motion_val[1][xy + wrap + 1][0] = 0;
+			s->cur_pic.motion_val[1][xy + wrap + 1][1] = 0;
+		}
+		return;
+	}
+
+	off = ((n == 0) || (n == 1)) ? 1 : -1;
+	/* predict A */
+	if (s->mb_x || (n == 1) || (n == 3)) {
+		if ((v->blk_mv_type[xy])                                   // current block (MB) has a field MV
+			|| (!v->blk_mv_type[xy] && !v->blk_mv_type[xy - 1])) { // or both have frame MV
+			A[0] = s->cur_pic.motion_val[dir][xy - 1][0];
+			A[1] = s->cur_pic.motion_val[dir][xy - 1][1];
+			a_valid = 1;
+		} else { // current block has frame mv and cand. has field MV (so average)
+			A[0] =
+				(s->cur_pic.motion_val[dir][xy - 1][0] + s->cur_pic.motion_val[dir][xy - 1 + off * wrap][0] + 1) >> 1;
+			A[1] =
+				(s->cur_pic.motion_val[dir][xy - 1][1] + s->cur_pic.motion_val[dir][xy - 1 + off * wrap][1] + 1) >> 1;
+			a_valid = 1;
+		}
+		if (!(n & 1) && v->is_intra[s->mb_x - 1]) {
+			a_valid = 0;
+			A[0] = A[1] = 0;
+		}
+	} else
+		A[0] = A[1] = 0;
+	/* Predict B and C */
+	B[0] = B[1] = C[0] = C[1] = 0;
+	if (n == 0 || n == 1 || v->blk_mv_type[xy]) {
+		if (!s->first_slice_line) {
+			if (!v->is_intra[s->mb_x - s->mb_stride]) {
+				b_valid = 1;
+				n_adj = n | 2;
+				pos_b = s->block_index[n_adj] - 2 * wrap;
+				if (v->blk_mv_type[pos_b] && v->blk_mv_type[xy]) {
+					n_adj = (n & 2) | (n & 1);
+				}
+				B[0] = s->cur_pic.motion_val[dir][s->block_index[n_adj] - 2 * wrap][0];
+				B[1] = s->cur_pic.motion_val[dir][s->block_index[n_adj] - 2 * wrap][1];
+				if (v->blk_mv_type[pos_b] && !v->blk_mv_type[xy]) {
+					B[0] = (B[0] + s->cur_pic.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap][0] + 1) >> 1;
+					B[1] = (B[1] + s->cur_pic.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap][1] + 1) >> 1;
+				}
+			}
+			if (s->mb_width > 1) {
+				if (!v->is_intra[s->mb_x - s->mb_stride + 1]) {
+					c_valid = 1;
+					n_adj = 2;
+					pos_c = s->block_index[2] - 2 * wrap + 2;
+					if (v->blk_mv_type[pos_c] && v->blk_mv_type[xy]) {
+						n_adj = n & 2;
+					}
+					C[0] = s->cur_pic.motion_val[dir][s->block_index[n_adj] - 2 * wrap + 2][0];
+					C[1] = s->cur_pic.motion_val[dir][s->block_index[n_adj] - 2 * wrap + 2][1];
+					if (v->blk_mv_type[pos_c] && !v->blk_mv_type[xy]) {
+						C[0] =
+							(1 + C[0] + (s->cur_pic.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap + 2][0])) >> 1;
+						C[1] =
+							(1 + C[1] + (s->cur_pic.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap + 2][1])) >> 1;
+					}
+					if (s->mb_x == s->mb_width - 1) {
+						if (!v->is_intra[s->mb_x - s->mb_stride - 1]) {
+							c_valid = 1;
+							n_adj = 3;
+							pos_c = s->block_index[3] - 2 * wrap - 2;
+							if (v->blk_mv_type[pos_c] && v->blk_mv_type[xy]) {
+								n_adj = n | 1;
+							}
+							C[0] = s->cur_pic.motion_val[dir][s->block_index[n_adj] - 2 * wrap - 2][0];
+							C[1] = s->cur_pic.motion_val[dir][s->block_index[n_adj] - 2 * wrap - 2][1];
+							if (v->blk_mv_type[pos_c] && !v->blk_mv_type[xy]) {
+								C[0] =
+									(1 + C[0] + s->cur_pic.motion_val[dir][s->block_index[1] - 2 * wrap - 2][0]) >> 1;
+								C[1] =
+									(1 + C[1] + s->cur_pic.motion_val[dir][s->block_index[1] - 2 * wrap - 2][1]) >> 1;
+							}
+						} else
+							c_valid = 0;
+					}
+				}
+			}
+		}
+	} else {
+		pos_b = s->block_index[1];
+		b_valid = 1;
+		B[0] = s->cur_pic.motion_val[dir][pos_b][0];
+		B[1] = s->cur_pic.motion_val[dir][pos_b][1];
+		pos_c = s->block_index[0];
+		c_valid = 1;
+		C[0] = s->cur_pic.motion_val[dir][pos_c][0];
+		C[1] = s->cur_pic.motion_val[dir][pos_c][1];
+	}
+
+	total_valid = a_valid + b_valid + c_valid;
+	// check if predictor A is out of bounds
+	if (!s->mb_x && !(n == 1 || n == 3)) {
+		A[0] = A[1] = 0;
+	}
+	// check if predictor B is out of bounds
+	if ((s->first_slice_line && v->blk_mv_type[xy]) || (s->first_slice_line && !(n & 2))) {
+		B[0] = B[1] = C[0] = C[1] = 0;
+	}
+	if (!v->blk_mv_type[xy]) {
+		if (s->mb_width == 1) {
+			px = B[0];
+			py = B[1];
+		} else {
+			if (total_valid >= 2) {
+				px = mid_pred(A[0], B[0], C[0]);
+				py = mid_pred(A[1], B[1], C[1]);
+			} else if (total_valid) {
+				if (a_valid) {
+					px = A[0];
+					py = A[1];
+				} else if (b_valid) {
+					px = B[0];
+					py = B[1];
+				} else {
+					px = C[0];
+					py = C[1];
+				}
+			}
+		}
+	} else {
+		if (a_valid)
+			field_a = (A[1] & 4) ? 1 : 0;
+		else
+			field_a = 0;
+		if (b_valid)
+			field_b = (B[1] & 4) ? 1 : 0;
+		else
+			field_b = 0;
+		if (c_valid)
+			field_c = (C[1] & 4) ? 1 : 0;
+		else
+			field_c = 0;
+
+		num_oppfield = field_a + field_b + field_c;
+		num_samefield = total_valid - num_oppfield;
+		if (total_valid == 3) {
+			if ((num_samefield == 3) || (num_oppfield == 3)) {
+				px = mid_pred(A[0], B[0], C[0]);
+				py = mid_pred(A[1], B[1], C[1]);
+			} else if (num_samefield >= num_oppfield) {
+				/* take one MV from same field set depending on priority
+				the check for B may not be necessary */
+				px = !field_a ? A[0] : B[0];
+				py = !field_a ? A[1] : B[1];
+			} else {
+				px = field_a ? A[0] : B[0];
+				py = field_a ? A[1] : B[1];
+			}
+		} else if (total_valid == 2) {
+			if (num_samefield >= num_oppfield) {
+				if (!field_a && a_valid) {
+					px = A[0];
+					py = A[1];
+				} else if (!field_b && b_valid) {
+					px = B[0];
+					py = B[1];
+				} else /*if (c_valid)*/ {
+					assert(c_valid);
+					px = C[0];
+					py = C[1];
+				}
+			} else {
+				if (field_a && a_valid) {
+					px = A[0];
+					py = A[1];
+				} else /*if (field_b && b_valid)*/ {
+					assert(field_b && b_valid);
+					px = B[0];
+					py = B[1];
+				}
+			}
+		} else if (total_valid == 1) {
+			px = (a_valid) ? A[0] : ((b_valid) ? B[0] : C[0]);
+			py = (a_valid) ? A[1] : ((b_valid) ? B[1] : C[1]);
+		}
+	}
+
+	/* store MV using signed modulus of MV range defined in 4.11 */
+	s->mv[dir][n][0] = s->cur_pic.motion_val[dir][xy][0] = ((px + dmv_x + r_x) & ((r_x << 1) - 1)) - r_x;
+	s->mv[dir][n][1] = s->cur_pic.motion_val[dir][xy][1] = ((py + dmv_y + r_y) & ((r_y << 1) - 1)) - r_y;
+	if (mvn == 1) { /* duplicate motion data for 1-MV block */
+		s->cur_pic.motion_val[dir][xy + 1][0] = s->cur_pic.motion_val[dir][xy][0];
+		s->cur_pic.motion_val[dir][xy + 1][1] = s->cur_pic.motion_val[dir][xy][1];
+		s->cur_pic.motion_val[dir][xy + wrap][0] = s->cur_pic.motion_val[dir][xy][0];
+		s->cur_pic.motion_val[dir][xy + wrap][1] = s->cur_pic.motion_val[dir][xy][1];
+		s->cur_pic.motion_val[dir][xy + wrap + 1][0] = s->cur_pic.motion_val[dir][xy][0];
+		s->cur_pic.motion_val[dir][xy + wrap + 1][1] = s->cur_pic.motion_val[dir][xy][1];
+	} else if (mvn == 2) { /* duplicate motion data for 2-Field MV block */
+		s->cur_pic.motion_val[dir][xy + 1][0] = s->cur_pic.motion_val[dir][xy][0];
+		s->cur_pic.motion_val[dir][xy + 1][1] = s->cur_pic.motion_val[dir][xy][1];
+		s->mv[dir][n + 1][0] = s->mv[dir][n][0];
+		s->mv[dir][n + 1][1] = s->mv[dir][n][1];
+	}
+}
+
+void ff_vc1_pred_b_mv(VC1Context *v, int dmv_x[2], int dmv_y[2], int direct, int mvtype) {
+	PictureState *s = &v->s;
+	int xy, wrap;
+	int px, py;
+	int sum;
+	int r_x, r_y;
+	const uint8 *is_intra = v->mb_type;
+
+	assert(!v->field_mode);
+
+	r_x = v->range_x;
+	r_y = v->range_y;
+	/* scale MV difference to be quad-pel */
+	if (!s->quarter_sample) {
+		dmv_x[0] *= 2;
+		dmv_y[0] *= 2;
+		dmv_x[1] *= 2;
+		dmv_y[1] *= 2;
+	}
+
+	wrap = s->b8_stride;
+	xy = s->block_index[0];
+
+	if (s->mb_intra) {
+		s->cur_pic.motion_val[0][xy][0] = s->cur_pic.motion_val[0][xy][1] = s->cur_pic.motion_val[1][xy][0] =
+			s->cur_pic.motion_val[1][xy][1] = 0;
+		return;
+	}
+	if (direct && s->next_pic.ptr->field_picture)
+		warning("Mixed frame/field direct mode not supported\n");
+
+	s->mv[0][0][0] = scale_mv(s->next_pic.motion_val[1][xy][0], v->bfraction, 0, s->quarter_sample);
+	s->mv[0][0][1] = scale_mv(s->next_pic.motion_val[1][xy][1], v->bfraction, 0, s->quarter_sample);
+	s->mv[1][0][0] = scale_mv(s->next_pic.motion_val[1][xy][0], v->bfraction, 1, s->quarter_sample);
+	s->mv[1][0][1] = scale_mv(s->next_pic.motion_val[1][xy][1], v->bfraction, 1, s->quarter_sample);
+
+	/* Pullback predicted motion vectors as specified in 8.4.5.4 */
+	s->mv[0][0][0] = av_clip(s->mv[0][0][0], -60 - (s->mb_x << 6), (s->mb_width << 6) - 4 - (s->mb_x << 6));
+	s->mv[0][0][1] = av_clip(s->mv[0][0][1], -60 - (s->mb_y << 6), (s->mb_height << 6) - 4 - (s->mb_y << 6));
+	s->mv[1][0][0] = av_clip(s->mv[1][0][0], -60 - (s->mb_x << 6), (s->mb_width << 6) - 4 - (s->mb_x << 6));
+	s->mv[1][0][1] = av_clip(s->mv[1][0][1], -60 - (s->mb_y << 6), (s->mb_height << 6) - 4 - (s->mb_y << 6));
+	if (direct) {
+		s->cur_pic.motion_val[0][xy][0] = s->mv[0][0][0];
+		s->cur_pic.motion_val[0][xy][1] = s->mv[0][0][1];
+		s->cur_pic.motion_val[1][xy][0] = s->mv[1][0][0];
+		s->cur_pic.motion_val[1][xy][1] = s->mv[1][0][1];
+		return;
+	}
+
+	if ((mvtype == BMV_TYPE_FORWARD) || (mvtype == BMV_TYPE_INTERPOLATED)) {
+		int16 *C = s->cur_pic.motion_val[0][xy - 2];
+		const int16 *A = s->cur_pic.motion_val[0][xy - wrap * 2];
+		int off = (s->mb_x == (s->mb_width - 1)) ? -2 : 2;
+		const int16 *B = s->cur_pic.motion_val[0][xy - wrap * 2 + off];
+
+		if (!s->mb_x)
+			C[0] = C[1] = 0;
+		if (!s->first_slice_line) { // predictor A is not out of bounds
+			if (s->mb_width == 1) {
+				px = A[0];
+				py = A[1];
+			} else {
+				px = mid_pred(A[0], B[0], C[0]);
+				py = mid_pred(A[1], B[1], C[1]);
+			}
+		} else if (s->mb_x) { // predictor C is not out of bounds
+			px = C[0];
+			py = C[1];
+		} else {
+			px = py = 0;
+		}
+		/* Pullback MV as specified in 8.3.5.3.4 */
+		{
+			int qx, qy, X, Y;
+			int sh = v->profile < PROFILE_ADVANCED ? 5 : 6;
+			int MV = 4 - (1 << sh);
+			qx = (s->mb_x << sh);
+			qy = (s->mb_y << sh);
+			X = (s->mb_width << sh) - 4;
+			Y = (s->mb_height << sh) - 4;
+			if (qx + px < MV)
+				px = MV - qx;
+			if (qy + py < MV)
+				py = MV - qy;
+			if (qx + px > X)
+				px = X - qx;
+			if (qy + py > Y)
+				py = Y - qy;
+		}
+		/* Calculate hybrid prediction as specified in 8.3.5.3.5 */
+		if (0 && !s->first_slice_line && s->mb_x) {
+			if (is_intra[xy - wrap])
+				sum = ABS(px) + ABS(py);
+			else
+				sum = ABS(px - A[0]) + ABS(py - A[1]);
+			if (sum > 32) {
+				if (get_bits1(&v->gb)) {
+					px = A[0];
+					py = A[1];
+				} else {
+					px = C[0];
+					py = C[1];
+				}
+			} else {
+				if (is_intra[xy - 2])
+					sum = ABS(px) + ABS(py);
+				else
+					sum = ABS(px - C[0]) + ABS(py - C[1]);
+				if (sum > 32) {
+					if (get_bits1(&v->gb)) {
+						px = A[0];
+						py = A[1];
+					} else {
+						px = C[0];
+						py = C[1];
+					}
+				}
+			}
+		}
+		/* store MV using signed modulus of MV range defined in 4.11 */
+		s->mv[0][0][0] = ((px + dmv_x[0] + r_x) & ((r_x << 1) - 1)) - r_x;
+		s->mv[0][0][1] = ((py + dmv_y[0] + r_y) & ((r_y << 1) - 1)) - r_y;
+	}
+	if ((mvtype == BMV_TYPE_BACKWARD) || (mvtype == BMV_TYPE_INTERPOLATED)) {
+		int16 *C = s->cur_pic.motion_val[1][xy - 2];
+		const int16 *A = s->cur_pic.motion_val[1][xy - wrap * 2];
+		int off = (s->mb_x == (s->mb_width - 1)) ? -2 : 2;
+		const int16 *B = s->cur_pic.motion_val[1][xy - wrap * 2 + off];
+
+		if (!s->mb_x)
+			C[0] = C[1] = 0;
+		if (!s->first_slice_line) { // predictor A is not out of bounds
+			if (s->mb_width == 1) {
+				px = A[0];
+				py = A[1];
+			} else {
+				px = mid_pred(A[0], B[0], C[0]);
+				py = mid_pred(A[1], B[1], C[1]);
+			}
+		} else if (s->mb_x) { // predictor C is not out of bounds
+			px = C[0];
+			py = C[1];
+		} else {
+			px = py = 0;
+		}
+		/* Pullback MV as specified in 8.3.5.3.4 */
+		{
+			int qx, qy, X, Y;
+			int sh = v->profile < PROFILE_ADVANCED ? 5 : 6;
+			int MV = 4 - (1 << sh);
+			qx = (s->mb_x << sh);
+			qy = (s->mb_y << sh);
+			X = (s->mb_width << sh) - 4;
+			Y = (s->mb_height << sh) - 4;
+			if (qx + px < MV)
+				px = MV - qx;
+			if (qy + py < MV)
+				py = MV - qy;
+			if (qx + px > X)
+				px = X - qx;
+			if (qy + py > Y)
+				py = Y - qy;
+		}
+		/* Calculate hybrid prediction as specified in 8.3.5.3.5 */
+		if (0 && !s->first_slice_line && s->mb_x) {
+			if (is_intra[xy - wrap])
+				sum = ABS(px) + ABS(py);
+			else
+				sum = ABS(px - A[0]) + ABS(py - A[1]);
+			if (sum > 32) {
+				if (get_bits1(&v->gb)) {
+					px = A[0];
+					py = A[1];
+				} else {
+					px = C[0];
+					py = C[1];
+				}
+			} else {
+				if (is_intra[xy - 2])
+					sum = ABS(px) + ABS(py);
+				else
+					sum = ABS(px - C[0]) + ABS(py - C[1]);
+				if (sum > 32) {
+					if (get_bits1(&v->gb)) {
+						px = A[0];
+						py = A[1];
+					} else {
+						px = C[0];
+						py = C[1];
+					}
+				}
+			}
+		}
+		/* store MV using signed modulus of MV range defined in 4.11 */
+
+		s->mv[1][0][0] = ((px + dmv_x[1] + r_x) & ((r_x << 1) - 1)) - r_x;
+		s->mv[1][0][1] = ((py + dmv_y[1] + r_y) & ((r_y << 1) - 1)) - r_y;
+	}
+	s->cur_pic.motion_val[0][xy][0] = s->mv[0][0][0];
+	s->cur_pic.motion_val[0][xy][1] = s->mv[0][0][1];
+	s->cur_pic.motion_val[1][xy][0] = s->mv[1][0][0];
+	s->cur_pic.motion_val[1][xy][1] = s->mv[1][0][1];
+}
+
+void ff_vc1_pred_b_mv_intfi(VC1Context *v, int n, int *dmv_x, int *dmv_y, int mv1, int *pred_flag) {
+	int dir = (v->bmvtype == BMV_TYPE_BACKWARD) ? 1 : 0;
+	PictureState *s = &v->s;
+	int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
+
+	if (v->bmvtype == BMV_TYPE_DIRECT) {
+		int total_opp, k, f;
+		if (s->next_pic.mb_type[mb_pos + v->mb_off] != MB_TYPE_INTRA) {
+			s->mv[0][0][0] = scale_mv(s->next_pic.motion_val[1][s->block_index[0] + v->blocks_off][0], v->bfraction, 0,
+									  s->quarter_sample);
+			s->mv[0][0][1] = scale_mv(s->next_pic.motion_val[1][s->block_index[0] + v->blocks_off][1], v->bfraction, 0,
+									  s->quarter_sample);
+			s->mv[1][0][0] = scale_mv(s->next_pic.motion_val[1][s->block_index[0] + v->blocks_off][0], v->bfraction, 1,
+									  s->quarter_sample);
+			s->mv[1][0][1] = scale_mv(s->next_pic.motion_val[1][s->block_index[0] + v->blocks_off][1], v->bfraction, 1,
+									  s->quarter_sample);
+
+			total_opp = v->mv_f_next[0][s->block_index[0] + v->blocks_off] +
+						v->mv_f_next[0][s->block_index[1] + v->blocks_off] +
+						v->mv_f_next[0][s->block_index[2] + v->blocks_off] +
+						v->mv_f_next[0][s->block_index[3] + v->blocks_off];
+			f = (total_opp > 2) ? 1 : 0;
+		} else {
+			s->mv[0][0][0] = s->mv[0][0][1] = 0;
+			s->mv[1][0][0] = s->mv[1][0][1] = 0;
+			f = 0;
+		}
+		v->ref_field_type[0] = v->ref_field_type[1] = v->cur_field_type ^ f;
+		for (k = 0; k < 4; k++) {
+			s->cur_pic.motion_val[0][s->block_index[k] + v->blocks_off][0] = s->mv[0][0][0];
+			s->cur_pic.motion_val[0][s->block_index[k] + v->blocks_off][1] = s->mv[0][0][1];
+			s->cur_pic.motion_val[1][s->block_index[k] + v->blocks_off][0] = s->mv[1][0][0];
+			s->cur_pic.motion_val[1][s->block_index[k] + v->blocks_off][1] = s->mv[1][0][1];
+			v->mv_f[0][s->block_index[k] + v->blocks_off] = f;
+			v->mv_f[1][s->block_index[k] + v->blocks_off] = f;
+		}
+		return;
+	}
+	if (v->bmvtype == BMV_TYPE_INTERPOLATED) {
+		ff_vc1_pred_mv(v, 0, dmv_x[0], dmv_y[0], 1, v->range_x, v->range_y, v->mb_type, pred_flag[0], 0);
+		ff_vc1_pred_mv(v, 0, dmv_x[1], dmv_y[1], 1, v->range_x, v->range_y, v->mb_type, pred_flag[1], 1);
+		return;
+	}
+	if (dir) { // backward
+		ff_vc1_pred_mv(v, n, dmv_x[1], dmv_y[1], mv1, v->range_x, v->range_y, v->mb_type, pred_flag[1], 1);
+		if (n == 3 || mv1) {
+			ff_vc1_pred_mv(v, 0, dmv_x[0], dmv_y[0], 1, v->range_x, v->range_y, v->mb_type, 0, 0);
+		}
+	} else { // forward
+		ff_vc1_pred_mv(v, n, dmv_x[0], dmv_y[0], mv1, v->range_x, v->range_y, v->mb_type, pred_flag[0], 0);
+		if (n == 3 || mv1) {
+			ff_vc1_pred_mv(v, 0, dmv_x[1], dmv_y[1], 1, v->range_x, v->range_y, v->mb_type, 0, 1);
+		}
+	}
+}
+
+static inline void vc1_h_overlap_filter(VC1Context *v, int16 (*left_block)[64], int16 (*right_block)[64],
+										int left_fieldtx, int right_fieldtx, int block_num) {
+	switch (block_num) {
+	case 0:
+		v->vc1dsp.vc1_h_s_overlap(
+			left_block[2], right_block[0], left_fieldtx ^ right_fieldtx ? 16 - 8 * left_fieldtx : 8,
+			left_fieldtx ^ right_fieldtx ? 16 - 8 * right_fieldtx : 8, left_fieldtx || right_fieldtx ? 0 : 1);
+		break;
+
+	case 1:
+		v->vc1dsp.vc1_h_s_overlap(right_block[0], right_block[2], 8, 8, right_fieldtx ? 0 : 1);
+		break;
+
+	case 2:
+		v->vc1dsp.vc1_h_s_overlap(!left_fieldtx && right_fieldtx ? left_block[2] + 8 : left_block[3],
+								  left_fieldtx && !right_fieldtx ? right_block[0] + 8 : right_block[1],
+								  left_fieldtx ^ right_fieldtx ? 16 - 8 * left_fieldtx : 8,
+								  left_fieldtx ^ right_fieldtx ? 16 - 8 * right_fieldtx : 8,
+								  left_fieldtx || right_fieldtx ? 2 : 1);
+		break;
+
+	case 3:
+		v->vc1dsp.vc1_h_s_overlap(right_block[1], right_block[3], 8, 8, right_fieldtx ? 2 : 1);
+		break;
+
+	case 4:
+	case 5:
+		v->vc1dsp.vc1_h_s_overlap(left_block[block_num], right_block[block_num], 8, 8, 1);
+		break;
+	}
+}
+
+static inline void vc1_v_overlap_filter(VC1Context *v, int16 (*top_block)[64], int16 (*bottom_block)[64],
+										int block_num) {
+	switch (block_num) {
+	case 0:
+		v->vc1dsp.vc1_v_s_overlap(top_block[1], bottom_block[0]);
+		break;
+
+	case 1:
+		v->vc1dsp.vc1_v_s_overlap(top_block[3], bottom_block[2]);
+		break;
+
+	case 2:
+		v->vc1dsp.vc1_v_s_overlap(bottom_block[0], bottom_block[1]);
+		break;
+
+	case 3:
+		v->vc1dsp.vc1_v_s_overlap(bottom_block[2], bottom_block[3]);
+		break;
+
+	case 4:
+	case 5:
+		v->vc1dsp.vc1_v_s_overlap(top_block[block_num], bottom_block[block_num]);
+		break;
+	}
+}
+
+void ff_vc1_i_overlap_filter(VC1Context *v) {
+	PictureState *s = &v->s;
+	int16(*topleft_blk)[64], (*top_blk)[64], (*left_blk)[64], (*cur_blk)[64];
+	int block_count = CONFIG_GRAY && (s->avctx->flags & AV_CODEC_FLAG_GRAY) ? 4 : 6;
+	int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
+	int i;
+
+	topleft_blk = v->block[v->topleft_blk_idx];
+	top_blk = v->block[v->top_blk_idx];
+	left_blk = v->block[v->left_blk_idx];
+	cur_blk = v->block[v->cur_blk_idx];
+
+	/* Within a MB, the horizontal overlap always runs before the vertical.
+	 * To accomplish that, we run the H on the left and internal vertical
+	 * borders of the currently decoded MB. Then, we wait for the next overlap
+	 * iteration to do H overlap on the right edge of this MB, before moving
+	 * over and running the V overlap on the top and internal horizontal
+	 * borders. Therefore, the H overlap trails by one MB col and the
+	 * V overlap trails by one MB row. This is reflected in the time at which
+	 * we run the put_pixels loop, i.e. delayed by one row and one column. */
+	for (i = 0; i < block_count; i++) {
+		if (s->mb_x == 0 && (i & 5) != 1)
+			continue;
+
+		if (v->pq >= 9 || (v->profile == PROFILE_ADVANCED &&
+						   (v->condover == CONDOVER_ALL ||
+							(v->over_flags_plane[mb_pos] && ((i & 5) == 1 || v->over_flags_plane[mb_pos - 1])))))
+			vc1_h_overlap_filter(v, s->mb_x ? left_blk : cur_blk, cur_blk,
+								 v->fcm == ILACE_FRAME && s->mb_x && v->fieldtx_plane[mb_pos - 1],
+								 v->fcm == ILACE_FRAME && v->fieldtx_plane[mb_pos], i);
+	}
+
+	if (v->fcm != ILACE_FRAME)
+		for (i = 0; i < block_count; i++) {
+			if (s->first_slice_line && !(i & 2))
+				continue;
+
+			if (s->mb_x &&
+				(v->pq >= 9 ||
+				 (v->profile == PROFILE_ADVANCED &&
+				  (v->condover == CONDOVER_ALL ||
+				   (v->over_flags_plane[mb_pos - 1] && ((i & 2) || v->over_flags_plane[mb_pos - 1 - s->mb_stride]))))))
+				vc1_v_overlap_filter(v, s->first_slice_line ? left_blk : topleft_blk, left_blk, i);
+			if (s->mb_x == s->mb_width - 1 &&
+				(v->pq >= 9 ||
+				 (v->profile == PROFILE_ADVANCED &&
+				  (v->condover == CONDOVER_ALL ||
+				   (v->over_flags_plane[mb_pos] && ((i & 2) || v->over_flags_plane[mb_pos - s->mb_stride]))))))
+				vc1_v_overlap_filter(v, s->first_slice_line ? cur_blk : top_blk, cur_blk, i);
+		}
+}
+
+void ff_vc1_p_overlap_filter(VC1Context *v) {
+	PictureState *s = &v->s;
+	int16(*topleft_blk)[64], (*top_blk)[64], (*left_blk)[64], (*cur_blk)[64];
+	int block_count = CONFIG_GRAY && (s->avctx->flags & AV_CODEC_FLAG_GRAY) ? 4 : 6;
+	int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
+	int i;
+
+	topleft_blk = v->block[v->topleft_blk_idx];
+	top_blk = v->block[v->top_blk_idx];
+	left_blk = v->block[v->left_blk_idx];
+	cur_blk = v->block[v->cur_blk_idx];
+
+	for (i = 0; i < block_count; i++) {
+		if (s->mb_x == 0 && (i & 5) != 1)
+			continue;
+
+		if (v->mb_type[s->block_index[i]] && v->mb_type[s->block_index[i] - 1])
+			vc1_h_overlap_filter(v, s->mb_x ? left_blk : cur_blk, cur_blk,
+								 v->fcm == ILACE_FRAME && s->mb_x && v->fieldtx_plane[mb_pos - 1],
+								 v->fcm == ILACE_FRAME && v->fieldtx_plane[mb_pos], i);
+	}
+
+	if (v->fcm != ILACE_FRAME)
+		for (i = 0; i < block_count; i++) {
+			if (s->first_slice_line && !(i & 2))
+				continue;
+
+			if (s->mb_x && v->mb_type[s->block_index[i] - 2 + (i > 3)] &&
+				v->mb_type[s->block_index[i] - s->block_wrap[i] - 2 + (i > 3)])
+				vc1_v_overlap_filter(v, s->first_slice_line ? left_blk : topleft_blk, left_blk, i);
+			if (s->mb_x == s->mb_width - 1)
+				if (v->mb_type[s->block_index[i]] && v->mb_type[s->block_index[i] - s->block_wrap[i]])
+					vc1_v_overlap_filter(v, s->first_slice_line ? cur_blk : top_blk, cur_blk, i);
+		}
+}
+
+#define LEFT_EDGE (1 << 0)
+#define RIGHT_EDGE (1 << 1)
+#define TOP_EDGE (1 << 2)
+#define BOTTOM_EDGE (1 << 3)
+
+static inline void vc1_i_h_loop_filter(VC1Context *v, uint8 *dest, uint32 flags, int block_num) {
+	PictureState *s = &v->s;
+	int pq = v->pq;
+	uint8 *dst;
+
+	if (block_num & 2)
+		return;
+
+	if (!(flags & LEFT_EDGE) || (block_num & 5) == 1) {
+		if (block_num > 3)
+			dst = dest;
+		else
+			dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
+
+		if (v->fcm == ILACE_FRAME)
+			if (block_num > 3) {
+				v->vc1dsp.vc1_h_loop_filter4(dst, 2 * s->uvlinesize, pq);
+				v->vc1dsp.vc1_h_loop_filter4(dst + s->uvlinesize, 2 * s->uvlinesize, pq);
+			} else {
+				v->vc1dsp.vc1_h_loop_filter8(dst, 2 * s->linesize, pq);
+				v->vc1dsp.vc1_h_loop_filter8(dst + s->linesize, 2 * s->linesize, pq);
+			}
+		else if (block_num > 3)
+			v->vc1dsp.vc1_h_loop_filter8(dst, s->uvlinesize, pq);
+		else
+			v->vc1dsp.vc1_h_loop_filter16(dst, s->linesize, pq);
+	}
+}
+
+static inline void vc1_i_v_loop_filter(VC1Context *v, uint8 *dest, uint32 flags, uint8 fieldtx, int block_num) {
+	PictureState *s = &v->s;
+	int pq = v->pq;
+	uint8 *dst;
+
+	if ((block_num & 5) == 1)
+		return;
+
+	if (!(flags & TOP_EDGE) || block_num & 2) {
+		if (block_num > 3)
+			dst = dest;
+		else
+			dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
+
+		if (v->fcm == ILACE_FRAME) {
+			if (block_num > 3) {
+				v->vc1dsp.vc1_v_loop_filter8(dst, 2 * s->uvlinesize, pq);
+				v->vc1dsp.vc1_v_loop_filter8(dst + s->uvlinesize, 2 * s->uvlinesize, pq);
+			} else if (block_num < 2 || !fieldtx) {
+				v->vc1dsp.vc1_v_loop_filter16(dst, 2 * s->linesize, pq);
+				v->vc1dsp.vc1_v_loop_filter16(dst + s->linesize, 2 * s->linesize, pq);
+			}
+		} else if (block_num > 3)
+			v->vc1dsp.vc1_v_loop_filter8(dst, s->uvlinesize, pq);
+		else
+			v->vc1dsp.vc1_v_loop_filter16(dst, s->linesize, pq);
+	}
+}
+
+void ff_vc1_i_loop_filter(VC1Context *v) {
+	PictureState *s = &v->s;
+	int block_count = CONFIG_GRAY && (s->avctx->flags & AV_CODEC_FLAG_GRAY) ? 4 : 6;
+	int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
+	uint8 *dest, fieldtx;
+	uint32 flags = 0;
+	int i;
+
+	/* Within a MB, the vertical loop filter always runs before the horizontal.
+	 * To accomplish that, we run the V loop filter on top and internal
+	 * horizontal borders of the last overlap filtered MB. Then, we wait for
+	 * the loop filter iteration on the next row to do V loop filter on the
+	 * bottom edge of this MB, before moving over and running the H loop
+	 * filter on the left and internal vertical borders. Therefore, the loop
+	 * filter trails by one row and one column relative to the overlap filter
+	 * and two rows and two columns relative to the decoding loop. */
+	if (!s->first_slice_line) {
+		dest = s->dest[0] - 16 * s->linesize - 16;
+		flags = s->mb_y == s->start_mb_y + 1 ? TOP_EDGE : 0;
+		if (s->mb_x) {
+			fieldtx = v->fieldtx_plane[mb_pos - s->mb_stride - 1];
+			for (i = 0; i < block_count; i++)
+				vc1_i_v_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 8 : dest, flags, fieldtx, i);
+		}
+		if (s->mb_x == v->end_mb_x - 1) {
+			dest += 16;
+			fieldtx = v->fieldtx_plane[mb_pos - s->mb_stride];
+			for (i = 0; i < block_count; i++)
+				vc1_i_v_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize : dest, flags, fieldtx, i);
+		}
+	}
+	if (s->mb_y == s->end_mb_y - 1) {
+		dest = s->dest[0] - 16;
+		flags = s->first_slice_line ? TOP_EDGE | BOTTOM_EDGE : BOTTOM_EDGE;
+		if (s->mb_x) {
+			fieldtx = v->fieldtx_plane[mb_pos - 1];
+			for (i = 0; i < block_count; i++)
+				vc1_i_v_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 : dest, flags, fieldtx, i);
+		}
+		if (s->mb_x == v->end_mb_x - 1) {
+			dest += 16;
+			fieldtx = v->fieldtx_plane[mb_pos];
+			for (i = 0; i < block_count; i++)
+				vc1_i_v_loop_filter(v, i > 3 ? s->dest[i - 3] : dest, flags, fieldtx, i);
+		}
+	}
+
+	if (s->mb_y >= s->start_mb_y + 2) {
+		dest = s->dest[0] - 32 * s->linesize - 16;
+		if (s->mb_x) {
+			flags = s->mb_x == 1 ? LEFT_EDGE : 0;
+			for (i = 0; i < block_count; i++)
+				vc1_i_h_loop_filter(v, i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize - 8 : dest, flags, i);
+		}
+		if (s->mb_x == v->end_mb_x - 1) {
+			dest += 16;
+			flags = s->mb_x == 0 ? LEFT_EDGE | RIGHT_EDGE : RIGHT_EDGE;
+			for (i = 0; i < block_count; i++)
+				vc1_i_h_loop_filter(v, i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize : dest, flags, i);
+		}
+	}
+	if (s->mb_y == s->end_mb_y - 1) {
+		if (s->mb_y >= s->start_mb_y + 1) {
+			dest = s->dest[0] - 16 * s->linesize - 16;
+			if (s->mb_x) {
+				flags = s->mb_x == 1 ? LEFT_EDGE : 0;
+				for (i = 0; i < block_count; i++)
+					vc1_i_h_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 8 : dest, flags, i);
+			}
+			if (s->mb_x == v->end_mb_x - 1) {
+				flags = s->mb_x == 0 ? LEFT_EDGE | RIGHT_EDGE : RIGHT_EDGE;
+				dest += 16;
+				for (i = 0; i < block_count; i++)
+					vc1_i_h_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize : dest, flags, i);
+			}
+		}
+		dest = s->dest[0] - 16;
+		if (s->mb_x) {
+			flags = s->mb_x == 1 ? LEFT_EDGE : 0;
+			for (i = 0; i < block_count; i++)
+				vc1_i_h_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 : dest, flags, i);
+		}
+		if (s->mb_x == v->end_mb_x - 1) {
+			dest += 16;
+			flags = s->mb_x == 0 ? LEFT_EDGE | RIGHT_EDGE : RIGHT_EDGE;
+			for (i = 0; i < block_count; i++)
+				vc1_i_h_loop_filter(v, i > 3 ? s->dest[i - 3] : dest, flags, i);
+		}
+	}
+}
+
+static inline void vc1_p_h_loop_filter(VC1Context *v, uint8 *dest, uint32 *cbp, uint8 *is_intra, int16 (*mv)[2],
+									   uint8 *mv_f, int *ttblk, uint32 flags, int block_num) {
+	PictureState *s = &v->s;
+	int pq = v->pq;
+	uint32 left_cbp = cbp[0] >> (block_num * 4), right_cbp;
+	uint8 left_is_intra, right_is_intra;
+	int tt;
+	int idx, linesize = block_num > 3 ? s->uvlinesize : s->linesize;
+	uint8 *dst;
+
+	if (block_num > 3)
+		dst = dest;
+	else
+		dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
+
+	if (!(flags & RIGHT_EDGE) || !(block_num & 5)) {
+		left_is_intra = is_intra[0] & (1 << block_num);
+
+		if (block_num > 3) {
+			right_is_intra = is_intra[1] & (1 << block_num);
+			right_cbp = cbp[1] >> (block_num * 4);
+		} else if (block_num & 1) {
+			right_is_intra = is_intra[1] & (1 << block_num - 1);
+			right_cbp = cbp[1] >> ((block_num - 1) * 4);
+		} else {
+			right_is_intra = is_intra[0] & (1 << block_num + 1);
+			right_cbp = cbp[0] >> ((block_num + 1) * 4);
+		}
+
+		if (left_is_intra || right_is_intra || mv[0][0] != mv[1][0] || mv[0][1] != mv[1][1] ||
+			(v->fcm == ILACE_FIELD && mv_f[0] != mv_f[1]))
+			v->vc1dsp.vc1_h_loop_filter8(dst + 8, linesize, pq);
+		else {
+			idx = (left_cbp | (right_cbp >> 1)) & 5;
+			if (idx & 1)
+				v->vc1dsp.vc1_h_loop_filter4(dst + 4 * linesize + 8, linesize, pq);
+			if (idx & 4)
+				v->vc1dsp.vc1_h_loop_filter4(dst + 8, linesize, pq);
+		}
+	}
+
+	tt = ttblk[0] >> (block_num * 4) & 0xf;
+	if (tt == TT_4X4 || tt == TT_4X8) {
+		if (left_cbp & 3)
+			v->vc1dsp.vc1_h_loop_filter4(dst + 4 * linesize + 4, linesize, pq);
+		if (left_cbp & 12)
+			v->vc1dsp.vc1_h_loop_filter4(dst + 4, linesize, pq);
+	}
+}
+
+static inline void vc1_p_v_loop_filter(VC1Context *v, uint8 *dest, const uint32 *cbp, const uint8 *is_intra,
+									   int16 (*mv)[2], const uint8 *mv_f, const int *ttblk, uint32 flags,
+									   int block_num) {
+	PictureState *s = &v->s;
+	int pq = v->pq;
+	uint32 top_cbp = cbp[0] >> (block_num * 4), bottom_cbp;
+	uint8 top_is_intra, bottom_is_intra;
+	int tt;
+	int idx, linesize = block_num > 3 ? s->uvlinesize : s->linesize;
+	uint8 *dst;
+
+	if (block_num > 3)
+		dst = dest;
+	else
+		dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
+
+	if (!(flags & BOTTOM_EDGE) || block_num < 2) {
+		top_is_intra = is_intra[0] & (1 << block_num);
+
+		if (block_num > 3) {
+			bottom_is_intra = is_intra[s->mb_stride] & (1 << block_num);
+			bottom_cbp = cbp[s->mb_stride] >> (block_num * 4);
+		} else if (block_num < 2) {
+			bottom_is_intra = is_intra[0] & (1 << block_num + 2);
+			bottom_cbp = cbp[0] >> ((block_num + 2) * 4);
+		} else {
+			bottom_is_intra = is_intra[s->mb_stride] & (1 << block_num - 2);
+			bottom_cbp = cbp[s->mb_stride] >> ((block_num - 2) * 4);
+		}
+
+		if (top_is_intra || bottom_is_intra || mv[0][0] != mv[block_num > 3 ? s->mb_stride : s->b8_stride][0] ||
+			mv[0][1] != mv[block_num > 3 ? s->mb_stride : s->b8_stride][1] ||
+			(v->fcm == ILACE_FIELD && mv_f[0] != mv_f[block_num > 3 ? s->mb_stride : s->b8_stride]))
+			v->vc1dsp.vc1_v_loop_filter8(dst + 8 * linesize, linesize, pq);
+		else {
+			idx = (top_cbp | (bottom_cbp >> 2)) & 3;
+			if (idx & 1)
+				v->vc1dsp.vc1_v_loop_filter4(dst + 8 * linesize + 4, linesize, pq);
+			if (idx & 2)
+				v->vc1dsp.vc1_v_loop_filter4(dst + 8 * linesize, linesize, pq);
+		}
+	}
+
+	tt = ttblk[0] >> (block_num * 4) & 0xf;
+	if (tt == TT_4X4 || tt == TT_8X4) {
+		if (top_cbp & 5)
+			v->vc1dsp.vc1_v_loop_filter4(dst + 4 * linesize + 4, linesize, pq);
+		if (top_cbp & 10)
+			v->vc1dsp.vc1_v_loop_filter4(dst + 4 * linesize, linesize, pq);
+	}
+}
+
+void ff_vc1_p_loop_filter(VC1Context *v) {
+	PictureState *s = &v->s;
+	int block_count = CONFIG_GRAY && (s->avctx->flags & AV_CODEC_FLAG_GRAY) ? 4 : 6;
+	uint8 *dest;
+	uint32 *cbp;
+	uint8 *is_intra;
+	int16(*uvmv)[2];
+	int *ttblk;
+	uint32 flags;
+	int i;
+
+	/* Within a MB, the vertical loop filter always runs before the horizontal.
+	 * To accomplish that, we run the V loop filter on all applicable
+	 * horizontal borders of the MB above the last overlap filtered MB. Then,
+	 * we wait for the next loop filter iteration to do H loop filter on all
+	 * applicable vertical borders of this MB. Therefore, the loop filter
+	 * trails by one row and one column relative to the overlap filter and two
+	 * rows and two columns relative to the decoding loop. */
+	if (s->mb_y >= s->start_mb_y + 2) {
+		if (s->mb_x) {
+			dest = s->dest[0] - 32 * s->linesize - 16;
+			cbp = &v->cbp[s->mb_x - 2 * s->mb_stride - 1];
+			is_intra = &v->is_intra[s->mb_x - 2 * s->mb_stride - 1];
+			uvmv = &v->luma_mv[s->mb_x - 2 * s->mb_stride - 1];
+			ttblk = &v->ttblk[s->mb_x - 2 * s->mb_stride - 1];
+			flags = s->mb_y == s->start_mb_y + 2 ? TOP_EDGE : 0;
+			for (i = 0; i < block_count; i++)
+				vc1_p_v_loop_filter(
+					v, i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize - 8 : dest, cbp, is_intra,
+					i > 3 ? uvmv : &s->cur_pic.motion_val[0][s->block_index[i] - 4 * s->b8_stride - 2 + v->blocks_off],
+					i > 3 ? &v->mv_f[0][s->block_index[i] - 2 * s->mb_stride - 1 + v->mb_off]
+						  : &v->mv_f[0][s->block_index[i] - 4 * s->b8_stride - 2 + v->blocks_off],
+					ttblk, flags, i);
+		}
+		if (s->mb_x == s->mb_width - 1) {
+			dest = s->dest[0] - 32 * s->linesize;
+			cbp = &v->cbp[s->mb_x - 2 * s->mb_stride];
+			is_intra = &v->is_intra[s->mb_x - 2 * s->mb_stride];
+			uvmv = &v->luma_mv[s->mb_x - 2 * s->mb_stride];
+			ttblk = &v->ttblk[s->mb_x - 2 * s->mb_stride];
+			flags = s->mb_y == s->start_mb_y + 2 ? TOP_EDGE : 0;
+			for (i = 0; i < block_count; i++)
+				vc1_p_v_loop_filter(
+					v, i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize : dest, cbp, is_intra,
+					i > 3 ? uvmv : &s->cur_pic.motion_val[0][s->block_index[i] - 4 * s->b8_stride + v->blocks_off],
+					i > 3 ? &v->mv_f[0][s->block_index[i] - 2 * s->mb_stride + v->mb_off]
+						  : &v->mv_f[0][s->block_index[i] - 4 * s->b8_stride + v->blocks_off],
+					ttblk, flags, i);
+		}
+	}
+	if (s->mb_y == s->end_mb_y - 1) {
+		if (s->mb_x) {
+			if (s->mb_y >= s->start_mb_y + 1) {
+				dest = s->dest[0] - 16 * s->linesize - 16;
+				cbp = &v->cbp[s->mb_x - s->mb_stride - 1];
+				is_intra = &v->is_intra[s->mb_x - s->mb_stride - 1];
+				uvmv = &v->luma_mv[s->mb_x - s->mb_stride - 1];
+				ttblk = &v->ttblk[s->mb_x - s->mb_stride - 1];
+				flags = s->mb_y == s->start_mb_y + 1 ? TOP_EDGE : 0;
+				for (i = 0; i < block_count; i++)
+					vc1_p_v_loop_filter(
+						v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 8 : dest, cbp, is_intra,
+						i > 3 ? uvmv
+							  : &s->cur_pic.motion_val[0][s->block_index[i] - 2 * s->b8_stride - 2 + v->blocks_off],
+						i > 3 ? &v->mv_f[0][s->block_index[i] - s->mb_stride - 1 + v->mb_off]
+							  : &v->mv_f[0][s->block_index[i] - 2 * s->b8_stride - 2 + v->blocks_off],
+						ttblk, flags, i);
+			}
+			dest = s->dest[0] - 16;
+			cbp = &v->cbp[s->mb_x - 1];
+			is_intra = &v->is_intra[s->mb_x - 1];
+			uvmv = &v->luma_mv[s->mb_x - 1];
+			ttblk = &v->ttblk[s->mb_x - 1];
+			flags = s->mb_y == s->start_mb_y ? TOP_EDGE | BOTTOM_EDGE : BOTTOM_EDGE;
+			for (i = 0; i < block_count; i++)
+				vc1_p_v_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 : dest, cbp, is_intra,
+									i > 3 ? uvmv : &s->cur_pic.motion_val[0][s->block_index[i] - 2 + v->blocks_off],
+									i > 3 ? &v->mv_f[0][s->block_index[i] - 1 + v->mb_off]
+										  : &v->mv_f[0][s->block_index[i] - 2 + v->blocks_off],
+									ttblk, flags, i);
+		}
+		if (s->mb_x == s->mb_width - 1) {
+			if (s->mb_y >= s->start_mb_y + 1) {
+				dest = s->dest[0] - 16 * s->linesize;
+				cbp = &v->cbp[s->mb_x - s->mb_stride];
+				is_intra = &v->is_intra[s->mb_x - s->mb_stride];
+				uvmv = &v->luma_mv[s->mb_x - s->mb_stride];
+				ttblk = &v->ttblk[s->mb_x - s->mb_stride];
+				flags = s->mb_y == s->start_mb_y + 1 ? TOP_EDGE : 0;
+				for (i = 0; i < block_count; i++)
+					vc1_p_v_loop_filter(
+						v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize : dest, cbp, is_intra,
+						i > 3 ? uvmv : &s->cur_pic.motion_val[0][s->block_index[i] - 2 * s->b8_stride + v->blocks_off],
+						i > 3 ? &v->mv_f[0][s->block_index[i] - s->mb_stride + v->mb_off]
+							  : &v->mv_f[0][s->block_index[i] - 2 * s->b8_stride + v->blocks_off],
+						ttblk, flags, i);
+			}
+			dest = s->dest[0];
+			cbp = &v->cbp[s->mb_x];
+			is_intra = &v->is_intra[s->mb_x];
+			uvmv = &v->luma_mv[s->mb_x];
+			ttblk = &v->ttblk[s->mb_x];
+			flags = s->mb_y == s->start_mb_y ? TOP_EDGE | BOTTOM_EDGE : BOTTOM_EDGE;
+			for (i = 0; i < block_count; i++)
+				vc1_p_v_loop_filter(v, i > 3 ? s->dest[i - 3] : dest, cbp, is_intra,
+									i > 3 ? uvmv : &s->cur_pic.motion_val[0][s->block_index[i] + v->blocks_off],
+									i > 3 ? &v->mv_f[0][s->block_index[i] + v->mb_off]
+										  : &v->mv_f[0][s->block_index[i] + v->blocks_off],
+									ttblk, flags, i);
+		}
+	}
+
+	if (s->mb_y >= s->start_mb_y + 2) {
+		if (s->mb_x >= 2) {
+			dest = s->dest[0] - 32 * s->linesize - 32;
+			cbp = &v->cbp[s->mb_x - 2 * s->mb_stride - 2];
+			is_intra = &v->is_intra[s->mb_x - 2 * s->mb_stride - 2];
+			uvmv = &v->luma_mv[s->mb_x - 2 * s->mb_stride - 2];
+			ttblk = &v->ttblk[s->mb_x - 2 * s->mb_stride - 2];
+			flags = s->mb_x == 2 ? LEFT_EDGE : 0;
+			for (i = 0; i < block_count; i++)
+				vc1_p_h_loop_filter(
+					v, i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize - 16 : dest, cbp, is_intra,
+					i > 3 ? uvmv : &s->cur_pic.motion_val[0][s->block_index[i] - 4 * s->b8_stride - 4 + v->blocks_off],
+					i > 3 ? &v->mv_f[0][s->block_index[i] - 2 * s->mb_stride - 2 + v->mb_off]
+						  : &v->mv_f[0][s->block_index[i] - 4 * s->b8_stride - 4 + v->blocks_off],
+					ttblk, flags, i);
+		}
+		if (s->mb_x == s->mb_width - 1) {
+			if (s->mb_x >= 1) {
+				dest = s->dest[0] - 32 * s->linesize - 16;
+				cbp = &v->cbp[s->mb_x - 2 * s->mb_stride - 1];
+				is_intra = &v->is_intra[s->mb_x - 2 * s->mb_stride - 1];
+				uvmv = &v->luma_mv[s->mb_x - 2 * s->mb_stride - 1];
+				ttblk = &v->ttblk[s->mb_x - 2 * s->mb_stride - 1];
+				flags = s->mb_x == 1 ? LEFT_EDGE : 0;
+				for (i = 0; i < block_count; i++)
+					vc1_p_h_loop_filter(
+						v, i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize - 8 : dest, cbp, is_intra,
+						i > 3 ? uvmv
+							  : &s->cur_pic.motion_val[0][s->block_index[i] - 4 * s->b8_stride - 2 + v->blocks_off],
+						i > 3 ? &v->mv_f[0][s->block_index[i] - 2 * s->mb_stride - 1 + v->mb_off]
+							  : &v->mv_f[0][s->block_index[i] - 4 * s->b8_stride - 2 + v->blocks_off],
+						ttblk, flags, i);
+			}
+			dest = s->dest[0] - 32 * s->linesize;
+			cbp = &v->cbp[s->mb_x - 2 * s->mb_stride];
+			is_intra = &v->is_intra[s->mb_x - 2 * s->mb_stride];
+			uvmv = &v->luma_mv[s->mb_x - 2 * s->mb_stride];
+			ttblk = &v->ttblk[s->mb_x - 2 * s->mb_stride];
+			flags = s->mb_x ? RIGHT_EDGE : LEFT_EDGE | RIGHT_EDGE;
+			for (i = 0; i < block_count; i++)
+				vc1_p_h_loop_filter(
+					v, i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize : dest, cbp, is_intra,
+					i > 3 ? uvmv : &s->cur_pic.motion_val[0][s->block_index[i] - 4 * s->b8_stride + v->blocks_off],
+					i > 3 ? &v->mv_f[0][s->block_index[i] - 2 * s->mb_stride + v->mb_off]
+						  : &v->mv_f[0][s->block_index[i] - 4 * s->b8_stride + v->blocks_off],
+					ttblk, flags, i);
+		}
+	}
+	if (s->mb_y == s->end_mb_y - 1) {
+		if (s->mb_y >= s->start_mb_y + 1) {
+			if (s->mb_x >= 2) {
+				dest = s->dest[0] - 16 * s->linesize - 32;
+				cbp = &v->cbp[s->mb_x - s->mb_stride - 2];
+				is_intra = &v->is_intra[s->mb_x - s->mb_stride - 2];
+				uvmv = &v->luma_mv[s->mb_x - s->mb_stride - 2];
+				ttblk = &v->ttblk[s->mb_x - s->mb_stride - 2];
+				flags = s->mb_x == 2 ? LEFT_EDGE : 0;
+				for (i = 0; i < block_count; i++)
+					vc1_p_h_loop_filter(
+						v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 16 : dest, cbp, is_intra,
+						i > 3 ? uvmv
+							  : &s->cur_pic.motion_val[0][s->block_index[i] - 2 * s->b8_stride - 4 + v->blocks_off],
+						i > 3 ? &v->mv_f[0][s->block_index[i] - s->mb_stride - 2 + v->mb_off]
+							  : &v->mv_f[0][s->block_index[i] - 2 * s->b8_stride - 4 + v->blocks_off],
+						ttblk, flags, i);
+			}
+			if (s->mb_x == s->mb_width - 1) {
+				if (s->mb_x >= 1) {
+					dest = s->dest[0] - 16 * s->linesize - 16;
+					cbp = &v->cbp[s->mb_x - s->mb_stride - 1];
+					is_intra = &v->is_intra[s->mb_x - s->mb_stride - 1];
+					uvmv = &v->luma_mv[s->mb_x - s->mb_stride - 1];
+					ttblk = &v->ttblk[s->mb_x - s->mb_stride - 1];
+					flags = s->mb_x == 1 ? LEFT_EDGE : 0;
+					for (i = 0; i < block_count; i++)
+						vc1_p_h_loop_filter(
+							v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 8 : dest, cbp, is_intra,
+							i > 3 ? uvmv
+								  : &s->cur_pic.motion_val[0][s->block_index[i] - 2 * s->b8_stride - 2 + v->blocks_off],
+							i > 3 ? &v->mv_f[0][s->block_index[i] - s->mb_stride - 1 + v->mb_off]
+								  : &v->mv_f[0][s->block_index[i] - 2 * s->b8_stride - 2 + v->blocks_off],
+							ttblk, flags, i);
+				}
+				dest = s->dest[0] - 16 * s->linesize;
+				cbp = &v->cbp[s->mb_x - s->mb_stride];
+				is_intra = &v->is_intra[s->mb_x - s->mb_stride];
+				uvmv = &v->luma_mv[s->mb_x - s->mb_stride];
+				ttblk = &v->ttblk[s->mb_x - s->mb_stride];
+				flags = s->mb_x ? RIGHT_EDGE : LEFT_EDGE | RIGHT_EDGE;
+				for (i = 0; i < block_count; i++)
+					vc1_p_h_loop_filter(
+						v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize : dest, cbp, is_intra,
+						i > 3 ? uvmv : &s->cur_pic.motion_val[0][s->block_index[i] - 2 * s->b8_stride + v->blocks_off],
+						i > 3 ? &v->mv_f[0][s->block_index[i] - s->mb_stride + v->mb_off]
+							  : &v->mv_f[0][s->block_index[i] - 2 * s->b8_stride + v->blocks_off],
+						ttblk, flags, i);
+			}
+		}
+		if (s->mb_x >= 2) {
+			dest = s->dest[0] - 32;
+			cbp = &v->cbp[s->mb_x - 2];
+			is_intra = &v->is_intra[s->mb_x - 2];
+			uvmv = &v->luma_mv[s->mb_x - 2];
+			ttblk = &v->ttblk[s->mb_x - 2];
+			flags = s->mb_x == 2 ? LEFT_EDGE : 0;
+			for (i = 0; i < block_count; i++)
+				vc1_p_h_loop_filter(v, i > 3 ? s->dest[i - 3] - 16 : dest, cbp, is_intra,
+									i > 3 ? uvmv : &s->cur_pic.motion_val[0][s->block_index[i] - 4 + v->blocks_off],
+									i > 3 ? &v->mv_f[0][s->block_index[i] - 2 + v->mb_off]
+										  : &v->mv_f[0][s->block_index[i] - 4 + v->blocks_off],
+									ttblk, flags, i);
+		}
+		if (s->mb_x == s->mb_width - 1) {
+			if (s->mb_x >= 1) {
+				dest = s->dest[0] - 16;
+				cbp = &v->cbp[s->mb_x - 1];
+				is_intra = &v->is_intra[s->mb_x - 1];
+				uvmv = &v->luma_mv[s->mb_x - 1];
+				ttblk = &v->ttblk[s->mb_x - 1];
+				flags = s->mb_x == 1 ? LEFT_EDGE : 0;
+				for (i = 0; i < block_count; i++)
+					vc1_p_h_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 : dest, cbp, is_intra,
+										i > 3 ? uvmv : &s->cur_pic.motion_val[0][s->block_index[i] - 2 + v->blocks_off],
+										i > 3 ? &v->mv_f[0][s->block_index[i] - 1 + v->mb_off]
+											  : &v->mv_f[0][s->block_index[i] - 2 + v->blocks_off],
+										ttblk, flags, i);
+			}
+			dest = s->dest[0];
+			cbp = &v->cbp[s->mb_x];
+			is_intra = &v->is_intra[s->mb_x];
+			uvmv = &v->luma_mv[s->mb_x];
+			ttblk = &v->ttblk[s->mb_x];
+			flags = s->mb_x ? RIGHT_EDGE : LEFT_EDGE | RIGHT_EDGE;
+			for (i = 0; i < block_count; i++)
+				vc1_p_h_loop_filter(v, i > 3 ? s->dest[i - 3] : dest, cbp, is_intra,
+									i > 3 ? uvmv : &s->cur_pic.motion_val[0][s->block_index[i] + v->blocks_off],
+									i > 3 ? &v->mv_f[0][s->block_index[i] + v->mb_off]
+										  : &v->mv_f[0][s->block_index[i] + v->blocks_off],
+									ttblk, flags, i);
+		}
+	}
+}
+
+static inline void vc1_p_h_intfr_loop_filter(VC1Context *v, uint8 *dest, const int *ttblk, uint32 flags, uint8 fieldtx,
+											 int block_num) {
+	PictureState *s = &v->s;
+	int pq = v->pq;
+	int tt;
+	int linesize = block_num > 3 ? s->uvlinesize : s->linesize;
+	uint8 *dst;
+
+	if (block_num > 3)
+		dst = dest;
+	else
+		dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
+
+	tt = ttblk[0] >> (block_num * 4) & 0xf;
+	if (block_num < 4) {
+		if (fieldtx) {
+			if (block_num < 2) {
+				if (tt == TT_4X4 || tt == TT_4X8)
+					v->vc1dsp.vc1_h_loop_filter8(dst + 4, 2 * linesize, pq);
+				if (!(flags & RIGHT_EDGE) || block_num == 0)
+					v->vc1dsp.vc1_h_loop_filter8(dst + 8, 2 * linesize, pq);
+			} else {
+				if (tt == TT_4X4 || tt == TT_4X8)
+					v->vc1dsp.vc1_h_loop_filter8(dst - 7 * linesize + 4, 2 * linesize, pq);
+				if (!(flags & RIGHT_EDGE) || block_num == 2)
+					v->vc1dsp.vc1_h_loop_filter8(dst - 7 * linesize + 8, 2 * linesize, pq);
+			}
+		} else {
+			if (tt == TT_4X4 || tt == TT_4X8) {
+				v->vc1dsp.vc1_h_loop_filter4(dst + 4, 2 * linesize, pq);
+				v->vc1dsp.vc1_h_loop_filter4(dst + linesize + 4, 2 * linesize, pq);
+			}
+			if (!(flags & RIGHT_EDGE) || !(block_num & 5)) {
+				v->vc1dsp.vc1_h_loop_filter4(dst + 8, 2 * linesize, pq);
+				v->vc1dsp.vc1_h_loop_filter4(dst + linesize + 8, 2 * linesize, pq);
+			}
+		}
+	} else {
+		if (tt == TT_4X4 || tt == TT_4X8) {
+			v->vc1dsp.vc1_h_loop_filter4(dst + 4, 2 * linesize, pq);
+			v->vc1dsp.vc1_h_loop_filter4(dst + linesize + 4, 2 * linesize, pq);
+		}
+		if (!(flags & RIGHT_EDGE)) {
+			v->vc1dsp.vc1_h_loop_filter4(dst + 8, 2 * linesize, pq);
+			v->vc1dsp.vc1_h_loop_filter4(dst + linesize + 8, 2 * linesize, pq);
+		}
+	}
+}
+
+static inline void vc1_p_v_intfr_loop_filter(VC1Context *v, uint8 *dest, const int *ttblk, uint32 flags, uint8 fieldtx,
+											 int block_num) {
+	PictureState *s = &v->s;
+	int pq = v->pq;
+	int tt;
+	int linesize = block_num > 3 ? s->uvlinesize : s->linesize;
+	uint8 *dst;
+
+	if (block_num > 3)
+		dst = dest;
+	else
+		dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
+
+	tt = ttblk[0] >> (block_num * 4) & 0xf;
+	if (block_num < 4) {
+		if (fieldtx) {
+			if (block_num < 2) {
+				if (tt == TT_4X4 || tt == TT_8X4)
+					v->vc1dsp.vc1_v_loop_filter8(dst + 8 * linesize, 2 * linesize, pq);
+				if (!(flags & BOTTOM_EDGE))
+					v->vc1dsp.vc1_v_loop_filter8(dst + 16 * linesize, 2 * linesize, pq);
+			} else {
+				if (tt == TT_4X4 || tt == TT_8X4)
+					v->vc1dsp.vc1_v_loop_filter8(dst + linesize, 2 * linesize, pq);
+				if (!(flags & BOTTOM_EDGE))
+					v->vc1dsp.vc1_v_loop_filter8(dst + 9 * linesize, 2 * linesize, pq);
+			}
+		} else {
+			if (block_num < 2) {
+				if (!(flags & TOP_EDGE) && (tt == TT_4X4 || tt == TT_8X4)) {
+					v->vc1dsp.vc1_v_loop_filter8(dst + 4 * linesize, 2 * linesize, pq);
+					v->vc1dsp.vc1_v_loop_filter8(dst + 5 * linesize, 2 * linesize, pq);
+				}
+				v->vc1dsp.vc1_v_loop_filter8(dst + 8 * linesize, 2 * linesize, pq);
+				v->vc1dsp.vc1_v_loop_filter8(dst + 9 * linesize, 2 * linesize, pq);
+			} else if (!(flags & BOTTOM_EDGE)) {
+				if (tt == TT_4X4 || tt == TT_8X4) {
+					v->vc1dsp.vc1_v_loop_filter8(dst + 4 * linesize, 2 * linesize, pq);
+					v->vc1dsp.vc1_v_loop_filter8(dst + 5 * linesize, 2 * linesize, pq);
+				}
+				v->vc1dsp.vc1_v_loop_filter8(dst + 8 * linesize, 2 * linesize, pq);
+				v->vc1dsp.vc1_v_loop_filter8(dst + 9 * linesize, 2 * linesize, pq);
+			}
+		}
+	} else {
+		if (!(flags & BOTTOM_EDGE)) {
+			if (!(flags & TOP_EDGE) && (tt == TT_4X4 || tt == TT_8X4)) {
+				v->vc1dsp.vc1_v_loop_filter8(dst + 4 * linesize, 2 * linesize, pq);
+				v->vc1dsp.vc1_v_loop_filter8(dst + 5 * linesize, 2 * linesize, pq);
+			}
+			v->vc1dsp.vc1_v_loop_filter8(dst + 8 * linesize, 2 * linesize, pq);
+			v->vc1dsp.vc1_v_loop_filter8(dst + 9 * linesize, 2 * linesize, pq);
+		}
+	}
+}
+
+void ff_vc1_p_intfr_loop_filter(VC1Context *v) {
+	PictureState *s = &v->s;
+	int block_count = CONFIG_GRAY && (s->avctx->flags & AV_CODEC_FLAG_GRAY) ? 4 : 6;
+	int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
+	uint8 *dest;
+	int *ttblk;
+	uint32 flags;
+	uint8 fieldtx;
+	int i;
+
+	/* Within a MB, the vertical loop filter always runs before the horizontal.
+	 * To accomplish that, we run the V loop filter on all applicable
+	 * horizontal borders of the MB above the last overlap filtered MB. Then,
+	 * we wait for the loop filter iteration on the next row and next column to
+	 * do H loop filter on all applicable vertical borders of this MB.
+	 * Therefore, the loop filter trails by two rows and one column relative to
+	 * the overlap filter and two rows and two columns relative to the decoding
+	 * loop. */
+	if (s->mb_x) {
+		if (s->mb_y >= s->start_mb_y + 1) {
+			dest = s->dest[0] - 16 * s->linesize - 16;
+			ttblk = &v->ttblk[s->mb_x - s->mb_stride - 1];
+			flags = s->mb_y == s->start_mb_y + 1 ? TOP_EDGE : 0;
+			fieldtx = v->fieldtx_plane[mb_pos - s->mb_stride - 1];
+			for (i = 0; i < block_count; i++)
+				vc1_p_v_intfr_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 8 : dest, ttblk, flags,
+										  fieldtx, i);
+		}
+	}
+	if (s->mb_x == s->mb_width - 1) {
+		if (s->mb_y >= s->start_mb_y + 1) {
+			dest = s->dest[0] - 16 * s->linesize;
+			ttblk = &v->ttblk[s->mb_x - s->mb_stride];
+			flags = s->mb_y == s->start_mb_y + 1 ? TOP_EDGE : 0;
+			fieldtx = v->fieldtx_plane[mb_pos - s->mb_stride];
+			for (i = 0; i < block_count; i++)
+				vc1_p_v_intfr_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize : dest, ttblk, flags, fieldtx,
+										  i);
+		}
+	}
+	if (s->mb_y == s->end_mb_y - 1) {
+		if (s->mb_x) {
+			dest = s->dest[0] - 16;
+			ttblk = &v->ttblk[s->mb_x - 1];
+			flags = s->mb_y == s->start_mb_y ? TOP_EDGE | BOTTOM_EDGE : BOTTOM_EDGE;
+			fieldtx = v->fieldtx_plane[mb_pos - 1];
+			for (i = 0; i < block_count; i++)
+				vc1_p_v_intfr_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 : dest, ttblk, flags, fieldtx, i);
+		}
+		if (s->mb_x == s->mb_width - 1) {
+			dest = s->dest[0];
+			ttblk = &v->ttblk[s->mb_x];
+			flags = s->mb_y == s->start_mb_y ? TOP_EDGE | BOTTOM_EDGE : BOTTOM_EDGE;
+			fieldtx = v->fieldtx_plane[mb_pos];
+			for (i = 0; i < block_count; i++)
+				vc1_p_v_intfr_loop_filter(v, i > 3 ? s->dest[i - 3] : dest, ttblk, flags, fieldtx, i);
+		}
+	}
+
+	if (s->mb_y >= s->start_mb_y + 2) {
+		if (s->mb_x >= 2) {
+			dest = s->dest[0] - 32 * s->linesize - 32;
+			ttblk = &v->ttblk[s->mb_x - 2 * s->mb_stride - 2];
+			flags = s->mb_x == 2 ? LEFT_EDGE : 0;
+			fieldtx = v->fieldtx_plane[mb_pos - 2 * s->mb_stride - 2];
+			for (i = 0; i < block_count; i++)
+				vc1_p_h_intfr_loop_filter(v, i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize - 16 : dest, ttblk, flags,
+										  fieldtx, i);
+		}
+		if (s->mb_x == s->mb_width - 1) {
+			if (s->mb_x >= 1) {
+				dest = s->dest[0] - 32 * s->linesize - 16;
+				ttblk = &v->ttblk[s->mb_x - 2 * s->mb_stride - 1];
+				flags = s->mb_x == 1 ? LEFT_EDGE : 0;
+				fieldtx = v->fieldtx_plane[mb_pos - 2 * s->mb_stride - 1];
+				for (i = 0; i < block_count; i++)
+					vc1_p_h_intfr_loop_filter(v, i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize - 8 : dest, ttblk, flags,
+											  fieldtx, i);
+			}
+			dest = s->dest[0] - 32 * s->linesize;
+			ttblk = &v->ttblk[s->mb_x - 2 * s->mb_stride];
+			flags = s->mb_x ? RIGHT_EDGE : LEFT_EDGE | RIGHT_EDGE;
+			fieldtx = v->fieldtx_plane[mb_pos - 2 * s->mb_stride];
+			for (i = 0; i < block_count; i++)
+				vc1_p_h_intfr_loop_filter(v, i > 3 ? s->dest[i - 3] - 16 * s->uvlinesize : dest, ttblk, flags, fieldtx,
+										  i);
+		}
+	}
+	if (s->mb_y == s->end_mb_y - 1) {
+		if (s->mb_y >= s->start_mb_y + 1) {
+			if (s->mb_x >= 2) {
+				dest = s->dest[0] - 16 * s->linesize - 32;
+				ttblk = &v->ttblk[s->mb_x - s->mb_stride - 2];
+				flags = s->mb_x == 2 ? LEFT_EDGE : 0;
+				fieldtx = v->fieldtx_plane[mb_pos - s->mb_stride - 2];
+				for (i = 0; i < block_count; i++)
+					vc1_p_h_intfr_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 16 : dest, ttblk, flags,
+											  fieldtx, i);
+			}
+			if (s->mb_x == s->mb_width - 1) {
+				if (s->mb_x >= 1) {
+					dest = s->dest[0] - 16 * s->linesize - 16;
+					ttblk = &v->ttblk[s->mb_x - s->mb_stride - 1];
+					flags = s->mb_x == 1 ? LEFT_EDGE : 0;
+					fieldtx = v->fieldtx_plane[mb_pos - s->mb_stride - 1];
+					for (i = 0; i < block_count; i++)
+						vc1_p_h_intfr_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 8 : dest, ttblk,
+												  flags, fieldtx, i);
+				}
+				dest = s->dest[0] - 16 * s->linesize;
+				ttblk = &v->ttblk[s->mb_x - s->mb_stride];
+				flags = s->mb_x ? RIGHT_EDGE : LEFT_EDGE | RIGHT_EDGE;
+				fieldtx = v->fieldtx_plane[mb_pos - s->mb_stride];
+				for (i = 0; i < block_count; i++)
+					vc1_p_h_intfr_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize : dest, ttblk, flags,
+											  fieldtx, i);
+			}
+		}
+		if (s->mb_x >= 2) {
+			dest = s->dest[0] - 32;
+			ttblk = &v->ttblk[s->mb_x - 2];
+			flags = s->mb_x == 2 ? LEFT_EDGE : 0;
+			fieldtx = v->fieldtx_plane[mb_pos - 2];
+			for (i = 0; i < block_count; i++)
+				vc1_p_h_intfr_loop_filter(v, i > 3 ? s->dest[i - 3] - 16 : dest, ttblk, flags, fieldtx, i);
+		}
+		if (s->mb_x == s->mb_width - 1) {
+			if (s->mb_x >= 1) {
+				dest = s->dest[0] - 16;
+				ttblk = &v->ttblk[s->mb_x - 1];
+				flags = s->mb_x == 1 ? LEFT_EDGE : 0;
+				fieldtx = v->fieldtx_plane[mb_pos - 1];
+				for (i = 0; i < block_count; i++)
+					vc1_p_h_intfr_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 : dest, ttblk, flags, fieldtx, i);
+			}
+			dest = s->dest[0];
+			ttblk = &v->ttblk[s->mb_x];
+			flags = s->mb_x ? RIGHT_EDGE : LEFT_EDGE | RIGHT_EDGE;
+			fieldtx = v->fieldtx_plane[mb_pos];
+			for (i = 0; i < block_count; i++)
+				vc1_p_h_intfr_loop_filter(v, i > 3 ? s->dest[i - 3] : dest, ttblk, flags, fieldtx, i);
+		}
+	}
+}
+
+static inline void vc1_b_h_intfi_loop_filter(VC1Context *v, uint8 *dest, const uint32 *cbp, const int *ttblk,
+											 uint32 flags, int block_num) {
+	PictureState *s = &v->s;
+	int pq = v->pq;
+	uint8 *dst;
+	uint32 block_cbp = cbp[0] >> (block_num * 4);
+	int tt;
+	int idx, linesize = block_num > 3 ? s->uvlinesize : s->linesize;
+
+	if (block_num > 3)
+		dst = dest;
+	else
+		dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
+
+	if (!(flags & RIGHT_EDGE) || !(block_num & 5)) {
+		v->vc1dsp.vc1_h_loop_filter8(dst + 8, linesize, pq);
+	}
+
+	tt = ttblk[0] >> (block_num * 4) & 0xf;
+	if (tt == TT_4X4 || tt == TT_4X8) {
+		idx = (block_cbp | (block_cbp >> 1)) & 5;
+		if (idx & 1)
+			v->vc1dsp.vc1_h_loop_filter4(dst + 4 * linesize + 4, linesize, pq);
+		if (idx & 4)
+			v->vc1dsp.vc1_h_loop_filter4(dst + 4, linesize, pq);
+	}
+}
+
+static inline void vc1_b_v_intfi_loop_filter(VC1Context *v, uint8 *dest, const uint32 *cbp, const int *ttblk,
+											 uint32 flags, int block_num) {
+	PictureState *s = &v->s;
+	int pq = v->pq;
+	uint8 *dst;
+	uint32 block_cbp = cbp[0] >> (block_num * 4);
+	int tt;
+	int idx, linesize = block_num > 3 ? s->uvlinesize : s->linesize;
+
+	if (block_num > 3)
+		dst = dest;
+	else
+		dst = dest + (block_num & 2) * 4 * s->linesize + (block_num & 1) * 8;
+
+	if (!(flags & BOTTOM_EDGE) || block_num < 2)
+		v->vc1dsp.vc1_v_loop_filter8(dst + 8 * linesize, linesize, pq);
+
+	tt = ttblk[0] >> (block_num * 4) & 0xf;
+	if (tt == TT_4X4 || tt == TT_8X4) {
+		idx = (block_cbp | (block_cbp >> 2)) & 3;
+		if (idx & 1)
+			v->vc1dsp.vc1_v_loop_filter4(dst + 4 * linesize + 4, linesize, pq);
+		if (idx & 2)
+			v->vc1dsp.vc1_v_loop_filter4(dst + 4 * linesize, linesize, pq);
+	}
+}
+
+void ff_vc1_b_intfi_loop_filter(VC1Context *v) {
+	PictureState *s = &v->s;
+	int block_count = CONFIG_GRAY && (s->avctx->flags & AV_CODEC_FLAG_GRAY) ? 4 : 6;
+	uint8 *dest;
+	const uint32 *cbp;
+	int *ttblk;
+	uint32 flags = 0;
+	int i;
+
+	/* Within a MB, the vertical loop filter always runs before the horizontal.
+	 * To accomplish that, we run the V loop filter on all applicable
+	 * horizontal borders of the MB above the currently decoded MB. Then,
+	 * we wait for the next loop filter iteration to do H loop filter on all
+	 * applicable vertical borders of this MB. Therefore, the loop filter
+	 * trails by one row and one column relative to the decoding loop. */
+	if (!s->first_slice_line) {
+		dest = s->dest[0] - 16 * s->linesize;
+		cbp = &v->cbp[s->mb_x - s->mb_stride];
+		ttblk = &v->ttblk[s->mb_x - s->mb_stride];
+		flags = s->mb_y == s->start_mb_y + 1 ? TOP_EDGE : 0;
+		for (i = 0; i < block_count; i++)
+			vc1_b_v_intfi_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize : dest, cbp, ttblk, flags, i);
+	}
+	if (s->mb_y == s->end_mb_y - 1) {
+		dest = s->dest[0];
+		cbp = &v->cbp[s->mb_x];
+		ttblk = &v->ttblk[s->mb_x];
+		flags = s->first_slice_line ? TOP_EDGE | BOTTOM_EDGE : BOTTOM_EDGE;
+		for (i = 0; i < block_count; i++)
+			vc1_b_v_intfi_loop_filter(v, i > 3 ? s->dest[i - 3] : dest, cbp, ttblk, flags, i);
+	}
+
+	if (!s->first_slice_line) {
+		dest = s->dest[0] - 16 * s->linesize - 16;
+		cbp = &v->cbp[s->mb_x - s->mb_stride - 1];
+		ttblk = &v->ttblk[s->mb_x - s->mb_stride - 1];
+		if (s->mb_x) {
+			flags = s->mb_x == 1 ? LEFT_EDGE : 0;
+			for (i = 0; i < block_count; i++)
+				vc1_b_h_intfi_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize - 8 : dest, cbp, ttblk, flags,
+										  i);
+		}
+		if (s->mb_x == s->mb_width - 1) {
+			dest += 16;
+			cbp++;
+			ttblk++;
+			flags = s->mb_x == 0 ? LEFT_EDGE | RIGHT_EDGE : RIGHT_EDGE;
+			for (i = 0; i < block_count; i++)
+				vc1_b_h_intfi_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 * s->uvlinesize : dest, cbp, ttblk, flags, i);
+		}
+	}
+	if (s->mb_y == s->end_mb_y - 1) {
+		dest = s->dest[0] - 16;
+		cbp = &v->cbp[s->mb_x - 1];
+		ttblk = &v->ttblk[s->mb_x - 1];
+		if (s->mb_x) {
+			flags = s->mb_x == 1 ? LEFT_EDGE : 0;
+			for (i = 0; i < block_count; i++)
+				vc1_b_h_intfi_loop_filter(v, i > 3 ? s->dest[i - 3] - 8 : dest, cbp, ttblk, flags, i);
+		}
+		if (s->mb_x == s->mb_width - 1) {
+			dest += 16;
+			cbp++;
+			ttblk++;
+			flags = s->mb_x == 0 ? LEFT_EDGE | RIGHT_EDGE : RIGHT_EDGE;
+			for (i = 0; i < block_count; i++)
+				vc1_b_h_intfi_loop_filter(v, i > 3 ? s->dest[i - 3] : dest, cbp, ttblk, flags, i);
+		}
+	}
+}
+
+#undef BOTTOM_EDGE
+#undef LEFT_EDGE
+#undef RIGHT_EDGE
+#undef TOP_EDGE
+
+static inline void vc1_scale_luma(uint8 *srcY, int k, int linesize) {
+	int i, j;
+	for (j = 0; j < k; j++) {
+		for (i = 0; i < k; i++)
+			srcY[i] = ((srcY[i] - 128) >> 1) + 128;
+		srcY += linesize;
+	}
+}
+
+static inline void vc1_scale_chroma(uint8 *srcU, uint8 *srcV, int k, int uvlinesize) {
+	int i, j;
+	for (j = 0; j < k; j++) {
+		for (i = 0; i < k; i++) {
+			srcU[i] = ((srcU[i] - 128) >> 1) + 128;
+			srcV[i] = ((srcV[i] - 128) >> 1) + 128;
+		}
+		srcU += uvlinesize;
+		srcV += uvlinesize;
+	}
+}
+
+static inline void vc1_lut_scale_luma(uint8 *srcY, const uint8 *lut1, const uint8 *lut2, int k, int linesize) {
+	int i, j;
+
+	for (j = 0; j < k; j += 2) {
+		for (i = 0; i < k; i++)
+			srcY[i] = lut1[srcY[i]];
+		srcY += linesize;
+
+		if (j + 1 == k)
+			break;
+
+		for (i = 0; i < k; i++)
+			srcY[i] = lut2[srcY[i]];
+		srcY += linesize;
+	}
+}
+
+static inline void vc1_lut_scale_chroma(uint8 *srcU, uint8 *srcV, const uint8 *lut1, const uint8 *lut2, int k,
+										int uvlinesize) {
+	int i, j;
+
+	for (j = 0; j < k; j += 2) {
+		for (i = 0; i < k; i++) {
+			srcU[i] = lut1[srcU[i]];
+			srcV[i] = lut1[srcV[i]];
+		}
+		srcU += uvlinesize;
+		srcV += uvlinesize;
+
+		if (j + 1 == k)
+			break;
+
+		for (i = 0; i < k; i++) {
+			srcU[i] = lut2[srcU[i]];
+			srcV[i] = lut2[srcV[i]];
+		}
+		srcU += uvlinesize;
+		srcV += uvlinesize;
+	}
+}
+
+static const uint8 popcount4[16] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
+
+static inline int get_luma_mv(VC1Context *v, int dir, int16 *tx, int16 *ty) {
+	PictureState *s = &v->s;
+	int idx = v->mv_f[dir][s->block_index[0] + v->blocks_off] | (v->mv_f[dir][s->block_index[1] + v->blocks_off] << 1) |
+			  (v->mv_f[dir][s->block_index[2] + v->blocks_off] << 2) |
+			  (v->mv_f[dir][s->block_index[3] + v->blocks_off] << 3);
+	static const uint8 index2[16] = {0, 0, 0, 0x23, 0, 0x13, 0x03, 0, 0, 0x12, 0x02, 0, 0x01, 0, 0, 0};
+	int opp_count = popcount4[idx];
+
+	switch (opp_count) {
+	case 0:
+	case 4:
+		*tx = median4(s->mv[dir][0][0], s->mv[dir][1][0], s->mv[dir][2][0], s->mv[dir][3][0]);
+		*ty = median4(s->mv[dir][0][1], s->mv[dir][1][1], s->mv[dir][2][1], s->mv[dir][3][1]);
+		break;
+	case 1:
+		*tx = mid_pred(s->mv[dir][idx < 2][0], s->mv[dir][1 + (idx < 4)][0], s->mv[dir][2 + (idx < 8)][0]);
+		*ty = mid_pred(s->mv[dir][idx < 2][1], s->mv[dir][1 + (idx < 4)][1], s->mv[dir][2 + (idx < 8)][1]);
+		break;
+	case 3:
+		*tx = mid_pred(s->mv[dir][idx > 0xd][0], s->mv[dir][1 + (idx > 0xb)][0], s->mv[dir][2 + (idx > 0x7)][0]);
+		*ty = mid_pred(s->mv[dir][idx > 0xd][1], s->mv[dir][1 + (idx > 0xb)][1], s->mv[dir][2 + (idx > 0x7)][1]);
+		break;
+	case 2:
+		*tx = (s->mv[dir][index2[idx] >> 4][0] + s->mv[dir][index2[idx] & 0xf][0]) / 2;
+		*ty = (s->mv[dir][index2[idx] >> 4][1] + s->mv[dir][index2[idx] & 0xf][1]) / 2;
+		break;
+	}
+	return opp_count;
+}
+
+static inline int get_chroma_mv(VC1Context *v, int dir, int16 *tx, int16 *ty) {
+	PictureState *s = &v->s;
+	int idx = !v->mb_type[s->block_index[0]] | (!v->mb_type[s->block_index[1]] << 1) |
+			  (!v->mb_type[s->block_index[2]] << 2) | (!v->mb_type[s->block_index[3]] << 3);
+	static const uint8 index2[16] = {0, 0, 0, 0x01, 0, 0x02, 0x12, 0, 0, 0x03, 0x13, 0, 0x23, 0, 0, 0};
+	int valid_count = popcount4[idx];
+
+	switch (valid_count) {
+	case 4:
+		*tx = median4(s->mv[dir][0][0], s->mv[dir][1][0], s->mv[dir][2][0], s->mv[dir][3][0]);
+		*ty = median4(s->mv[dir][0][1], s->mv[dir][1][1], s->mv[dir][2][1], s->mv[dir][3][1]);
+		break;
+	case 3:
+		*tx = mid_pred(s->mv[dir][idx > 0xd][0], s->mv[dir][1 + (idx > 0xb)][0], s->mv[dir][2 + (idx > 0x7)][0]);
+		*ty = mid_pred(s->mv[dir][idx > 0xd][1], s->mv[dir][1 + (idx > 0xb)][1], s->mv[dir][2 + (idx > 0x7)][1]);
+		break;
+	case 2:
+		*tx = (s->mv[dir][index2[idx] >> 4][0] + s->mv[dir][index2[idx] & 0xf][0]) / 2;
+		*ty = (s->mv[dir][index2[idx] >> 4][1] + s->mv[dir][index2[idx] & 0xf][1]) / 2;
+		break;
+	default:
+		return 0;
+	}
+	return valid_count;
+}
+
+/** Do motion compensation over 1 macroblock
+ * Mostly adapted hpel_motion and qpel_motion from mpegvideo.c
+ */
+void ff_vc1_mc_1mv(VC1Context *v, int dir) {
+	PictureState *s = &v->s;
+	ChromaDSP *h264chroma = &v->h264chroma;
+	uint8 *srcY, *srcU, *srcV;
+	int dxy, mx, my, uvmx, uvmy, src_x, src_y, uvsrc_x, uvsrc_y;
+	int v_edge_pos = s->v_edge_pos >> v->field_mode;
+	int i;
+	const uint8(*luty)[256], (*lutuv)[256];
+	int use_ic;
+	int interlace;
+	int linesize, uvlinesize;
+
+	if ((!v->field_mode || (v->ref_field_type[dir] == 1 && v->cur_field_type == 1)) && !v->s.last_pic.data[0])
+		return;
+
+	linesize = s->cur_pic.ptr->f->linesize[0];
+	uvlinesize = s->cur_pic.ptr->f->linesize[1];
+
+	mx = s->mv[dir][0][0];
+	my = s->mv[dir][0][1];
+
+	// store motion vectors for further use in B-frames
+	if (s->pict_type == AV_PICTURE_TYPE_P) {
+		for (i = 0; i < 4; i++) {
+			s->cur_pic.motion_val[1][s->block_index[i] + v->blocks_off][0] = mx;
+			s->cur_pic.motion_val[1][s->block_index[i] + v->blocks_off][1] = my;
+		}
+	}
+
+	uvmx = (mx + ((mx & 3) == 3)) >> 1;
+	uvmy = (my + ((my & 3) == 3)) >> 1;
+	v->luma_mv[s->mb_x][0] = uvmx;
+	v->luma_mv[s->mb_x][1] = uvmy;
+
+	if (v->field_mode && v->cur_field_type != v->ref_field_type[dir]) {
+		my = my - 2 + 4 * v->cur_field_type;
+		uvmy = uvmy - 2 + 4 * v->cur_field_type;
+	}
+
+	// fastuvmc shall be ignored for interlaced frame picture
+	if (v->fastuvmc && (v->fcm != ILACE_FRAME)) {
+		uvmx = uvmx + ((uvmx < 0) ? (uvmx & 1) : -(uvmx & 1));
+		uvmy = uvmy + ((uvmy < 0) ? (uvmy & 1) : -(uvmy & 1));
+	}
+	if (!dir) {
+		if (v->field_mode && (v->cur_field_type != v->ref_field_type[dir]) && v->second_field) {
+			srcY = s->cur_pic.data[0];
+			srcU = s->cur_pic.data[1];
+			srcV = s->cur_pic.data[2];
+			luty = v->curr_luty;
+			lutuv = v->curr_lutuv;
+			use_ic = *v->curr_use_ic;
+			interlace = 1;
+		} else {
+			srcY = s->last_pic.data[0];
+			srcU = s->last_pic.data[1];
+			srcV = s->last_pic.data[2];
+			luty = v->last_luty;
+			lutuv = v->last_lutuv;
+			use_ic = v->last_use_ic;
+			interlace = v->last_interlaced;
+		}
+	} else {
+		srcY = s->next_pic.data[0];
+		srcU = s->next_pic.data[1];
+		srcV = s->next_pic.data[2];
+		luty = v->next_luty;
+		lutuv = v->next_lutuv;
+		use_ic = v->next_use_ic;
+		interlace = v->next_interlaced;
+	}
+
+	if (!srcY || !srcU) {
+		warning("Referenced frame missing.\n");
+		return;
+	}
+
+	src_x = s->mb_x * 16 + (mx >> 2);
+	src_y = s->mb_y * 16 + (my >> 2);
+	uvsrc_x = s->mb_x * 8 + (uvmx >> 2);
+	uvsrc_y = s->mb_y * 8 + (uvmy >> 2);
+
+	if (v->profile != PROFILE_ADVANCED) {
+		src_x = av_clip(src_x, -16, s->mb_width * 16);
+		src_y = av_clip(src_y, -16, s->mb_height * 16);
+		uvsrc_x = av_clip(uvsrc_x, -8, s->mb_width * 8);
+		uvsrc_y = av_clip(uvsrc_y, -8, s->mb_height * 8);
+	} else {
+		src_x = av_clip(src_x, -17, s->avctx->coded_width);
+		uvsrc_x = av_clip(uvsrc_x, -8, s->avctx->coded_width >> 1);
+		if (v->fcm == ILACE_FRAME) {
+			src_y = av_clip(src_y, -18 + (src_y & 1), s->avctx->coded_height + (src_y & 1));
+			uvsrc_y = av_clip(uvsrc_y, -8 + (uvsrc_y & 1), (s->avctx->coded_height >> 1) + (uvsrc_y & 1));
+		} else {
+			src_y = av_clip(src_y, -18, s->avctx->coded_height + 1);
+			uvsrc_y = av_clip(uvsrc_y, -8, s->avctx->coded_height >> 1);
+		}
+	}
+
+	srcY += src_y * s->linesize + src_x;
+	srcU += uvsrc_y * s->uvlinesize + uvsrc_x;
+	srcV += uvsrc_y * s->uvlinesize + uvsrc_x;
+
+	if (v->field_mode && v->ref_field_type[dir]) {
+		srcY += linesize;
+		srcU += uvlinesize;
+		srcV += uvlinesize;
+	}
+
+	/* for grayscale we should not try to read from unknown area */
+	if (CONFIG_GRAY && s->avctx->flags & AV_CODEC_FLAG_GRAY) {
+		srcU = s->sc.edge_emu_buffer + 18 * s->linesize;
+		srcV = s->sc.edge_emu_buffer + 18 * s->linesize;
+	}
+
+	if (v->rangeredfrm || use_ic || s->h_edge_pos < 22 || v_edge_pos < 22 ||
+		(unsigned)(src_x - s->mspel) > s->h_edge_pos - (mx & 3) - 16 - s->mspel * 3 ||
+		(unsigned)(src_y - 1) > v_edge_pos - (my & 3) - 16 - 3) {
+		uint8 *ubuf = s->sc.edge_emu_buffer + 19 * s->linesize;
+		uint8 *vbuf = ubuf + 9 * s->uvlinesize;
+		const int k = 17 + s->mspel * 2;
+
+		srcY -= s->mspel * (1 + s->linesize);
+		if (interlace) {
+			s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, srcY, linesize << 1, linesize << 1, k,
+									 v->field_mode ? k : k + 1 >> 1, src_x - s->mspel,
+									 src_y - s->mspel >> !v->field_mode, s->h_edge_pos, s->v_edge_pos >> 1);
+			if (!v->field_mode)
+				s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer + linesize, srcY + linesize, linesize << 1,
+										 linesize << 1, k, k >> 1, src_x - s->mspel, src_y - s->mspel + 1 >> 1,
+										 s->h_edge_pos, s->v_edge_pos >> 1);
+		} else
+			s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, srcY, linesize, linesize, k,
+									 v->field_mode ? (k << 1) - 1 : k, src_x - s->mspel,
+									 v->field_mode ? 2 * (src_y - s->mspel) + v->ref_field_type[dir] : src_y - s->mspel,
+									 s->h_edge_pos, s->v_edge_pos);
+		srcY = s->sc.edge_emu_buffer;
+		if (interlace) {
+			s->vdsp.emulated_edge_mc(ubuf, srcU, uvlinesize << 1, uvlinesize << 1, 9, v->field_mode ? 9 : 5, uvsrc_x,
+									 uvsrc_y >> !v->field_mode, s->h_edge_pos >> 1, s->v_edge_pos >> 2);
+			s->vdsp.emulated_edge_mc(vbuf, srcV, uvlinesize << 1, uvlinesize << 1, 9, v->field_mode ? 9 : 5, uvsrc_x,
+									 uvsrc_y >> !v->field_mode, s->h_edge_pos >> 1, s->v_edge_pos >> 2);
+			if (!v->field_mode) {
+				s->vdsp.emulated_edge_mc(ubuf + uvlinesize, srcU + uvlinesize, uvlinesize << 1, uvlinesize << 1, 9, 4,
+										 uvsrc_x, uvsrc_y + 1 >> 1, s->h_edge_pos >> 1, s->v_edge_pos >> 2);
+				s->vdsp.emulated_edge_mc(vbuf + uvlinesize, srcV + uvlinesize, uvlinesize << 1, uvlinesize << 1, 9, 4,
+										 uvsrc_x, uvsrc_y + 1 >> 1, s->h_edge_pos >> 1, s->v_edge_pos >> 2);
+			}
+		} else {
+			s->vdsp.emulated_edge_mc(ubuf, srcU, uvlinesize, uvlinesize, 9, v->field_mode ? 17 : 9, uvsrc_x,
+									 v->field_mode ? 2 * uvsrc_y + v->ref_field_type[dir] : uvsrc_y, s->h_edge_pos >> 1,
+									 s->v_edge_pos >> 1);
+			s->vdsp.emulated_edge_mc(vbuf, srcV, uvlinesize, uvlinesize, 9, v->field_mode ? 17 : 9, uvsrc_x,
+									 v->field_mode ? 2 * uvsrc_y + v->ref_field_type[dir] : uvsrc_y, s->h_edge_pos >> 1,
+									 s->v_edge_pos >> 1);
+		}
+		srcU = ubuf;
+		srcV = vbuf;
+		/* if we deal with range reduction we need to scale source blocks */
+		if (v->rangeredfrm) {
+			vc1_scale_luma(srcY, k, s->linesize);
+			vc1_scale_chroma(srcU, srcV, 9, s->uvlinesize);
+		}
+		/* if we deal with intensity compensation we need to scale source blocks */
+		if (use_ic) {
+			vc1_lut_scale_luma(srcY, luty[v->field_mode ? v->ref_field_type[dir] : ((0 + src_y - s->mspel) & 1)],




More information about the Scummvm-git-logs mailing list