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