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