[FFmpeg-devel] [PATCH v2 103/162] avcodec/vc1: Use symbols table to decode MV differentials

Andreas Rheinhardt andreas.rheinhardt at gmail.com
Fri Nov 20 09:32:28 EET 2020


The VC1 decoder currently follows the spec very closely when decoding
MV differentials: The spec uses tables with contiguous indexes and
derives four values from it using a pseudo-code procedure: Two flags
and two values with a range of 0..5 each; the latter are obtained as the
result resp. the remainder of dividing the index by 6 in the spec and
in the earlier code.

Yet two flags can be encoded on two bits and the two values can be
encoded on three bits each. Therefore the new symbols use the two
lowest bits for the flags; the two other values are coded separately
on three bits each. There is just one additional minor complication:
The two three-bits values don't always exist; there is another mode.
Instead of using an arbitrary six bit value for the higher bits that
is different from all the values used by the ordinary mode this commit
instead uses a negative number for it; this is possible by shifting the
symbols as stored in the table (to make all fit into an uint8_t) and
then shifting the codes downwards when creating the table. The latter
is possible thanks to ff_init_vlc_from_lengths().

Switching to ff_init_vlc_from_lengths() also entails replacing 16bit
codes by 8bit symbols, thereby saving space.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at gmail.com>
---
 libavcodec/vc1.c       |   7 +-
 libavcodec/vc1_block.c |  30 ++++-----
 libavcodec/vc1data.c   | 149 +++++++++++++++++++----------------------
 libavcodec/vc1data.h   |  14 +++-
 4 files changed, 96 insertions(+), 104 deletions(-)

diff --git a/libavcodec/vc1.c b/libavcodec/vc1.c
index 478fe7d66d..a7cc11de54 100644
--- a/libavcodec/vc1.c
+++ b/libavcodec/vc1.c
@@ -1414,9 +1414,10 @@ av_cold int ff_vc1_init_common(VC1Context *v)
                      ff_vc1_cbpcy_p_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC);
             ff_vc1_mv_diff_vlc[i].table           = &vlc_table[vlc_offs[i * 3 + 11]];
             ff_vc1_mv_diff_vlc[i].table_allocated = vlc_offs[i * 3 + 12] - vlc_offs[i * 3 + 11];
