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