1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 /**
20  * @file
21  * @brief IntraX8 (J-Frame) subdecoder, used by WMV2 and VC-1
22  */
23 
24 #include "libavutil/avassert.h"
25 #include "avcodec.h"
26 #include "get_bits.h"
27 #include "idctdsp.h"
28 #include "msmpeg4data.h"
29 #include "intrax8huf.h"
30 #include "intrax8.h"
31 #include "intrax8dsp.h"
32 #include "mpegutils.h"
33 
34 #define MAX_TABLE_DEPTH(table_bits, max_bits) \
35     ((max_bits + table_bits - 1) / table_bits)
36 
37 #define DC_VLC_BITS 9
38 #define AC_VLC_BITS 9
39 #define OR_VLC_BITS 7
40 
41 #define DC_VLC_MTD MAX_TABLE_DEPTH(DC_VLC_BITS, MAX_DC_VLC_BITS)
42 #define AC_VLC_MTD MAX_TABLE_DEPTH(AC_VLC_BITS, MAX_AC_VLC_BITS)
43 #define OR_VLC_MTD MAX_TABLE_DEPTH(OR_VLC_BITS, MAX_OR_VLC_BITS)
44 
45 static VLC j_ac_vlc[2][2][8];  // [quant < 13], [intra / inter], [select]
46 static VLC j_dc_vlc[2][8];     // [quant], [select]
47 static VLC j_orient_vlc[2][4]; // [quant], [select]
48 
x8_vlc_init(void)49 static av_cold int x8_vlc_init(void)
50 {
51     int i;
52     int offset = 0;
53     int sizeidx = 0;
54     static const uint16_t sizes[8 * 4 + 8 * 2 + 2 + 4] = {
55         576, 548, 582, 618, 546, 616, 560, 642,
56         584, 582, 704, 664, 512, 544, 656, 640,
57         512, 648, 582, 566, 532, 614, 596, 648,
58         586, 552, 584, 590, 544, 578, 584, 624,
59 
60         528, 528, 526, 528, 536, 528, 526, 544,
61         544, 512, 512, 528, 528, 544, 512, 544,
62 
63         128, 128, 128, 128, 128, 128,
64     };
65 
66     static VLC_TYPE table[28150][2];
67 
68 // set ac tables
69 #define init_ac_vlc(dst, src)                                                 \
70     do {                                                                      \
71         dst.table           = &table[offset];                                 \
72         dst.table_allocated = sizes[sizeidx];                                 \
73         offset             += sizes[sizeidx++];                               \
74         init_vlc(&dst, AC_VLC_BITS, 77, &src[1], 4, 2, &src[0], 4, 2,         \
75                  INIT_VLC_USE_NEW_STATIC);                                    \
76     } while(0)
77 
78     for (i = 0; i < 8; i++) {
79         init_ac_vlc(j_ac_vlc[0][0][i], x8_ac0_highquant_table[i][0]);
80         init_ac_vlc(j_ac_vlc[0][1][i], x8_ac1_highquant_table[i][0]);
81         init_ac_vlc(j_ac_vlc[1][0][i], x8_ac0_lowquant_table[i][0]);
82         init_ac_vlc(j_ac_vlc[1][1][i], x8_ac1_lowquant_table[i][0]);
83     }
84 #undef init_ac_vlc
85 
86 // set dc tables
87 #define init_dc_vlc(dst, src)                                                 \
88     do {                                                                      \
89         dst.table           = &table[offset];                                 \
90         dst.table_allocated = sizes[sizeidx];                                 \
91         offset             += sizes[sizeidx++];                               \
92         init_vlc(&dst, DC_VLC_BITS, 34, &src[1], 4, 2, &src[0], 4, 2,         \
93                  INIT_VLC_USE_NEW_STATIC);                                    \
94     } while(0)
95 
96     for (i = 0; i < 8; i++) {
97         init_dc_vlc(j_dc_vlc[0][i], x8_dc_highquant_table[i][0]);
98         init_dc_vlc(j_dc_vlc[1][i], x8_dc_lowquant_table[i][0]);
99     }
100 #undef init_dc_vlc
101 
102 // set orient tables
103 #define init_or_vlc(dst, src)                                                 \
104     do {                                                                      \
105         dst.table           = &table[offset];                                 \
106         dst.table_allocated = sizes[sizeidx];                                 \
107         offset             += sizes[sizeidx++];                               \
108         init_vlc(&dst, OR_VLC_BITS, 12, &src[1], 4, 2, &src[0], 4, 2,         \
109                  INIT_VLC_USE_NEW_STATIC);                                    \
110     } while(0)
111 
112     for (i = 0; i < 2; i++)
113         init_or_vlc(j_orient_vlc[0][i], x8_orient_highquant_table[i][0]);
114     for (i = 0; i < 4; i++)
115         init_or_vlc(j_orient_vlc[1][i], x8_orient_lowquant_table[i][0]);
116 #undef init_or_vlc
117 
118     if (offset != sizeof(table) / sizeof(VLC_TYPE) / 2) {
119         av_log(NULL, AV_LOG_ERROR, "table size %"SIZE_SPECIFIER" does not match needed %i\n",
120                sizeof(table) / sizeof(VLC_TYPE) / 2, offset);
121         return AVERROR_INVALIDDATA;
122     }
123 
124     return 0;
125 }
126 
x8_reset_vlc_tables(IntraX8Context * w)127 static void x8_reset_vlc_tables(IntraX8Context *w)
128 {
129     memset(w->j_dc_vlc, 0, sizeof(w->j_dc_vlc));
130     memset(w->j_ac_vlc, 0, sizeof(w->j_ac_vlc));
131     w->j_orient_vlc = NULL;
132 }
133 
x8_select_ac_table(IntraX8Context * const w,int mode)134 static inline void x8_select_ac_table(IntraX8Context *const w, int mode)
135 {
136     int table_index;
137 
138     av_assert2(mode < 4);
139 
140     if (w->j_ac_vlc[mode])
141         return;
142 
143     table_index       = get_bits(w->gb, 3);
144     // 2 modes use same tables
145     w->j_ac_vlc[mode] = &j_ac_vlc[w->quant < 13][mode >> 1][table_index];
146     av_assert2(w->j_ac_vlc[mode]);
147 }
148 
x8_get_orient_vlc(IntraX8Context * w)149 static inline int x8_get_orient_vlc(IntraX8Context *w)
150 {
151     if (!w->j_orient_vlc) {
152         int table_index = get_bits(w->gb, 1 + (w->quant < 13));
153         w->j_orient_vlc = &j_orient_vlc[w->quant < 13][table_index];
154     }
155 
156     return get_vlc2(w->gb, w->j_orient_vlc->table, OR_VLC_BITS, OR_VLC_MTD);
157 }
158 
159 #define extra_bits(eb)  (eb)        // 3 bits
160 #define extra_run       (0xFF << 8) // 1 bit
161 #define extra_level     (0x00 << 8) // 1 bit
162 #define run_offset(r)   ((r) << 16) // 6 bits
163 #define level_offset(l) ((l) << 24) // 5 bits
164 static const uint32_t ac_decode_table[] = {
165     /* 46 */ extra_bits(3) | extra_run   | run_offset(16) | level_offset(0),
166     /* 47 */ extra_bits(3) | extra_run   | run_offset(24) | level_offset(0),
167     /* 48 */ extra_bits(2) | extra_run   | run_offset(4)  | level_offset(1),
168     /* 49 */ extra_bits(3) | extra_run   | run_offset(8)  | level_offset(1),
169 
170     /* 50 */ extra_bits(5) | extra_run   | run_offset(32) | level_offset(0),
171     /* 51 */ extra_bits(4) | extra_run   | run_offset(16) | level_offset(1),
172 
173     /* 52 */ extra_bits(2) | extra_level | run_offset(0)  | level_offset(4),
174     /* 53 */ extra_bits(2) | extra_level | run_offset(0)  | level_offset(8),
175     /* 54 */ extra_bits(2) | extra_level | run_offset(0)  | level_offset(12),
176     /* 55 */ extra_bits(3) | extra_level | run_offset(0)  | level_offset(16),
177     /* 56 */ extra_bits(3) | extra_level | run_offset(0)  | level_offset(24),
178 
179     /* 57 */ extra_bits(2) | extra_level | run_offset(1)  | level_offset(3),
180     /* 58 */ extra_bits(3) | extra_level | run_offset(1)  | level_offset(7),
181 
182     /* 59 */ extra_bits(2) | extra_run   | run_offset(16) | level_offset(0),
183     /* 60 */ extra_bits(2) | extra_run   | run_offset(20) | level_offset(0),
184     /* 61 */ extra_bits(2) | extra_run   | run_offset(24) | level_offset(0),
185     /* 62 */ extra_bits(2) | extra_run   | run_offset(28) | level_offset(0),
186     /* 63 */ extra_bits(4) | extra_run   | run_offset(32) | level_offset(0),
187     /* 64 */ extra_bits(4) | extra_run   | run_offset(48) | level_offset(0),
188 
189     /* 65 */ extra_bits(2) | extra_run   | run_offset(4)  | level_offset(1),
190     /* 66 */ extra_bits(3) | extra_run   | run_offset(8)  | level_offset(1),
191     /* 67 */ extra_bits(4) | extra_run   | run_offset(16) | level_offset(1),
192 
193     /* 68 */ extra_bits(2) | extra_level | run_offset(0)  | level_offset(4),
194     /* 69 */ extra_bits(3) | extra_level | run_offset(0)  | level_offset(8),
195     /* 70 */ extra_bits(4) | extra_level | run_offset(0)  | level_offset(16),
196 
197     /* 71 */ extra_bits(2) | extra_level | run_offset(1)  | level_offset(3),
198     /* 72 */ extra_bits(3) | extra_level | run_offset(1)  | level_offset(7),
199 };
200 #undef extra_bits
201 #undef extra_run
202 #undef extra_level
203 #undef run_offset
204 #undef level_offset
205 
x8_get_ac_rlf(IntraX8Context * const w,const int mode,int * const run,int * const level,int * const final)206 static void x8_get_ac_rlf(IntraX8Context *const w, const int mode,
207                           int *const run, int *const level, int *const final)
208 {
209     int i, e;
210 
211 //    x8_select_ac_table(w, mode);
212     i = get_vlc2(w->gb, w->j_ac_vlc[mode]->table, AC_VLC_BITS, AC_VLC_MTD);
213 
214     if (i < 46) { // [0-45]
215         int t, l;
216         if (i < 0) {
217             *level =
218             *final =      // prevent 'may be used uninitialized'
219             *run   = 64;  // this would cause error exit in the ac loop
220             return;
221         }
222 
223         /*
224          * i == 0-15  r = 0-15 l = 0; r = i & %01111
225          * i == 16-19 r = 0-3  l = 1; r = i & %00011
226          * i == 20-21 r = 0-1  l = 2; r = i & %00001
227          * i == 22    r = 0    l = 3; r = i & %00000
228          */
229 
230         *final =
231         t      = i > 22;
232         i     -= 23 * t;
233 
234         /* l = lut_l[i / 2] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3 }[i >> 1];
235          *     11 10'01 01'00 00'00 00'00 00'00 00 => 0xE50000 */
236         l = (0xE50000 >> (i & 0x1E)) & 3; // 0x1E or ~1 or (i >> 1 << 1)
237 
238         /* t = lut_mask[l] = { 0x0f, 0x03, 0x01, 0x00 }[l];
239          *     as i < 256 the higher bits do not matter */
240         t = 0x01030F >> (l << 3);
241 
242         *run   = i & t;
243         *level = l;
244     } else if (i < 73) { // [46-72]
245         uint32_t sm;
246         uint32_t mask;
247 
248         i -= 46;
249         sm = ac_decode_table[i];
250 
251         e    = get_bits(w->gb, sm & 0xF);
252         sm >>= 8;                               // 3 bits
253         mask = sm & 0xff;
254         sm >>= 8;                               // 1 bit
255 
256         *run   = (sm &  0xff) + (e &  mask);    // 6 bits
257         *level = (sm >>    8) + (e & ~mask);    // 5 bits
258         *final = i > (58 - 46);
259     } else if (i < 75) { // [73-74]
260         static const uint8_t crazy_mix_runlevel[32] = {
261             0x22, 0x32, 0x33, 0x53, 0x23, 0x42, 0x43, 0x63,
262             0x24, 0x52, 0x34, 0x73, 0x25, 0x62, 0x44, 0x83,
263             0x26, 0x72, 0x35, 0x54, 0x27, 0x82, 0x45, 0x64,
264             0x28, 0x92, 0x36, 0x74, 0x29, 0xa2, 0x46, 0x84,
265         };
266 
267         *final = !(i & 1);
268         e      = get_bits(w->gb, 5); // get the extra bits
269         *run   = crazy_mix_runlevel[e] >> 4;
270         *level = crazy_mix_runlevel[e] & 0x0F;
271     } else {
272         *level = get_bits(w->gb, 7 - 3 * (i & 1));
273         *run   = get_bits(w->gb, 6);
274         *final = get_bits1(w->gb);
275     }
276     return;
277 }
278 
279 /* static const uint8_t dc_extra_sbits[] = {
280  *     0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
281  * }; */
282 static const uint8_t dc_index_offset[] = {
283     0, 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
284 };
285 
x8_get_dc_rlf(IntraX8Context * const w,const int mode,int * const level,int * const final)286 static int x8_get_dc_rlf(IntraX8Context *const w, const int mode,
287                          int *const level, int *const final)
288 {
289     int i, e, c;
290 
291     av_assert2(mode < 3);
292     if (!w->j_dc_vlc[mode]) {
293         int table_index = get_bits(w->gb, 3);
294         // 4 modes, same table
295         w->j_dc_vlc[mode] = &j_dc_vlc[w->quant < 13][table_index];
296     }
297 
298     i = get_vlc2(w->gb, w->j_dc_vlc[mode]->table, DC_VLC_BITS, DC_VLC_MTD);
299 
300     /* (i >= 17) { i -= 17; final =1; } */
301     c      = i > 16;
302     *final = c;
303     i      -= 17 * c;
304 
305     if (i <= 0) {
306         *level = 0;
307         return -i;
308     }
309     c  = (i + 1) >> 1; // hackish way to calculate dc_extra_sbits[]
310     c -= c > 1;
311 
312     e = get_bits(w->gb, c); // get the extra bits
313     i = dc_index_offset[i] + (e >> 1);
314 
315     e      = -(e & 1);     // 0, 0xffffff
316     *level =  (i ^ e) - e; // (i ^ 0) - 0, (i ^ 0xff) - (-1)
317     return 0;
318 }
319 
320 // end of huffman
321 
x8_setup_spatial_predictor(IntraX8Context * const w,const int chroma)322 static int x8_setup_spatial_predictor(IntraX8Context *const w, const int chroma)
323 {
324     int range;
325     int sum;
326     int quant;
327 
328     w->dsp.setup_spatial_compensation(w->dest[chroma], w->scratchpad,
329                                       w->frame->linesize[chroma > 0],
330                                       &range, &sum, w->edges);
331     if (chroma) {
332         w->orient = w->chroma_orient;
333         quant     = w->quant_dc_chroma;
334     } else {
335         quant = w->quant;
336     }
337 
338     w->flat_dc = 0;
339     if (range < quant || range < 3) {
340         w->orient = 0;
341 
342         // yep you read right, a +-1 idct error may break decoding!
343         if (range < 3) {
344             w->flat_dc      = 1;
345             sum            += 9;
346             // ((1 << 17) + 9) / (8 + 8 + 1 + 2) = 6899
347             w->predicted_dc = sum * 6899 >> 17;
348         }
349     }
350     if (chroma)
351         return 0;
352 
353     av_assert2(w->orient < 3);
354     if (range < 2 * w->quant) {
355         if ((w->edges & 3) == 0) {
356             if (w->orient == 1)
357                 w->orient = 11;
358             if (w->orient == 2)
359                 w->orient = 10;
360         } else {
361             w->orient = 0;
362         }
363         w->raw_orient = 0;
364     } else {
365         static const uint8_t prediction_table[3][12] = {
366             { 0, 8, 4, 10, 11, 2, 6, 9, 1, 3, 5, 7 },
367             { 4, 0, 8, 11, 10, 3, 5, 2, 6, 9, 1, 7 },
368             { 8, 0, 4, 10, 11, 1, 7, 2, 6, 9, 3, 5 },
369         };
370         w->raw_orient = x8_get_orient_vlc(w);
371         if (w->raw_orient < 0)
372             return -1;
373         av_assert2(w->raw_orient < 12);
374         av_assert2(w->orient < 3);
375         w->orient=prediction_table[w->orient][w->raw_orient];
376     }
377     return 0;
378 }
379 
x8_update_predictions(IntraX8Context * const w,const int orient,const int est_run)380 static void x8_update_predictions(IntraX8Context *const w, const int orient,
381                                   const int est_run)
382 {
383     w->prediction_table[w->mb_x * 2 + (w->mb_y & 1)] = (est_run << 2) + 1 * (orient == 4) + 2 * (orient == 8);
384 /*
385  * y = 2n + 0 -> // 0 2 4
386  * y = 2n + 1 -> // 1 3 5
387  */
388 }
389 
x8_get_prediction_chroma(IntraX8Context * const w)390 static void x8_get_prediction_chroma(IntraX8Context *const w)
391 {
392     w->edges  = 1 * !(w->mb_x >> 1);
393     w->edges |= 2 * !(w->mb_y >> 1);
394     w->edges |= 4 * (w->mb_x >= (2 * w->mb_width - 1)); // mb_x for chroma would always be odd
395 
396     w->raw_orient = 0;
397     // lut_co[8] = {inv,4,8,8, inv,4,8,8} <- => {1,1,0,0;1,1,0,0} => 0xCC
398     if (w->edges & 3) {
399         w->chroma_orient = 4 << ((0xCC >> w->edges) & 1);
400         return;
401     }
402     // block[x - 1][y | 1 - 1)]
403     w->chroma_orient = (w->prediction_table[2 * w->mb_x - 2] & 0x03) << 2;
404 }
405 
x8_get_prediction(IntraX8Context * const w)406 static void x8_get_prediction(IntraX8Context *const w)
407 {
408     int a, b, c, i;
409 
410     w->edges  = 1 * !w->mb_x;
411     w->edges |= 2 * !w->mb_y;
412     w->edges |= 4 * (w->mb_x >= (2 * w->mb_width - 1));
413 
414     switch (w->edges & 3) {
415     case 0:
416         break;
417     case 1:
418         // take the one from the above block[0][y - 1]
419         w->est_run = w->prediction_table[!(w->mb_y & 1)] >> 2;
420         w->orient  = 1;
421         return;
422     case 2:
423         // take the one from the previous block[x - 1][0]
424         w->est_run = w->prediction_table[2 * w->mb_x - 2] >> 2;
425         w->orient  = 2;
426         return;
427     case 3:
428         w->est_run = 16;
429         w->orient  = 0;
430         return;
431     }
432     // no edge cases
433     b = w->prediction_table[2 * w->mb_x     + !(w->mb_y & 1)]; // block[x    ][y - 1]
434     a = w->prediction_table[2 * w->mb_x - 2 +  (w->mb_y & 1)]; // block[x - 1][y    ]
435     c = w->prediction_table[2 * w->mb_x - 2 + !(w->mb_y & 1)]; // block[x - 1][y - 1]
436 
437     w->est_run = FFMIN(b, a);
438     /* This condition has nothing to do with w->edges, even if it looks
439      * similar it would trigger if e.g. x = 3; y = 2;
440      * I guess somebody wrote something wrong and it became standard. */
441     if ((w->mb_x & w->mb_y) != 0)
442         w->est_run = FFMIN(c, w->est_run);
443     w->est_run >>= 2;
444 
445     a &= 3;
446     b &= 3;
447     c &= 3;
448 
449     i = (0xFFEAF4C4 >> (2 * b + 8 * a)) & 3;
450     if (i != 3)
451         w->orient = i;
452     else
453         w->orient = (0xFFEAD8 >> (2 * c + 8 * (w->quant > 12))) & 3;
454 /*
455  * lut1[b][a] = {
456  * ->{ 0, 1, 0, pad },
457  *   { 0, 1, X, pad },
458  *   { 2, 2, 2, pad }
459  * }
460  * pad 2  2  2;
461  * pad X  1  0;
462  * pad 0  1  0 <-
463  * -> 11 10 '10 10 '11 11'01 00 '11 00'01 00 => 0xEAF4C4
464  *
465  * lut2[q>12][c] = {
466  * ->{ 0, 2, 1, pad},
467  *   { 2, 2, 2, pad}
468  * }
469  * pad 2  2  2;
470  * pad 1  2  0 <-
471  * -> 11 10'10 10 '11 01'10 00 => 0xEAD8
472  */
473 }
474 
x8_ac_compensation(IntraX8Context * const w,const int direction,const int dc_level)475 static void x8_ac_compensation(IntraX8Context *const w, const int direction,
476                                const int dc_level)
477 {
478     int t;
479 #define B(x,y)  w->block[0][w->idct_permutation[(x) + (y) * 8]]
480 #define T(x)  ((x) * dc_level + 0x8000) >> 16;
481     switch (direction) {
482     case 0:
483         t        = T(3811); // h
484         B(1, 0) -= t;
485         B(0, 1) -= t;
486 
487         t        = T(487); // e
488         B(2, 0) -= t;
489         B(0, 2) -= t;
490 
491         t        = T(506); // f
492         B(3, 0) -= t;
493         B(0, 3) -= t;
494 
495         t        = T(135); // c
496         B(4, 0) -= t;
497         B(0, 4) -= t;
498         B(2, 1) += t;
499         B(1, 2) += t;
500         B(3, 1) += t;
501         B(1, 3) += t;
502 
503         t        = T(173); // d
504         B(5, 0) -= t;
505         B(0, 5) -= t;
506 
507         t        = T(61); // b
508         B(6, 0) -= t;
509         B(0, 6) -= t;
510         B(5, 1) += t;
511         B(1, 5) += t;
512 
513         t        = T(42); // a
514         B(7, 0) -= t;
515         B(0, 7) -= t;
516         B(4, 1) += t;
517         B(1, 4) += t;
518         B(4, 4) += t;
519 
520         t        = T(1084); // g
521         B(1, 1) += t;
522 
523         w->block_last_index[0] = FFMAX(w->block_last_index[0], 7 * 8);
524         break;
525     case 1:
526         B(0, 1) -= T(6269);
527         B(0, 3) -= T(708);
528         B(0, 5) -= T(172);
529         B(0, 7) -= T(73);
530 
531         w->block_last_index[0] = FFMAX(w->block_last_index[0], 7 * 8);
532         break;
533     case 2:
534         B(1, 0) -= T(6269);
535         B(3, 0) -= T(708);
536         B(5, 0) -= T(172);
537         B(7, 0) -= T(73);
538 
539         w->block_last_index[0] = FFMAX(w->block_last_index[0], 7);
540         break;
541     }
542 #undef B
543 #undef T
544 }
545 
dsp_x8_put_solidcolor(const uint8_t pix,uint8_t * dst,const ptrdiff_t linesize)546 static void dsp_x8_put_solidcolor(const uint8_t pix, uint8_t *dst,
547                                   const ptrdiff_t linesize)
548 {
549     int k;
550     for (k = 0; k < 8; k++) {
551         memset(dst, pix, 8);
552         dst += linesize;
553     }
554 }
555 
556 static const int16_t quant_table[64] = {
557     256, 256, 256, 256, 256, 256, 259, 262,
558     265, 269, 272, 275, 278, 282, 285, 288,
559     292, 295, 299, 303, 306, 310, 314, 317,
560     321, 325, 329, 333, 337, 341, 345, 349,
561     353, 358, 362, 366, 371, 375, 379, 384,
562     389, 393, 398, 403, 408, 413, 417, 422,
563     428, 433, 438, 443, 448, 454, 459, 465,
564     470, 476, 482, 488, 493, 499, 505, 511,
565 };
566 
x8_decode_intra_mb(IntraX8Context * const w,const int chroma)567 static int x8_decode_intra_mb(IntraX8Context *const w, const int chroma)
568 {
569     uint8_t *scantable;
570     int final, run, level;
571     int ac_mode, dc_mode, est_run, dc_level;
572     int pos, n;
573     int zeros_only;
574     int use_quant_matrix;
575     int sign;
576 
577     av_assert2(w->orient < 12);
578     w->bdsp.clear_block(w->block[0]);
579 
580     if (chroma)
581         dc_mode = 2;
582     else
583         dc_mode = !!w->est_run; // 0, 1
584 
585     if (x8_get_dc_rlf(w, dc_mode, &dc_level, &final))
586         return -1;
587     n          = 0;
588     zeros_only = 0;
589     if (!final) { // decode ac
590         use_quant_matrix = w->use_quant_matrix;
591         if (chroma) {
592             ac_mode = 1;
593             est_run = 64; // not used
594         } else {
595             if (w->raw_orient < 3)
596                 use_quant_matrix = 0;
597 
598             if (w->raw_orient > 4) {
599                 ac_mode = 0;
600                 est_run = 64;
601             } else {
602                 if (w->est_run > 1) {
603                     ac_mode = 2;
604                     est_run = w->est_run;
605                 } else {
606                     ac_mode = 3;
607                     est_run = 64;
608                 }
609             }
610         }
611         x8_select_ac_table(w, ac_mode);
612         /* scantable_selector[12] = { 0, 2, 0, 1, 1, 1, 0, 2, 2, 0, 1, 2 }; <-
613          * -> 10'01' 00'10' 10'00' 01'01' 01'00' 10'00 => 0x928548 */
614         scantable = w->scantable[(0x928548 >> (2 * w->orient)) & 3].permutated;
615         pos       = 0;
616         do {
617             n++;
618             if (n >= est_run) {
619                 ac_mode = 3;
620                 x8_select_ac_table(w, 3);
621             }
622 
623             x8_get_ac_rlf(w, ac_mode, &run, &level, &final);
624 
625             pos += run + 1;
626             if (pos > 63) {
627                 // this also handles vlc error in x8_get_ac_rlf
628                 return -1;
629             }
630             level  = (level + 1) * w->dquant;
631             level += w->qsum;
632 
633             sign  = -get_bits1(w->gb);
634             level = (level ^ sign) - sign;
635 
636             if (use_quant_matrix)
637                 level = (level * quant_table[pos]) >> 8;
638 
639             w->block[0][scantable[pos]] = level;
640         } while (!final);
641 
642         w->block_last_index[0] = pos;
643     } else { // DC only
644         w->block_last_index[0] = 0;
645         if (w->flat_dc && ((unsigned) (dc_level + 1)) < 3) { // [-1; 1]
646             int32_t divide_quant = !chroma ? w->divide_quant_dc_luma
647                                            : w->divide_quant_dc_chroma;
648             int32_t dc_quant     = !chroma ? w->quant
649                                            : w->quant_dc_chroma;
650 
651             // original intent dc_level += predicted_dc/quant;
652             // but it got lost somewhere in the rounding
653             dc_level += (w->predicted_dc * divide_quant + (1 << 12)) >> 13;
654 
655             dsp_x8_put_solidcolor(av_clip_uint8((dc_level * dc_quant + 4) >> 3),
656                                   w->dest[chroma],
657                                   w->frame->linesize[!!chroma]);
658 
659             goto block_placed;
660         }
661         zeros_only = dc_level == 0;
662     }
663     if (!chroma)
664         w->block[0][0] = dc_level * w->quant;
665     else
666         w->block[0][0] = dc_level * w->quant_dc_chroma;
667 
668     // there is !zero_only check in the original, but dc_level check is enough
669     if ((unsigned int) (dc_level + 1) >= 3 && (w->edges & 3) != 3) {
670         int direction;
671         /* ac_comp_direction[orient] = { 0, 3, 3, 1, 1, 0, 0, 0, 2, 2, 2, 1 }; <-
672          * -> 01'10' 10'10' 00'00' 00'01' 01'11' 11'00 => 0x6A017C */
673         direction = (0x6A017C >> (w->orient * 2)) & 3;
674         if (direction != 3) {
675             // modify block_last[]
676             x8_ac_compensation(w, direction, w->block[0][0]);
677         }
678     }
679 
680     if (w->flat_dc) {
681         dsp_x8_put_solidcolor(w->predicted_dc, w->dest[chroma],
682                               w->frame->linesize[!!chroma]);
683     } else {
684         w->dsp.spatial_compensation[w->orient](w->scratchpad,
685                                                w->dest[chroma],
686                                                w->frame->linesize[!!chroma]);
687     }
688     if (!zeros_only)
689         w->wdsp.idct_add(w->dest[chroma],
690                          w->frame->linesize[!!chroma],
691                          w->block[0]);
692 
693 block_placed:
694     if (!chroma)
695         x8_update_predictions(w, w->orient, n);
696 
697     if (w->loopfilter) {
698         uint8_t *ptr = w->dest[chroma];
699         ptrdiff_t linesize = w->frame->linesize[!!chroma];
700 
701         if (!((w->edges & 2) || (zeros_only && (w->orient | 4) == 4)))
702             w->dsp.h_loop_filter(ptr, linesize, w->quant);
703 
704         if (!((w->edges & 1) || (zeros_only && (w->orient | 8) == 8)))
705             w->dsp.v_loop_filter(ptr, linesize, w->quant);
706     }
707     return 0;
708 }
709 
710 // FIXME maybe merge with ff_*
x8_init_block_index(IntraX8Context * w,AVFrame * frame)711 static void x8_init_block_index(IntraX8Context *w, AVFrame *frame)
712 {
713     // not parent codec linesize as this would be wrong for field pics
714     // not that IntraX8 has interlacing support ;)
715     const ptrdiff_t linesize   = frame->linesize[0];
716     const ptrdiff_t uvlinesize = frame->linesize[1];
717 
718     w->dest[0] = frame->data[0];
719     w->dest[1] = frame->data[1];
720     w->dest[2] = frame->data[2];
721 
722     w->dest[0] +=  w->mb_y       * linesize   << 3;
723     // chroma blocks are on add rows
724     w->dest[1] += (w->mb_y & ~1) * uvlinesize << 2;
725     w->dest[2] += (w->mb_y & ~1) * uvlinesize << 2;
726 }
727 
ff_intrax8_common_init(AVCodecContext * avctx,IntraX8Context * w,IDCTDSPContext * idsp,int16_t (* block)[64],int block_last_index[12],int mb_width,int mb_height)728 av_cold int ff_intrax8_common_init(AVCodecContext *avctx,
729                                    IntraX8Context *w, IDCTDSPContext *idsp,
730                                    int16_t (*block)[64],
731                                    int block_last_index[12],
732                                    int mb_width, int mb_height)
733 {
734     int ret = x8_vlc_init();
735     if (ret < 0)
736         return ret;
737 
738     w->avctx = avctx;
739     w->idsp = *idsp;
740     w->mb_width  = mb_width;
741     w->mb_height = mb_height;
742     w->block = block;
743     w->block_last_index = block_last_index;
744 
745     // two rows, 2 blocks per cannon mb
746     w->prediction_table = av_mallocz(w->mb_width * 2 * 2);
747     if (!w->prediction_table)
748         return AVERROR(ENOMEM);
749 
750     ff_wmv2dsp_init(&w->wdsp);
751 
752     ff_init_scantable_permutation(w->idct_permutation,
753                                   w->wdsp.idct_perm);
754 
755     ff_init_scantable(w->idct_permutation, &w->scantable[0],
756                       ff_wmv1_scantable[0]);
757     ff_init_scantable(w->idct_permutation, &w->scantable[1],
758                       ff_wmv1_scantable[2]);
759     ff_init_scantable(w->idct_permutation, &w->scantable[2],
760                       ff_wmv1_scantable[3]);
761 
762     ff_intrax8dsp_init(&w->dsp);
763     ff_blockdsp_init(&w->bdsp, avctx);
764 
765     return 0;
766 }
767 
ff_intrax8_common_end(IntraX8Context * w)768 av_cold void ff_intrax8_common_end(IntraX8Context *w)
769 {
770     av_freep(&w->prediction_table);
771 }
772 
ff_intrax8_decode_picture(IntraX8Context * w,Picture * pict,GetBitContext * gb,int * mb_x,int * mb_y,int dquant,int quant_offset,int loopfilter,int lowdelay)773 int ff_intrax8_decode_picture(IntraX8Context *w, Picture *pict,
774                               GetBitContext *gb, int *mb_x, int *mb_y,
775                               int dquant, int quant_offset,
776                               int loopfilter, int lowdelay)
777 {
778     int mb_xy;
779 
780     w->gb     = gb;
781     w->dquant = dquant;
782     w->quant  = dquant >> 1;
783     w->qsum   = quant_offset;
784     w->frame  = pict->f;
785     w->loopfilter = loopfilter;
786     w->use_quant_matrix = get_bits1(w->gb);
787 
788     w->mb_x = *mb_x;
789     w->mb_y = *mb_y;
790 
791     w->divide_quant_dc_luma = ((1 << 16) + (w->quant >> 1)) / w->quant;
792     if (w->quant < 5) {
793         w->quant_dc_chroma        = w->quant;
794         w->divide_quant_dc_chroma = w->divide_quant_dc_luma;
795     } else {
796         w->quant_dc_chroma        = w->quant + ((w->quant + 3) >> 3);
797         w->divide_quant_dc_chroma = ((1 << 16) + (w->quant_dc_chroma >> 1)) / w->quant_dc_chroma;
798     }
799     x8_reset_vlc_tables(w);
800 
801     for (w->mb_y = 0; w->mb_y < w->mb_height * 2; w->mb_y++) {
802         x8_init_block_index(w, w->frame);
803         mb_xy = (w->mb_y >> 1) * (w->mb_width + 1);
804         for (w->mb_x = 0; w->mb_x < w->mb_width * 2; w->mb_x++) {
805             x8_get_prediction(w);
806             if (x8_setup_spatial_predictor(w, 0))
807                 goto error;
808             if (x8_decode_intra_mb(w, 0))
809                 goto error;
810 
811             if (w->mb_x & w->mb_y & 1) {
812                 x8_get_prediction_chroma(w);
813 
814                 /* when setting up chroma, no vlc is read,
815                  * so no error condition can be reached */
816                 x8_setup_spatial_predictor(w, 1);
817                 if (x8_decode_intra_mb(w, 1))
818                     goto error;
819 
820                 x8_setup_spatial_predictor(w, 2);
821                 if (x8_decode_intra_mb(w, 2))
822                     goto error;
823 
824                 w->dest[1] += 8;
825                 w->dest[2] += 8;
826 
827                 pict->qscale_table[mb_xy] = w->quant;
828                 mb_xy++;
829             }
830             w->dest[0] += 8;
831         }
832         if (w->mb_y & 1)
833             ff_draw_horiz_band(w->avctx, w->frame, w->frame,
834                                (w->mb_y - 1) * 8, 16,
835                                PICT_FRAME, 0, lowdelay);
836     }
837 
838 error:
839     *mb_x = w->mb_x;
840     *mb_y = w->mb_y;
841 
842     return 0;
843 }
844