]> git.sesse.net Git - ffmpeg/blob - libavcodec/cavsdata.h
fix -a^b which was interpreted as (-a)^b
[ffmpeg] / libavcodec / cavsdata.h
1 /*
2  * Chinese AVS video (AVS1-P2, JiZhun profile) decoder.
3  * Copyright (c) 2006  Stefan Gehrer <stefan.gehrer@gmx.de>
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #define SLICE_MIN_START_CODE    0x00000101
23 #define SLICE_MAX_START_CODE    0x000001af
24 #define EXT_START_CODE          0x000001b5
25 #define USER_START_CODE         0x000001b2
26 #define SEQ_START_CODE          0x000001b0
27 #define PIC_I_START_CODE        0x000001b3
28 #define PIC_PB_START_CODE       0x000001b6
29
30 #define A_AVAIL                          1
31 #define B_AVAIL                          2
32 #define C_AVAIL                          4
33 #define D_AVAIL                          8
34 #define NOT_AVAIL                       -1
35 #define REF_INTRA                       -2
36 #define REF_DIR                         -3
37
38 #define ESCAPE_CODE                     59
39
40 #define FWD0                          0x01
41 #define FWD1                          0x02
42 #define BWD0                          0x04
43 #define BWD1                          0x08
44 #define SYM0                          0x10
45 #define SYM1                          0x20
46 #define SPLITH                        0x40
47 #define SPLITV                        0x80
48
49 #define MV_BWD_OFFS                     12
50 #define MV_STRIDE                        4
51
52 enum mb_t {
53   I_8X8 = 0,
54   P_SKIP,
55   P_16X16,
56   P_16X8,
57   P_8X16,
58   P_8X8,
59   B_SKIP,
60   B_DIRECT,
61   B_FWD_16X16,
62   B_BWD_16X16,
63   B_SYM_16X16,
64   B_8X8 = 29
65 };
66
67 enum sub_mb_t {
68   B_SUB_DIRECT,
69   B_SUB_FWD,
70   B_SUB_BWD,
71   B_SUB_SYM
72 };
73
74 enum intra_luma_t {
75   INTRA_L_VERT,
76   INTRA_L_HORIZ,
77   INTRA_L_LP,
78   INTRA_L_DOWN_LEFT,
79   INTRA_L_DOWN_RIGHT,
80   INTRA_L_LP_LEFT,
81   INTRA_L_LP_TOP,
82   INTRA_L_DC_128
83 };
84
85 enum intra_chroma_t {
86   INTRA_C_LP,
87   INTRA_C_HORIZ,
88   INTRA_C_VERT,
89   INTRA_C_PLANE,
90   INTRA_C_LP_LEFT,
91   INTRA_C_LP_TOP,
92   INTRA_C_DC_128,
93 };
94
95 enum mv_pred_t {
96   MV_PRED_MEDIAN,
97   MV_PRED_LEFT,
98   MV_PRED_TOP,
99   MV_PRED_TOPRIGHT,
100   MV_PRED_PSKIP,
101   MV_PRED_BSKIP
102 };
103
104 enum block_t {
105   BLK_16X16,
106   BLK_16X8,
107   BLK_8X16,
108   BLK_8X8
109 };
110
111 enum mv_loc_t {
112   MV_FWD_D3 = 0,
113   MV_FWD_B2,
114   MV_FWD_B3,
115   MV_FWD_C2,
116   MV_FWD_A1,
117   MV_FWD_X0,
118   MV_FWD_X1,
119   MV_FWD_A3 = 8,
120   MV_FWD_X2,
121   MV_FWD_X3,
122   MV_BWD_D3 = MV_BWD_OFFS,
123   MV_BWD_B2,
124   MV_BWD_B3,
125   MV_BWD_C2,
126   MV_BWD_A1,
127   MV_BWD_X0,
128   MV_BWD_X1,
129   MV_BWD_A3 = MV_BWD_OFFS+8,
130   MV_BWD_X2,
131   MV_BWD_X3
132 };
133
134 static const uint8_t partition_flags[30] = {
135   0,                                 //I_8X8
136   0,                                 //P_SKIP
137   0,                                 //P_16X16
138                       SPLITH,        //P_16X8
139                              SPLITV, //P_8X16
140                       SPLITH|SPLITV, //P_8X8
141                       SPLITH|SPLITV, //B_SKIP
142                       SPLITH|SPLITV, //B_DIRECT
143   0,                                 //B_FWD_16X16
144   0,                                 //B_BWD_16X16
145   0,                                 //B_SYM_16X16
146   FWD0|FWD1          |SPLITH,
147   FWD0|FWD1                 |SPLITV,
148   BWD0|BWD1          |SPLITH,
149   BWD0|BWD1                 |SPLITV,
150   FWD0|BWD1          |SPLITH,
151   FWD0|BWD1                 |SPLITV,
152   BWD0|FWD1          |SPLITH,
153   BWD0|FWD1                 |SPLITV,
154   FWD0|FWD1     |SYM1|SPLITH,
155   FWD0|FWD1     |SYM1       |SPLITV,
156   BWD0|FWD1     |SYM1|SPLITH,
157   BWD0|FWD1     |SYM1       |SPLITV,
158   FWD0|FWD1|SYM0     |SPLITH,
159   FWD0|FWD1|SYM0            |SPLITV,
160   FWD0|BWD1|SYM0     |SPLITH,
161   FWD0|BWD1|SYM0            |SPLITV,
162   FWD0|FWD1|SYM0|SYM1|SPLITH,
163   FWD0|FWD1|SYM0|SYM1       |SPLITV,
164                       SPLITH|SPLITV, //B_8X8 = 29
165 };
166
167 static const uint8_t scan3x3[4] = {4,5,7,8};
168
169 static const uint8_t mv_scan[4] = {
170     MV_FWD_X0,MV_FWD_X1,
171     MV_FWD_X2,MV_FWD_X3
172 };
173
174 static const uint8_t cbp_tab[64][2] = {
175   {63, 0},{15,15},{31,63},{47,31},{ 0,16},{14,32},{13,47},{11,13},
176   { 7,14},{ 5,11},{10,12},{ 8, 5},{12,10},{61, 7},{ 4,48},{55, 3},
177   { 1, 2},{ 2, 8},{59, 4},{ 3, 1},{62,61},{ 9,55},{ 6,59},{29,62},
178   {45,29},{51,27},{23,23},{39,19},{27,30},{46,28},{53, 9},{30, 6},
179   {43,60},{37,21},{60,44},{16,26},{21,51},{28,35},{19,18},{35,20},
180   {42,24},{26,53},{44,17},{32,37},{58,39},{24,45},{20,58},{17,43},
181   {18,42},{48,46},{22,36},{33,33},{25,34},{49,40},{40,52},{36,49},
182   {34,50},{50,56},{52,25},{54,22},{41,54},{56,57},{38,41},{57,38}
183 };
184
185 static const uint8_t chroma_qp[64] = {
186   0,  1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,
187   16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
188   32,33,34,35,36,37,38,39,40,41,42,42,43,43,44,44,
189   45,45,46,46,47,47,48,48,48,49,49,49,50,50,50,51
190 };
191
192 static const uint8_t dequant_shift[64] = {
193   14,14,14,14,14,14,14,14,
194   13,13,13,13,13,13,13,13,
195   13,12,12,12,12,12,12,12,
196   11,11,11,11,11,11,11,11,
197   11,10,10,10,10,10,10,10,
198   10, 9, 9, 9, 9, 9, 9, 9,
199   9, 8, 8, 8, 8, 8, 8, 8,
200   7, 7, 7, 7, 7, 7, 7, 7
201 };
202
203 static const uint16_t dequant_mul[64] = {
204   32768,36061,38968,42495,46341,50535,55437,60424,
205   32932,35734,38968,42495,46177,50535,55109,59933,
206   65535,35734,38968,42577,46341,50617,55027,60097,
207   32809,35734,38968,42454,46382,50576,55109,60056,
208   65535,35734,38968,42495,46320,50515,55109,60076,
209   65535,35744,38968,42495,46341,50535,55099,60087,
210   65535,35734,38973,42500,46341,50535,55109,60097,
211   32771,35734,38965,42497,46341,50535,55109,60099
212 };
213
214 DECLARE_ALIGNED_8(typedef, struct) {
215     int16_t x;
216     int16_t y;
217     int16_t dist;
218     int16_t ref;
219 } vector_t;
220
221 /** marks block as unavailable, i.e. out of picture
222     or not yet decoded */
223 static const vector_t un_mv    = {0,0,1,NOT_AVAIL};
224
225 /** marks block as "no prediction from this direction"
226     e.g. forward motion vector in BWD partition */
227 static const vector_t dir_mv   = {0,0,1,REF_DIR};
228
229 /** marks block as using intra prediction */
230 static const vector_t intra_mv = {0,0,1,REF_INTRA};
231
232 typedef struct residual_vlc_t {
233   int8_t rltab[59][3];
234   int8_t level_add[27];
235   int8_t golomb_order;
236   int inc_limit;
237   int8_t max_run;
238 } residual_vlc_t;
239
240 #define EOB 0,0,0
241
242 static const residual_vlc_t intra_2dvlc[7] = {
243   {
244     { //level / run / table_inc
245       {  1, 1, 1},{ -1, 1, 1},{  1, 2, 1},{ -1, 2, 1},{  1, 3, 1},{ -1, 3, 1},
246       {  1, 4, 1},{ -1, 4, 1},{  1, 5, 1},{ -1, 5, 1},{  1, 6, 1},{ -1, 6, 1},
247       {  1, 7, 1},{ -1, 7, 1},{  1, 8, 1},{ -1, 8, 1},{  1, 9, 1},{ -1, 9, 1},
248       {  1,10, 1},{ -1,10, 1},{  1,11, 1},{ -1,11, 1},{  2, 1, 2},{ -2, 1, 2},
249       {  1,12, 1},{ -1,12, 1},{  1,13, 1},{ -1,13, 1},{  1,14, 1},{ -1,14, 1},
250       {  1,15, 1},{ -1,15, 1},{  2, 2, 2},{ -2, 2, 2},{  1,16, 1},{ -1,16, 1},
251       {  1,17, 1},{ -1,17, 1},{  3, 1, 3},{ -3, 1, 3},{  1,18, 1},{ -1,18, 1},
252       {  1,19, 1},{ -1,19, 1},{  2, 3, 2},{ -2, 3, 2},{  1,20, 1},{ -1,20, 1},
253       {  1,21, 1},{ -1,21, 1},{  2, 4, 2},{ -2, 4, 2},{  1,22, 1},{ -1,22, 1},
254       {  2, 5, 2},{ -2, 5, 2},{  1,23, 1},{ -1,23, 1},{   EOB   }
255     },
256     //level_add
257     { 0, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
258       2, 2, 2, 2, 2, 2, 2,-1,-1,-1},
259     2, //golomb_order
260     0, //inc_limit
261     23, //max_run
262   },{
263     { //level / run
264       {  1, 1, 0},{ -1, 1, 0},{  1, 2, 0},{ -1, 2, 0},{  2, 1, 1},{ -2, 1, 1},
265       {  1, 3, 0},{ -1, 3, 0},{   EOB   },{  1, 4, 0},{ -1, 4, 0},{  1, 5, 0},
266       { -1, 5, 0},{  1, 6, 0},{ -1, 6, 0},{  3, 1, 2},{ -3, 1, 2},{  2, 2, 1},
267       { -2, 2, 1},{  1, 7, 0},{ -1, 7, 0},{  1, 8, 0},{ -1, 8, 0},{  1, 9, 0},
268       { -1, 9, 0},{  2, 3, 1},{ -2, 3, 1},{  4, 1, 2},{ -4, 1, 2},{  1,10, 0},
269       { -1,10, 0},{  1,11, 0},{ -1,11, 0},{  2, 4, 1},{ -2, 4, 1},{  3, 2, 2},
270       { -3, 2, 2},{  1,12, 0},{ -1,12, 0},{  2, 5, 1},{ -2, 5, 1},{  5, 1, 3},
271       { -5, 1, 3},{  1,13, 0},{ -1,13, 0},{  2, 6, 1},{ -2, 6, 1},{  1,14, 0},
272       { -1,14, 0},{  2, 7, 1},{ -2, 7, 1},{  2, 8, 1},{ -2, 8, 1},{  3, 3, 2},
273       { -3, 3, 2},{  6, 1, 3},{ -6, 1, 3},{  1,15, 0},{ -1,15, 0}
274     },
275     //level_add
276     { 0, 7, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2,-1,
277       -1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
278     2, //golomb_order
279     1, //inc_limit
280     15, //max_run
281   },{
282     { //level / run
283       {  1, 1, 0},{ -1, 1, 0},{  2, 1, 0},{ -2, 1, 0},{  1, 2, 0},{ -1, 2, 0},
284       {  3, 1, 1},{ -3, 1, 1},{   EOB   },{  1, 3, 0},{ -1, 3, 0},{  2, 2, 0},
285       { -2, 2, 0},{  4, 1, 1},{ -4, 1, 1},{  1, 4, 0},{ -1, 4, 0},{  5, 1, 2},
286       { -5, 1, 2},{  1, 5, 0},{ -1, 5, 0},{  3, 2, 1},{ -3, 2, 1},{  2, 3, 0},
287       { -2, 3, 0},{  1, 6, 0},{ -1, 6, 0},{  6, 1, 2},{ -6, 1, 2},{  2, 4, 0},
288       { -2, 4, 0},{  1, 7, 0},{ -1, 7, 0},{  4, 2, 1},{ -4, 2, 1},{  7, 1, 2},
289       { -7, 1, 2},{  3, 3, 1},{ -3, 3, 1},{  2, 5, 0},{ -2, 5, 0},{  1, 8, 0},
290       { -1, 8, 0},{  2, 6, 0},{ -2, 6, 0},{  8, 1, 3},{ -8, 1, 3},{  1, 9, 0},
291       { -1, 9, 0},{  5, 2, 2},{ -5, 2, 2},{  3, 4, 1},{ -3, 4, 1},{  2, 7, 0},
292       { -2, 7, 0},{  9, 1, 3},{ -9, 1, 3},{  1,10, 0},{ -1,10, 0}
293     },
294     //level_add
295     { 0,10, 6, 4, 4, 3, 3, 3, 2, 2, 2,-1,-1,-1,-1,-1,-1,
296      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
297     2, //golomb_order
298     2, //inc_limit
299     10, //max_run
300   },{
301     { //level / run
302       {  1, 1, 0},{ -1, 1, 0},{  2, 1, 0},{ -2, 1, 0},{  3, 1, 0},{ -3, 1, 0},
303       {  1, 2, 0},{ -1, 2, 0},{   EOB   },{  4, 1, 0},{ -4, 1, 0},{  5, 1, 1},
304       { -5, 1, 1},{  2, 2, 0},{ -2, 2, 0},{  1, 3, 0},{ -1, 3, 0},{  6, 1, 1},
305       { -6, 1, 1},{  3, 2, 0},{ -3, 2, 0},{  7, 1, 1},{ -7, 1, 1},{  1, 4, 0},
306       { -1, 4, 0},{  8, 1, 2},{ -8, 1, 2},{  2, 3, 0},{ -2, 3, 0},{  4, 2, 0},
307       { -4, 2, 0},{  1, 5, 0},{ -1, 5, 0},{  9, 1, 2},{ -9, 1, 2},{  5, 2, 1},
308       { -5, 2, 1},{  2, 4, 0},{ -2, 4, 0},{ 10, 1, 2},{-10, 1, 2},{  3, 3, 0},
309       { -3, 3, 0},{  1, 6, 0},{ -1, 6, 0},{ 11, 1, 3},{-11, 1, 3},{  6, 2, 1},
310       { -6, 2, 1},{  1, 7, 0},{ -1, 7, 0},{  2, 5, 0},{ -2, 5, 0},{  3, 4, 0},
311       { -3, 4, 0},{ 12, 1, 3},{-12, 1, 3},{  4, 3, 0},{ -4, 3, 0}
312     },
313     //level_add
314     { 0,13, 7, 5, 4, 3, 2, 2,-1,-1,-1 -1,-1,-1,-1,-1,-1,
315      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
316     2, //golomb_order
317     4, //inc_limit
318     7, //max_run
319   },{
320     { //level / run
321       {  1, 1, 0},{ -1, 1, 0},{  2, 1, 0},{ -2, 1, 0},{  3, 1, 0},{ -3, 1, 0},
322       {   EOB   },{  4, 1, 0},{ -4, 1, 0},{  5, 1, 0},{ -5, 1, 0},{  6, 1, 0},
323       { -6, 1, 0},{  1, 2, 0},{ -1, 2, 0},{  7, 1, 0},{ -7, 1, 0},{  8, 1, 1},
324       { -8, 1, 1},{  2, 2, 0},{ -2, 2, 0},{  9, 1, 1},{ -9, 1, 1},{ 10, 1, 1},
325       {-10, 1, 1},{  1, 3, 0},{ -1, 3, 0},{  3, 2, 0},{ -3, 2, 0},{ 11, 1, 2},
326       {-11, 1, 2},{  4, 2, 0},{ -4, 2, 0},{ 12, 1, 2},{-12, 1, 2},{ 13, 1, 2},
327       {-13, 1, 2},{  5, 2, 0},{ -5, 2, 0},{  1, 4, 0},{ -1, 4, 0},{  2, 3, 0},
328       { -2, 3, 0},{ 14, 1, 2},{-14, 1, 2},{  6, 2, 0},{ -6, 2, 0},{ 15, 1, 2},
329       {-15, 1, 2},{ 16, 1, 2},{-16, 1, 2},{  3, 3, 0},{ -3, 3, 0},{  1, 5, 0},
330       { -1, 5, 0},{  7, 2, 0},{ -7, 2, 0},{ 17, 1, 2},{-17, 1, 2}
331     },
332     //level_add
333     { 0,18, 8, 4, 2, 2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
334      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
335     2, //golomb_order
336     7, //inc_limit
337     5, //max_run
338   },{
339     { //level / run
340       {   EOB   },{  1, 1, 0},{ -1, 1, 0},{  2, 1, 0},{ -2, 1, 0},{  3, 1, 0},
341       { -3, 1, 0},{  4, 1, 0},{ -4, 1, 0},{  5, 1, 0},{ -5, 1, 0},{  6, 1, 0},
342       { -6, 1, 0},{  7, 1, 0},{ -7, 1, 0},{  8, 1, 0},{ -8, 1, 0},{  9, 1, 0},
343       { -9, 1, 0},{ 10, 1, 0},{-10, 1, 0},{  1, 2, 0},{ -1, 2, 0},{ 11, 1, 1},
344       {-11, 1, 1},{ 12, 1, 1},{-12, 1, 1},{ 13, 1, 1},{-13, 1, 1},{  2, 2, 0},
345       { -2, 2, 0},{ 14, 1, 1},{-14, 1, 1},{ 15, 1, 1},{-15, 1, 1},{  3, 2, 0},
346       { -3, 2, 0},{ 16, 1, 1},{-16, 1, 1},{  1, 3, 0},{ -1, 3, 0},{ 17, 1, 1},
347       {-17, 1, 1},{  4, 2, 0},{ -4, 2, 0},{ 18, 1, 1},{-18, 1, 1},{  5, 2, 0},
348       { -5, 2, 0},{ 19, 1, 1},{-19, 1, 1},{ 20, 1, 1},{-20, 1, 1},{  6, 2, 0},
349       { -6, 2, 0},{ 21, 1, 1},{-21, 1, 1},{  2, 3, 0},{ -2, 3, 0}
350     },
351     //level_add
352     { 0,22, 7, 3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
353      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
354     2, //golomb_order
355     10, //inc_limit
356     3, //max_run
357   },{
358     { //level / run
359       {   EOB   },{  1, 1, 0},{ -1, 1, 0},{  2, 1, 0},{ -2, 1, 0},{  3, 1, 0},
360       { -3, 1, 0},{  4, 1, 0},{ -4, 1, 0},{  5, 1, 0},{ -5, 1, 0},{  6, 1, 0},
361       { -6, 1, 0},{  7, 1, 0},{ -7, 1, 0},{  8, 1, 0},{ -8, 1, 0},{  9, 1, 0},
362       { -9, 1, 0},{ 10, 1, 0},{-10, 1, 0},{ 11, 1, 0},{-11, 1, 0},{ 12, 1, 0},
363       {-12, 1, 0},{ 13, 1, 0},{-13, 1, 0},{ 14, 1, 0},{-14, 1, 0},{ 15, 1, 0},
364       {-15, 1, 0},{ 16, 1, 0},{-16, 1, 0},{  1, 2, 0},{ -1, 2, 0},{ 17, 1, 0},
365       {-17, 1, 0},{ 18, 1, 0},{-18, 1, 0},{ 19, 1, 0},{-19, 1, 0},{ 20, 1, 0},
366       {-20, 1, 0},{ 21, 1, 0},{-21, 1, 0},{  2, 2, 0},{ -2, 2, 0},{ 22, 1, 0},
367       {-22, 1, 0},{ 23, 1, 0},{-23, 1, 0},{ 24, 1, 0},{-24, 1, 0},{ 25, 1, 0},
368       {-25, 1, 0},{  3, 2, 0},{ -3, 2, 0},{ 26, 1, 0},{-26, 1, 0}
369     },
370     //level_add
371     { 0,27, 4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
372      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
373     2, //golomb_order
374     INT_MAX, //inc_limit
375     2, //max_run
376   }
377 };
378
379 static const residual_vlc_t inter_2dvlc[7] = {
380   {
381     { //level / run
382       {  1, 1, 1},{ -1, 1, 1},{  1, 2, 1},{ -1, 2, 1},{  1, 3, 1},{ -1, 3, 1},
383       {  1, 4, 1},{ -1, 4, 1},{  1, 5, 1},{ -1, 5, 1},{  1, 6, 1},{ -1, 6, 1},
384       {  1, 7, 1},{ -1, 7, 1},{  1, 8, 1},{ -1, 8, 1},{  1, 9, 1},{ -1, 9, 1},
385       {  1,10, 1},{ -1,10, 1},{  1,11, 1},{ -1,11, 1},{  1,12, 1},{ -1,12, 1},
386       {  1,13, 1},{ -1,13, 1},{  2, 1, 2},{ -2, 1, 2},{  1,14, 1},{ -1,14, 1},
387       {  1,15, 1},{ -1,15, 1},{  1,16, 1},{ -1,16, 1},{  1,17, 1},{ -1,17, 1},
388       {  1,18, 1},{ -1,18, 1},{  1,19, 1},{ -1,19, 1},{  3, 1, 3},{ -3, 1, 3},
389       {  1,20, 1},{ -1,20, 1},{  1,21, 1},{ -1,21, 1},{  2, 2, 2},{ -2, 2, 2},
390       {  1,22, 1},{ -1,22, 1},{  1,23, 1},{ -1,23, 1},{  1,24, 1},{ -1,24, 1},
391       {  1,25, 1},{ -1,25, 1},{  1,26, 1},{ -1,26, 1},{   EOB   }
392     },
393     //level_add
394     { 0, 4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
395       2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
396     3, //golomb_order
397     0, //inc_limit
398     26 //max_run
399   },{
400     { //level / run
401       {  1, 1, 0},{ -1, 1, 0},{   EOB   },{  1, 2, 0},{ -1, 2, 0},{  1, 3, 0},
402       { -1, 3, 0},{  1, 4, 0},{ -1, 4, 0},{  1, 5, 0},{ -1, 5, 0},{  1, 6, 0},
403       { -1, 6, 0},{  2, 1, 1},{ -2, 1, 1},{  1, 7, 0},{ -1, 7, 0},{  1, 8, 0},
404       { -1, 8, 0},{  1, 9, 0},{ -1, 9, 0},{  1,10, 0},{ -1,10, 0},{  2, 2, 1},
405       { -2, 2, 1},{  1,11, 0},{ -1,11, 0},{  1,12, 0},{ -1,12, 0},{  3, 1, 2},
406       { -3, 1, 2},{  1,13, 0},{ -1,13, 0},{  1,14, 0},{ -1,14, 0},{  2, 3, 1},
407       { -2, 3, 1},{  1,15, 0},{ -1,15, 0},{  2, 4, 1},{ -2, 4, 1},{  1,16, 0},
408       { -1,16, 0},{  2, 5, 1},{ -2, 5, 1},{  1,17, 0},{ -1,17, 0},{  4, 1, 3},
409       { -4, 1, 3},{  2, 6, 1},{ -2, 6, 1},{  1,18, 0},{ -1,18, 0},{  1,19, 0},
410       { -1,19, 0},{  2, 7, 1},{ -2, 7, 1},{  3, 2, 2},{ -3, 2, 2}
411     },
412     //level_add
413     { 0, 5, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2,
414       2, 2, 2,-1,-1,-1,-1,-1,-1,-1},
415     2, //golomb_order
416     1, //inc_limit
417     19 //max_run
418   },{
419     { //level / run
420       {  1, 1, 0},{ -1, 1, 0},{   EOB   },{  1, 2, 0},{ -1, 2, 0},{  2, 1, 0},
421       { -2, 1, 0},{  1, 3, 0},{ -1, 3, 0},{  1, 4, 0},{ -1, 4, 0},{  3, 1, 1},
422       { -3, 1, 1},{  2, 2, 0},{ -2, 2, 0},{  1, 5, 0},{ -1, 5, 0},{  1, 6, 0},
423       { -1, 6, 0},{  1, 7, 0},{ -1, 7, 0},{  2, 3, 0},{ -2, 3, 0},{  4, 1, 2},
424       { -4, 1, 2},{  1, 8, 0},{ -1, 8, 0},{  3, 2, 1},{ -3, 2, 1},{  2, 4, 0},
425       { -2, 4, 0},{  1, 9, 0},{ -1, 9, 0},{  1,10, 0},{ -1,10, 0},{  5, 1, 2},
426       { -5, 1, 2},{  2, 5, 0},{ -2, 5, 0},{  1,11, 0},{ -1,11, 0},{  2, 6, 0},
427       { -2, 6, 0},{  1,12, 0},{ -1,12, 0},{  3, 3, 1},{ -3, 3, 1},{  6, 1, 2},
428       { -6, 1, 2},{  4, 2, 2},{ -4, 2, 2},{  1,13, 0},{ -1,13, 0},{  2, 7, 0},
429       { -2, 7, 0},{  3, 4, 1},{ -3, 4, 1},{  1,14, 0},{ -1,14, 0}
430     },
431     //level_add
432     { 0, 7, 5, 4, 4, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2,-1,-1,
433       -1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
434     2, //golomb_order
435     2, //inc_limit
436     14 //max_run
437   },{
438     { //level / run
439       {  1, 1, 0},{ -1, 1, 0},{   EOB   },{  2, 1, 0},{ -2, 1, 0},{  1, 2, 0},
440       { -1, 2, 0},{  3, 1, 0},{ -3, 1, 0},{  1, 3, 0},{ -1, 3, 0},{  2, 2, 0},
441       { -2, 2, 0},{  4, 1, 1},{ -4, 1, 1},{  1, 4, 0},{ -1, 4, 0},{  5, 1, 1},
442       { -5, 1, 1},{  1, 5, 0},{ -1, 5, 0},{  3, 2, 0},{ -3, 2, 0},{  2, 3, 0},
443       { -2, 3, 0},{  1, 6, 0},{ -1, 6, 0},{  6, 1, 1},{ -6, 1, 1},{  2, 4, 0},
444       { -2, 4, 0},{  1, 7, 0},{ -1, 7, 0},{  4, 2, 1},{ -4, 2, 1},{  7, 1, 2},
445       { -7, 1, 2},{  3, 3, 0},{ -3, 3, 0},{  1, 8, 0},{ -1, 8, 0},{  2, 5, 0},
446       { -2, 5, 0},{  8, 1, 2},{ -8, 1, 2},{  1, 9, 0},{ -1, 9, 0},{  3, 4, 0},
447       { -3, 4, 0},{  2, 6, 0},{ -2, 6, 0},{  5, 2, 1},{ -5, 2, 1},{  1,10, 0},
448       { -1,10, 0},{  9, 1, 2},{ -9, 1, 2},{  4, 3, 1},{ -4, 3, 1}
449     },
450     //level_add
451     { 0,10, 6, 5, 4, 3, 3, 2, 2, 2, 2,-1,-1,-1,-1,-1,-1,
452      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
453     2, //golomb_order
454     3, //inc_limit
455     10 //max_run
456   },{
457     { //level / run
458       {  1, 1, 0},{ -1, 1, 0},{   EOB   },{  2, 1, 0},{ -2, 1, 0},{  3, 1, 0},
459       { -3, 1, 0},{  1, 2, 0},{ -1, 2, 0},{  4, 1, 0},{ -4, 1, 0},{  5, 1, 0},
460       { -5, 1, 0},{  2, 2, 0},{ -2, 2, 0},{  1, 3, 0},{ -1, 3, 0},{  6, 1, 0},
461       { -6, 1, 0},{  3, 2, 0},{ -3, 2, 0},{  7, 1, 1},{ -7, 1, 1},{  1, 4, 0},
462       { -1, 4, 0},{  8, 1, 1},{ -8, 1, 1},{  2, 3, 0},{ -2, 3, 0},{  4, 2, 0},
463       { -4, 2, 0},{  1, 5, 0},{ -1, 5, 0},{  9, 1, 1},{ -9, 1, 1},{  5, 2, 0},
464       { -5, 2, 0},{  2, 4, 0},{ -2, 4, 0},{  1, 6, 0},{ -1, 6, 0},{ 10, 1, 2},
465       {-10, 1, 2},{  3, 3, 0},{ -3, 3, 0},{ 11, 1, 2},{-11, 1, 2},{  1, 7, 0},
466       { -1, 7, 0},{  6, 2, 0},{ -6, 2, 0},{  3, 4, 0},{ -3, 4, 0},{  2, 5, 0},
467       { -2, 5, 0},{ 12, 1, 2},{-12, 1, 2},{  4, 3, 0},{ -4, 3, 0}
468     },
469     //level_add
470     { 0,13, 7, 5, 4, 3, 2, 2,-1,-1,-1,-1,-1,-1,-1,-1,-1,
471      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
472     2, //golomb_order
473     6, //inc_limit
474     7  //max_run
475   },{
476     { //level / run
477       {   EOB   },{  1, 1, 0},{ -1, 1, 0},{  2, 1, 0},{ -2, 1, 0},{  3, 1, 0},
478       { -3, 1, 0},{  4, 1, 0},{ -4, 1, 0},{  5, 1, 0},{ -5, 1, 0},{  1, 2, 0},
479       { -1, 2, 0},{  6, 1, 0},{ -6, 1, 0},{  7, 1, 0},{ -7, 1, 0},{  8, 1, 0},
480       { -8, 1, 0},{  2, 2, 0},{ -2, 2, 0},{  9, 1, 0},{ -9, 1, 0},{  1, 3, 0},
481       { -1, 3, 0},{ 10, 1, 1},{-10, 1, 1},{  3, 2, 0},{ -3, 2, 0},{ 11, 1, 1},
482       {-11, 1, 1},{  4, 2, 0},{ -4, 2, 0},{ 12, 1, 1},{-12, 1, 1},{  1, 4, 0},
483       { -1, 4, 0},{  2, 3, 0},{ -2, 3, 0},{ 13, 1, 1},{-13, 1, 1},{  5, 2, 0},
484       { -5, 2, 0},{ 14, 1, 1},{-14, 1, 1},{  6, 2, 0},{ -6, 2, 0},{  1, 5, 0},
485       { -1, 5, 0},{ 15, 1, 1},{-15, 1, 1},{  3, 3, 0},{ -3, 3, 0},{ 16, 1, 1},
486       {-16, 1, 1},{  2, 4, 0},{ -2, 4, 0},{  7, 2, 0},{ -7, 2, 0}
487     },
488     //level_add
489     { 0,17, 8, 4, 3, 2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
490      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
491     2, //golomb_order
492     9, //inc_limit
493     5  //max_run
494   },{
495     { //level / run
496       {   EOB   },{  1, 1, 0},{ -1, 1, 0},{  2, 1, 0},{ -2, 1, 0},{  3, 1, 0},
497       { -3, 1, 0},{  4, 1, 0},{ -4, 1, 0},{  5, 1, 0},{ -5, 1, 0},{  6, 1, 0},
498       { -6, 1, 0},{  7, 1, 0},{ -7, 1, 0},{  1, 2, 0},{ -1, 2, 0},{  8, 1, 0},
499       { -8, 1, 0},{  9, 1, 0},{ -9, 1, 0},{ 10, 1, 0},{-10, 1, 0},{ 11, 1, 0},
500       {-11, 1, 0},{ 12, 1, 0},{-12, 1, 0},{  2, 2, 0},{ -2, 2, 0},{ 13, 1, 0},
501       {-13, 1, 0},{  1, 3, 0},{ -1, 3, 0},{ 14, 1, 0},{-14, 1, 0},{ 15, 1, 0},
502       {-15, 1, 0},{  3, 2, 0},{ -3, 2, 0},{ 16, 1, 0},{-16, 1, 0},{ 17, 1, 0},
503       {-17, 1, 0},{ 18, 1, 0},{-18, 1, 0},{  4, 2, 0},{ -4, 2, 0},{ 19, 1, 0},
504       {-19, 1, 0},{ 20, 1, 0},{-20, 1, 0},{  2, 3, 0},{ -2, 3, 0},{  1, 4, 0},
505       { -1, 4, 0},{  5, 2, 0},{ -5, 2, 0},{ 21, 1, 0},{-21, 1, 0}
506     },
507     //level_add
508     { 0,22, 6, 3, 2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
509      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
510     2, //golomb_order
511     INT_MAX, //inc_limit
512     4 //max_run
513   }
514 };
515
516 static const residual_vlc_t chroma_2dvlc[5] = {
517   {
518     { //level / run
519       {  1, 1, 1},{ -1, 1, 1},{  1, 2, 1},{ -1, 2, 1},{  1, 3, 1},{ -1, 3, 1},
520       {  1, 4, 1},{ -1, 4, 1},{  1, 5, 1},{ -1, 5, 1},{  1, 6, 1},{ -1, 6, 1},
521       {  1, 7, 1},{ -1, 7, 1},{  2, 1, 2},{ -2, 1, 2},{  1, 8, 1},{ -1, 8, 1},
522       {  1, 9, 1},{ -1, 9, 1},{  1,10, 1},{ -1,10, 1},{  1,11, 1},{ -1,11, 1},
523       {  1,12, 1},{ -1,12, 1},{  1,13, 1},{ -1,13, 1},{  1,14, 1},{ -1,14, 1},
524       {  1,15, 1},{ -1,15, 1},{  3, 1, 3},{ -3, 1, 3},{  1,16, 1},{ -1,16, 1},
525       {  1,17, 1},{ -1,17, 1},{  1,18, 1},{ -1,18, 1},{  1,19, 1},{ -1,19, 1},
526       {  1,20, 1},{ -1,20, 1},{  1,21, 1},{ -1,21, 1},{  1,22, 1},{ -1,22, 1},
527       {  2, 2, 2},{ -2, 2, 2},{  1,23, 1},{ -1,23, 1},{  1,24, 1},{ -1,24, 1},
528       {  1,25, 1},{ -1,25, 1},{  4, 1, 3},{ -4, 1, 3},{   EOB   }
529     },
530     //level_add
531     { 0, 5, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
532       2, 2, 2, 2, 2, 2, 2, 2, 2,-1},
533     2, //golomb_order
534     0, //inc_limit
535     25 //max_run
536   },{
537     { //level / run
538       {   EOB   },{  1, 1, 0},{ -1, 1, 0},{  1, 2, 0},{ -1, 2, 0},{  2, 1, 1},
539       { -2, 1, 1},{  1, 3, 0},{ -1, 3, 0},{  1, 4, 0},{ -1, 4, 0},{  1, 5, 0},
540       { -1, 5, 0},{  1, 6, 0},{ -1, 6, 0},{  3, 1, 2},{ -3, 1, 2},{  1, 7, 0},
541       { -1, 7, 0},{  1, 8, 0},{ -1, 8, 0},{  2, 2, 1},{ -2, 2, 1},{  1, 9, 0},
542       { -1, 9, 0},{  1,10, 0},{ -1,10, 0},{  1,11, 0},{ -1,11, 0},{  4, 1, 2},
543       { -4, 1, 2},{  1,12, 0},{ -1,12, 0},{  1,13, 0},{ -1,13, 0},{  1,14, 0},
544       { -1,14, 0},{  2, 3, 1},{ -2, 3, 1},{  1,15, 0},{ -1,15, 0},{  2, 4, 1},
545       { -2, 4, 1},{  5, 1, 3},{ -5, 1, 3},{  3, 2, 2},{ -3, 2, 2},{  1,16, 0},
546       { -1,16, 0},{  1,17, 0},{ -1,17, 0},{  1,18, 0},{ -1,18, 0},{  2, 5, 1},
547       { -2, 5, 1},{  1,19, 0},{ -1,19, 0},{  1,20, 0},{ -1,20, 0}
548     },
549     //level_add
550     { 0, 6, 4, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
551       2, 2, 2, 2,-1,-1,-1,-1,-1,-1},
552     0, //golomb_order
553     1, //inc_limit
554     20 //max_run
555   },{
556     { //level / run
557       {  1, 1, 0},{ -1, 1, 0},{   EOB   },{  2, 1, 0},{ -2, 1, 0},{  1, 2, 0},
558       { -1, 2, 0},{  3, 1, 1},{ -3, 1, 1},{  1, 3, 0},{ -1, 3, 0},{  4, 1, 1},
559       { -4, 1, 1},{  2, 2, 0},{ -2, 2, 0},{  1, 4, 0},{ -1, 4, 0},{  5, 1, 2},
560       { -5, 1, 2},{  1, 5, 0},{ -1, 5, 0},{  3, 2, 1},{ -3, 2, 1},{  2, 3, 0},
561       { -2, 3, 0},{  1, 6, 0},{ -1, 6, 0},{  6, 1, 2},{ -6, 1, 2},{  1, 7, 0},
562       { -1, 7, 0},{  2, 4, 0},{ -2, 4, 0},{  7, 1, 2},{ -7, 1, 2},{  1, 8, 0},
563       { -1, 8, 0},{  4, 2, 1},{ -4, 2, 1},{  1, 9, 0},{ -1, 9, 0},{  3, 3, 1},
564       { -3, 3, 1},{  2, 5, 0},{ -2, 5, 0},{  2, 6, 0},{ -2, 6, 0},{  8, 1, 2},
565       { -8, 1, 2},{  1,10, 0},{ -1,10, 0},{  1,11, 0},{ -1,11, 0},{  9, 1, 2},
566       { -9, 1, 2},{  5, 2, 2},{ -5, 2, 2},{  3, 4, 1},{ -3, 4, 1},
567     },
568     //level_add
569     { 0,10, 6, 4, 4, 3, 3, 2, 2, 2, 2, 2,-1,-1,-1,-1,-1,
570      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
571     1, //golomb_order
572     2, //inc_limit
573     11 //max_run
574   },{
575     { //level / run
576       {   EOB   },{  1, 1, 0},{ -1, 1, 0},{  2, 1, 0},{ -2, 1, 0},{  3, 1, 0},
577       { -3, 1, 0},{  4, 1, 0},{ -4, 1, 0},{  1, 2, 0},{ -1, 2, 0},{  5, 1, 1},
578       { -5, 1, 1},{  2, 2, 0},{ -2, 2, 0},{  6, 1, 1},{ -6, 1, 1},{  1, 3, 0},
579       { -1, 3, 0},{  7, 1, 1},{ -7, 1, 1},{  3, 2, 0},{ -3, 2, 0},{  8, 1, 1},
580       { -8, 1, 1},{  1, 4, 0},{ -1, 4, 0},{  2, 3, 0},{ -2, 3, 0},{  9, 1, 1},
581       { -9, 1, 1},{  4, 2, 0},{ -4, 2, 0},{  1, 5, 0},{ -1, 5, 0},{ 10, 1, 1},
582       {-10, 1, 1},{  3, 3, 0},{ -3, 3, 0},{  5, 2, 1},{ -5, 2, 1},{  2, 4, 0},
583       { -2, 4, 0},{ 11, 1, 1},{-11, 1, 1},{  1, 6, 0},{ -1, 6, 0},{ 12, 1, 1},
584       {-12, 1, 1},{  1, 7, 0},{ -1, 7, 0},{  6, 2, 1},{ -6, 2, 1},{ 13, 1, 1},
585       {-13, 1, 1},{  2, 5, 0},{ -2, 5, 0},{  1, 8, 0},{ -1, 8, 0},
586     },
587     //level_add
588     { 0,14, 7, 4, 3, 3, 2, 2, 2,-1,-1,-1,-1,-1,-1,-1,-1,
589      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
590     1, //golomb_order
591     4, //inc_limit
592     8  //max_run
593   },{
594     { //level / run
595       {   EOB   },{  1, 1, 0},{ -1, 1, 0},{  2, 1, 0},{ -2, 1, 0},{  3, 1, 0},
596       { -3, 1, 0},{  4, 1, 0},{ -4, 1, 0},{  5, 1, 0},{ -5, 1, 0},{  6, 1, 0},
597       { -6, 1, 0},{  7, 1, 0},{ -7, 1, 0},{  8, 1, 0},{ -8, 1, 0},{  1, 2, 0},
598       { -1, 2, 0},{  9, 1, 0},{ -9, 1, 0},{ 10, 1, 0},{-10, 1, 0},{ 11, 1, 0},
599       {-11, 1, 0},{  2, 2, 0},{ -2, 2, 0},{ 12, 1, 0},{-12, 1, 0},{ 13, 1, 0},
600       {-13, 1, 0},{  3, 2, 0},{ -3, 2, 0},{ 14, 1, 0},{-14, 1, 0},{  1, 3, 0},
601       { -1, 3, 0},{ 15, 1, 0},{-15, 1, 0},{  4, 2, 0},{ -4, 2, 0},{ 16, 1, 0},
602       {-16, 1, 0},{ 17, 1, 0},{-17, 1, 0},{  5, 2, 0},{ -5, 2, 0},{  1, 4, 0},
603       { -1, 4, 0},{  2, 3, 0},{ -2, 3, 0},{ 18, 1, 0},{-18, 1, 0},{  6, 2, 0},
604       { -6, 2, 0},{ 19, 1, 0},{-19, 1, 0},{  1, 5, 0},{ -1, 5, 0},
605     },
606     //level_add
607     { 0,20, 7, 3, 2, 2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
608      -1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
609     0, //golomb_order
610     INT_MAX, //inc_limit
611     5, //max_run
612   }
613 };
614
615 #undef EOB
616
617 static const uint8_t alpha_tab[64] = {
618    0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  2,  2,  2,  3,  3,
619    4,  4,  5,  5,  6,  7,  8,  9, 10, 11, 12, 13, 15, 16, 18, 20,
620   22, 24, 26, 28, 30, 33, 33, 35, 35, 36, 37, 37, 39, 39, 42, 44,
621   46, 48, 50, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64
622 };
623
624 static const uint8_t beta_tab[64] = {
625    0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  2,  2,  2,
626    2,  2,  3,  3,  3,  3,  4,  4,  4,  4,  5,  5,  5,  5,  6,  6,
627    6,  7,  7,  7,  8,  8,  8,  9,  9, 10, 10, 11, 11, 12, 13, 14,
628   15, 16, 17, 18, 19, 20, 21, 22, 23, 23, 24, 24, 25, 25, 26, 27
629 };
630
631 static const uint8_t tc_tab[64] = {
632   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
633   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,
634   2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4,
635   5, 5, 5, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9
636 };
637
638 static const int_fast8_t left_modifier_l[8] = { 0,-1, 6,-1,-1, 7, 6, 7};
639 static const int_fast8_t top_modifier_l[8]  = {-1, 1, 5,-1,-1, 5, 7, 7};
640 static const int_fast8_t left_modifier_c[7] = { 5,-1, 2,-1, 6, 5, 6};
641 static const int_fast8_t top_modifier_c[7]  = { 4, 1,-1,-1, 4, 6, 6};