-            init_vlc(&ff_vc1_mv_diff_vlc[i], VC1_MV_DIFF_VLC_BITS, 73,
-                     ff_vc1_mv_diff_bits[i], 1, 1,
-                     ff_vc1_mv_diff_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC);
+            ff_init_vlc_from_lengths(&ff_vc1_mv_diff_vlc[i], VC1_MV_DIFF_VLC_BITS, 73,
+                                     &ff_vc1_mv_diff_tabs[i][0][1], 2,
+                                     &ff_vc1_mv_diff_tabs[i][0][0], 2, 1,
+                                     -4, INIT_VLC_USE_NEW_STATIC, NULL);
         }
         for (int i = 0, ac_offset = 0; i < 8; i++) {
             ff_vc1_ac_coeff_table[i].table           = &vlc_table[vlc_offs[i * 2 + 21]];
diff --git a/libavcodec/vc1_block.c b/libavcodec/vc1_block.c
index 3ff67d83bf..6820ffb0d7 100644
--- a/libavcodec/vc1_block.c
+++ b/libavcodec/vc1_block.c
@@ -223,25 +223,16 @@ static void vc1_put_blocks_clamped(VC1Context *v, int put_signed)
  */
 #define GET_MVDATA(_dmv_x, _dmv_y)                                      \
 do {                                                                    \
-    int index = 1 + get_vlc2(gb, ff_vc1_mv_diff_vlc[s->mv_table_index].table, \
+    int symbol = get_vlc2(gb, ff_vc1_mv_diff_vlc[s->mv_table_index].table, \
                          VC1_MV_DIFF_VLC_BITS, 2);                      \
-    if (index > 36) {                                                   \
-        mb_has_coeffs = 1;                                              \
-        index -= 37;                                                    \
-    } else                                                              \
-        mb_has_coeffs = 0;                                              \
-    s->mb_intra = 0;                                                    \
-    if (!index) {                                                       \
+    mb_has_coeffs = symbol & 1;                                         \
+    symbol      >>= 1;                                                  \
+    s->mb_intra   = symbol & 1;                                         \
+    symbol      >>= 1;                                                  \
+    if (!symbol) {                                                      \
         _dmv_x = _dmv_y = 0;                                            \
-    } else if (index == 35) {                                           \
-        _dmv_x = get_bits(gb, v->k_x - 1 + s->quarter_sample);          \
-        _dmv_y = get_bits(gb, v->k_y - 1 + s->quarter_sample);          \
-    } else if (index == 36) {                                           \
-        _dmv_x = 0;                                                     \
-        _dmv_y = 0;                                                     \
-        s->mb_intra = 1;                                                \
-    } else {                                                            \
-        int index1 = index % 6, sign, val;                              \
+    } else if (symbol > 0) {                                            \
+        int index1 = symbol & 7, sign, val;                             \
         _dmv_x = offset_table[1][index1];                               \
         val = size_table[index1] - (!s->quarter_sample && index1 == 5); \
         if (val > 0) {                                                  \
@@ -250,7 +241,7 @@ do {                                                                    \
             _dmv_x = (sign ^ ((val >> 1) + _dmv_x)) - sign;             \
         }                                                               \
                                                                         \
-        index1 = index / 6;                                             \
+        index1 = symbol >> 3;                                           \
         _dmv_y = offset_table[1][index1];                               \
         val = size_table[index1] - (!s->quarter_sample && index1 == 5); \
         if (val > 0) {                                                  \
@@ -258,6 +249,9 @@ do {                                                                    \
             sign = 0 - (val & 1);                                       \
             _dmv_y = (sign ^ ((val >> 1) + _dmv_y)) - sign;             \
         }                                                               \
+    } else {                                                            \
+        _dmv_x = get_bits(gb, v->k_x - 1 + s->quarter_sample);          \
+        _dmv_y = get_bits(gb, v->k_y - 1 + s->quarter_sample);          \
     }                                                                   \
 } while (0)
 
diff --git a/libavcodec/vc1data.c b/libavcodec/vc1data.c
index 57bc1fa9d6..be5cd3bffe 100644
--- a/libavcodec/vc1data.c
+++ b/libavcodec/vc1data.c
@@ -931,86 +931,75 @@ const uint8_t ff_vc1_subblkpat_tabs[3][15][2] = {
 };
 
 /* MV differential tables, p265 */
-const uint16_t ff_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 */
-  }
-};
-const uint8_t ff_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 */
-  }
+const uint8_t ff_vc1_mv_diff_tabs[4][73][2] = {
+    { /* Based upon table 246 */
+        { 0x08,  6 }, { 0x0C,  7 }, { 0x10,  7 }, { 0x14,  8 }, { 0x18, 14 },
+        { 0x34, 14 }, { 0x38, 14 }, { 0x74, 14 }, { 0x78, 14 }, { 0xA4, 14 },
+        { 0xA8, 14 }, { 0xAC, 14 }, { 0xB0, 13 }, { 0xB4, 13 }, { 0x00, 13 },
+        { 0x19, 13 }, { 0x58, 10 }, { 0x54,  9 }, { 0x30,  7 }, { 0x24,  6 },
+        { 0x28,  5 }, { 0x2C,  6 }, { 0x44,  6 }, { 0x48,  6 }, { 0x4C,  6 },
+        { 0x50,  8 }, { 0x64,  9 }, { 0x84, 10 }, { 0x8C, 10 }, { 0x68,  7 },
+        { 0x6C,  7 }, { 0x70,  7 }, { 0x88,  9 }, { 0x94, 10 }, { 0x98, 10 },
+        { 0x90,  8 }, { 0x11,  8 }, { 0x15,  9 }, { 0x39,  9 }, { 0x06,  6 },
+        { 0x09,  5 }, { 0x05,  3 }, { 0x0D,  6 }, { 0x35,  7 }, { 0x59,  9 },
+        { 0x79, 10 }, { 0xA5, 10 }, { 0x65,  8 }, { 0x25,  5 }, { 0x29,  4 },
+        { 0x2D,  4 }, { 0x31,  5 }, { 0x45,  6 }, { 0x55,  6 }, { 0x49,  5 },
+        { 0x4D,  5 }, { 0x51,  5 }, { 0x69,  5 }, { 0x6D,  5 }, { 0x71,  5 },
+        { 0x75,  7 }, { 0x85,  7 }, { 0x89,  7 }, { 0x8D,  7 }, { 0x91,  7 },
+        { 0x95,  7 }, { 0x99,  8 }, { 0xA9,  9 }, { 0xB1,  9 }, { 0xAD,  8 },
+        { 0xB5,  9 }, { 0x01,  9 }, { 0x07,  3 }, /* 73 elements */
+    },
+    { /* Based upon table 247 */
+        { 0x08,  5 }, { 0x0C,  7 }, { 0x10,  7 }, { 0x14,  6 }, { 0x18,  6 },
+        { 0x2C,  6 }, { 0x24,  5 }, { 0x28,  5 }, { 0x30,  7 }, { 0x38,  7 },
+        { 0x44,  8 }, { 0x48,  8 }, { 0x4C,  8 }, { 0x50, 14 }, { 0x6C, 14 },
+        { 0x70, 14 }, { 0x84, 14 }, { 0x8C, 14 }, { 0x90, 14 }, { 0x94, 14 },
+        { 0x98, 14 }, { 0xA4, 14 }, { 0xA8, 14 }, { 0xAC, 14 }, { 0xB0, 14 },
+        { 0xB4, 14 }, { 0x00, 14 }, { 0x06, 14 }, { 0x65, 14 }, { 0x85, 13 },
+        { 0x95, 13 }, { 0xA5, 13 }, { 0xA9, 13 }, { 0xAD, 13 }, { 0xB1, 13 },
+        { 0xB5, 13 }, { 0x01, 13 }, { 0x54,  9 }, { 0x34,  5 }, { 0x58,  9 },
+        { 0x64,  9 }, { 0x68,  8 }, { 0x74,  9 }, { 0x78,  9 }, { 0x88,  9 },
+        { 0x39,  9 }, { 0x0D,  6 }, { 0x05,  2 }, { 0x09,  3 }, { 0x11,  8 },
+        { 0x15,  8 }, { 0x31,  8 }, { 0x51,  8 }, { 0x19,  6 }, { 0x2D,  6 },
+        { 0x35,  6 }, { 0x29,  4 }, { 0x25,  3 }, { 0x45,  6 }, { 0x49,  6 },
+        { 0x4D,  6 }, { 0x55,  8 }, { 0x59,  8 }, { 0x69,  7 }, { 0x6D,  7 },
+        { 0x71,  8 }, { 0x79,  9 }, { 0x89,  9 }, { 0x75,  7 }, { 0x8D,  8 },
+        { 0x91,  9 }, { 0x99,  9 }, { 0x07,  5 }, /* 73 elements */
+    },
+    { /* Based upon table 248 */
+        { 0x08,  3 }, { 0x0C, 12 }, { 0x10, 12 }, { 0x14, 12 }, { 0x18, 12 },
+        { 0x2C, 11 }, { 0x30, 11 }, { 0x34, 11 }, { 0x38, 11 }, { 0x44, 11 },
+        { 0x48, 11 }, { 0x4C, 11 }, { 0x50, 11 }, { 0x54, 11 }, { 0x58, 11 },
+        { 0x64, 11 }, { 0x68, 11 }, { 0x6C, 11 }, { 0x70, 11 }, { 0x74, 11 },
+        { 0x78, 11 }, { 0x84, 11 }, { 0x88, 11 }, { 0x8C, 11 }, { 0x90, 11 },
+        { 0x94, 11 }, { 0x98, 11 }, { 0xA4, 11 }, { 0xA8, 11 }, { 0xAC, 11 },
+        { 0xB0, 11 }, { 0xB4, 11 }, { 0x00, 11 }, { 0x06, 11 }, { 0x0D, 11 },
+        { 0x11, 11 }, { 0x15, 11 }, { 0x19, 11 }, { 0x2D, 11 }, { 0x31, 11 },
+        { 0x35, 11 }, { 0x39, 11 }, { 0x45, 11 }, { 0x49, 11 }, { 0x4D, 11 },
+        { 0x51, 11 }, { 0x55, 11 }, { 0x59, 11 }, { 0x65, 11 }, { 0x69, 11 },
+        { 0x6D, 11 }, { 0x71, 11 }, { 0x75, 11 }, { 0x79, 11 }, { 0x85, 11 },
+        { 0x89, 11 }, { 0x8D, 11 }, { 0x91, 11 }, { 0x95, 11 }, { 0x99, 11 },
+        { 0xA5, 11 }, { 0xA9, 11 }, { 0xAD, 11 }, { 0xB1, 11 }, { 0xB5, 11 },
+        { 0x01, 11 }, { 0x07, 11 }, { 0x09,  5 }, { 0x28,  4 }, { 0x24,  3 },
+        { 0x25,  4 }, { 0x29,  4 }, { 0x05,  1 }, /* 73 elements */
+    },
+    { /* Based upon table 249 */
+        { 0x08, 15 }, { 0x10, 15 }, { 0x14, 15 }, { 0x18, 15 }, { 0x24, 15 },
+        { 0x2C, 15 }, { 0x48, 15 }, { 0x64, 15 }, { 0x28, 12 }, { 0x0C, 11 },
+        { 0x30, 12 }, { 0x38, 12 }, { 0x34, 11 }, { 0x44, 12 }, { 0x4C, 12 },
+        { 0x50, 12 }, { 0x54, 12 }, { 0x58, 12 }, { 0x68, 15 }, { 0x70, 15 },
+        { 0x98, 15 }, { 0xA4, 15 }, { 0xA8, 15 }, { 0xB0, 15 }, { 0x00, 14 },
+        { 0x6C, 12 }, { 0x84, 12 }, { 0x74, 10 }, { 0x78, 11 }, { 0x88, 11 },
+        { 0x8C, 10 }, { 0x90, 11 }, { 0xAC, 11 }, { 0x94, 10 }, { 0xB4, 10 },
+        { 0x06, 10 }, { 0xA5, 10 }, { 0x15,  8 }, { 0x11,  7 }, { 0x19,  9 },
+        { 0x85,  9 }, { 0x39,  8 }, { 0x0D,  5 }, { 0x05,  4 }, { 0x09,  4 },
+        { 0x25,  5 }, { 0x31,  5 }, { 0x29,  3 }, { 0x2D,  4 }, { 0x35,  6 },
+        { 0x55,  6 }, { 0x45,  5 }, { 0x49,  4 }, { 0x51,  5 }, { 0x59,  8 },
+        { 0xA9,  8 }, { 0x65,  7 }, { 0x75,  6 }, { 0x4D,  3 }, { 0x69,  5 },
+        { 0x6D,  5 }, { 0x71,  5 }, { 0x79,  7 }, { 0x89,  7 }, { 0x8D,  6 },
+        { 0x91,  6 }, { 0x95,  6 }, { 0x99,  7 }, { 0xAD,  8 }, { 0xB1,  8 },
+        { 0xB5,  7 }, { 0x01,  7 }, { 0x07,  4 }, /* 73 elements */
+    },
 };
 
 /* DC differentials low+hi-mo, p217 are the same as in msmpeg4data .h */
diff --git a/libavcodec/vc1data.h b/libavcodec/vc1data.h
index 136e48e773..ccd2a0ec57 100644
--- a/libavcodec/vc1data.h
+++ b/libavcodec/vc1data.h
@@ -153,9 +153,17 @@ extern const uint8_t ff_vc1_ttblk_tabs[3][8][2];
  * The symbols contain the Subblock Pattern. */
 extern const uint8_t ff_vc1_subblkpat_tabs[3][15][2];
 
-/* MV differential tables, p265 */
-extern const uint16_t ff_vc1_mv_diff_codes[4][73];
-extern const uint8_t ff_vc1_mv_diff_bits[4][73];
+/*
+ * MV differential tables. Based upon tables #246-249.
+ *
+ * After offsetting the symbols by -4 the symbols contain all
+ * relevant information: The 0x01 bit contains 'more_present_flag',
+ * the 0x02 bit contains 'intra_flag'. The case of a negative symbol
+ * corresponds to the escape mechanism (i.e. index == 35 in the spec).
+ * Otherwise if the 0xFC bits are zero, both motion vectors are zero
+ * (index == 0 and index == 36 in the spec); otherwise the 0x1C bits
+ * contain the spec's index % 6 and bits 0xE0 contain index / 6. */
+extern const uint8_t ff_vc1_mv_diff_tabs[4][73][2];
 
 /* Interlaced frame picture MBMODE VLC tables (p. 246, p. 360) */
 extern const uint16_t ff_vc1_intfr_4mv_mbmode_codes[4][15];
-- 
2.25.1



More information about the ffmpeg-devel mailing list