1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * Infinity IMM4 decoder
3cabdff1aSopenharmony_ci *
4cabdff1aSopenharmony_ci * Copyright (c) 2018 Paul B Mahol
5cabdff1aSopenharmony_ci *
6cabdff1aSopenharmony_ci * This file is part of FFmpeg.
7cabdff1aSopenharmony_ci *
8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
12cabdff1aSopenharmony_ci *
13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16cabdff1aSopenharmony_ci * Lesser General Public License for more details.
17cabdff1aSopenharmony_ci *
18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21cabdff1aSopenharmony_ci */
22cabdff1aSopenharmony_ci
23cabdff1aSopenharmony_ci#include <stdio.h>
24cabdff1aSopenharmony_ci#include <stdlib.h>
25cabdff1aSopenharmony_ci#include <string.h>
26cabdff1aSopenharmony_ci
27cabdff1aSopenharmony_ci#include "libavutil/mem_internal.h"
28cabdff1aSopenharmony_ci#include "libavutil/thread.h"
29cabdff1aSopenharmony_ci
30cabdff1aSopenharmony_ci#include "avcodec.h"
31cabdff1aSopenharmony_ci#include "bswapdsp.h"
32cabdff1aSopenharmony_ci#include "codec_internal.h"
33cabdff1aSopenharmony_ci#include "copy_block.h"
34cabdff1aSopenharmony_ci#include "get_bits.h"
35cabdff1aSopenharmony_ci#include "idctdsp.h"
36cabdff1aSopenharmony_ci#include "internal.h"
37cabdff1aSopenharmony_ci
38cabdff1aSopenharmony_ci#define CBPLO_VLC_BITS   6
39cabdff1aSopenharmony_ci#define CBPHI_VLC_BITS   6
40cabdff1aSopenharmony_ci#define BLKTYPE_VLC_BITS 9
41cabdff1aSopenharmony_ci#define BLOCK_VLC_BITS  12
42cabdff1aSopenharmony_ci
43cabdff1aSopenharmony_citypedef struct IMM4Context {
44cabdff1aSopenharmony_ci    BswapDSPContext bdsp;
45cabdff1aSopenharmony_ci    GetBitContext  gb;
46cabdff1aSopenharmony_ci
47cabdff1aSopenharmony_ci    AVFrame *prev_frame;
48cabdff1aSopenharmony_ci    uint8_t *bitstream;
49cabdff1aSopenharmony_ci    int bitstream_size;
50cabdff1aSopenharmony_ci
51cabdff1aSopenharmony_ci    int factor;
52cabdff1aSopenharmony_ci    unsigned lo;
53cabdff1aSopenharmony_ci    unsigned hi;
54cabdff1aSopenharmony_ci
55cabdff1aSopenharmony_ci    ScanTable intra_scantable;
56cabdff1aSopenharmony_ci    DECLARE_ALIGNED(32, int16_t, block)[6][64];
57cabdff1aSopenharmony_ci    IDCTDSPContext idsp;
58cabdff1aSopenharmony_ci} IMM4Context;
59cabdff1aSopenharmony_ci
60cabdff1aSopenharmony_cistatic const uint8_t intra_cb[] = {
61cabdff1aSopenharmony_ci    24, 18, 12
62cabdff1aSopenharmony_ci};
63cabdff1aSopenharmony_ci
64cabdff1aSopenharmony_cistatic const uint8_t inter_cb[] = {
65cabdff1aSopenharmony_ci    30, 20, 15
66cabdff1aSopenharmony_ci};
67cabdff1aSopenharmony_ci
68cabdff1aSopenharmony_cistatic const uint8_t cbplo[][2] = {
69cabdff1aSopenharmony_ci    {    0,-6 }, { 0x01, 6 }, { 0x02, 6 }, { 0x03, 6 }, { 0x00, 4 },
70cabdff1aSopenharmony_ci    { 0x01, 3 }, { 0x02, 3 }, { 0x03, 3 }, { 0x00, 1 },
71cabdff1aSopenharmony_ci};
72cabdff1aSopenharmony_ci
73cabdff1aSopenharmony_cistatic const uint8_t cbphi_bits[] = {
74cabdff1aSopenharmony_ci    4, 5, 5, 4, 5, 4, 6, 4, 5, 6, 4, 4, 4, 4, 4, 2
75cabdff1aSopenharmony_ci};
76cabdff1aSopenharmony_ci
77cabdff1aSopenharmony_cistatic const uint8_t cbphi_codes[] = {
78cabdff1aSopenharmony_ci    3, 5, 4, 9, 3, 7, 2, 11, 2, 3, 5, 10, 4, 8, 6, 3
79cabdff1aSopenharmony_ci};
80cabdff1aSopenharmony_ci
81cabdff1aSopenharmony_cistatic const uint8_t blktype[][2] = {
82cabdff1aSopenharmony_ci    {    0,-8 }, { 0x34, 9 }, {    0,-9 }, { 0x14, 9 }, {    0,-9 },
83cabdff1aSopenharmony_ci    { 0x23, 8 }, { 0x13, 8 }, { 0x32, 8 }, { 0x33, 7 }, { 0x22, 7 },
84cabdff1aSopenharmony_ci    { 0x12, 7 }, { 0x21, 7 }, { 0x11, 7 }, { 0x04, 6 }, { 0x30, 6 },
85cabdff1aSopenharmony_ci    { 0x03, 5 }, { 0x20, 4 }, { 0x10, 4 }, { 0x02, 3 }, { 0x01, 3 },
86cabdff1aSopenharmony_ci    { 0x00, 1 },
87cabdff1aSopenharmony_ci};
88cabdff1aSopenharmony_ci
89cabdff1aSopenharmony_cistatic const uint16_t block_symbols[] = {
90cabdff1aSopenharmony_ci         0, 0x4082, 0x4003, 0x000B, 0x000A, 0x4E01, 0x4D81, 0x4D01, 0x4C81,
91cabdff1aSopenharmony_ci    0x0482, 0x0402, 0x0382, 0x0302, 0x0282, 0x0183, 0x0103, 0x0084, 0x000C,
92cabdff1aSopenharmony_ci    0x0085, 0x0B81, 0x0C01, 0x4E81, 0x4F01, 0x4F81, 0x5001, 0x0086, 0x0104,
93cabdff1aSopenharmony_ci    0x0203, 0x0283, 0x0303, 0x0502, 0x0C81, 0x0D01, 0x5081, 0x5101, 0x5181,
94cabdff1aSopenharmony_ci    0x5201, 0x5281, 0x5301, 0x5381, 0x5401, 0x0000, 0x0009, 0x0008, 0x4C01,
95cabdff1aSopenharmony_ci    0x4B81, 0x4B01, 0x4A81, 0x4A01, 0x4981, 0x4901, 0x4881, 0x4002, 0x0B01,
96cabdff1aSopenharmony_ci    0x0A81, 0x0A01, 0x0981, 0x0901, 0x0881, 0x0801, 0x0781, 0x0202, 0x0182,
97cabdff1aSopenharmony_ci    0x0007, 0x0006, 0x4801, 0x4781, 0x4701, 0x4681, 0x4601, 0x4581, 0x4501,
98cabdff1aSopenharmony_ci    0x4481, 0x0701, 0x0681, 0x0102, 0x0083, 0x0005, 0x4401, 0x4381, 0x4301,
99cabdff1aSopenharmony_ci    0x4281, 0x0601, 0x0581, 0x0501, 0x0004, 0x4201, 0x4181, 0x4101, 0x4081,
100cabdff1aSopenharmony_ci    0x0481, 0x0401, 0x0381, 0x0301, 0x0082, 0x0003, 0x0281, 0x0201, 0x0181,
101cabdff1aSopenharmony_ci    0x4001, 0x0001, 0x0081, 0x0101, 0x0002,
102cabdff1aSopenharmony_ci};
103cabdff1aSopenharmony_ci
104cabdff1aSopenharmony_cistatic const uint8_t block_bits[] = {
105cabdff1aSopenharmony_ci    -9, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11,
106cabdff1aSopenharmony_ci    11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
107cabdff1aSopenharmony_ci    12, 12, 12,  7, 10, 10,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
108cabdff1aSopenharmony_ci     9,  9,  9,  9,  9,  9,  9,  9,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
109cabdff1aSopenharmony_ci     8,  8,  7,  7,  7,  7,  7,  7,  7,  7,  6,  6,  6,  6,  6,  6,  6,  6,  6,
110cabdff1aSopenharmony_ci     6,  5,  5,  5,  4,  2,  3,  4,  4,
111cabdff1aSopenharmony_ci};
112cabdff1aSopenharmony_ci
113cabdff1aSopenharmony_cistatic VLC cbplo_tab;
114cabdff1aSopenharmony_cistatic VLC cbphi_tab;
115cabdff1aSopenharmony_cistatic VLC blktype_tab;
116cabdff1aSopenharmony_cistatic VLC block_tab;
117cabdff1aSopenharmony_ci
118cabdff1aSopenharmony_cistatic int get_cbphi(GetBitContext *gb, int x)
119cabdff1aSopenharmony_ci{
120cabdff1aSopenharmony_ci    int value;
121cabdff1aSopenharmony_ci
122cabdff1aSopenharmony_ci    value = get_vlc2(gb, cbphi_tab.table, CBPHI_VLC_BITS, 1);
123cabdff1aSopenharmony_ci    if (value < 0)
124cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
125cabdff1aSopenharmony_ci
126cabdff1aSopenharmony_ci    return x ? value : 15 - value;
127cabdff1aSopenharmony_ci}
128cabdff1aSopenharmony_ci
129cabdff1aSopenharmony_cistatic int decode_block(AVCodecContext *avctx, GetBitContext *gb,
130cabdff1aSopenharmony_ci                        int block, int factor, int flag, int offset, int flag2)
131cabdff1aSopenharmony_ci{
132cabdff1aSopenharmony_ci    IMM4Context *s = avctx->priv_data;
133cabdff1aSopenharmony_ci    const uint8_t *scantable = s->intra_scantable.permutated;
134cabdff1aSopenharmony_ci    int i, last, len, factor2;
135cabdff1aSopenharmony_ci
136cabdff1aSopenharmony_ci    for (i = !flag; i < 64; i++) {
137cabdff1aSopenharmony_ci        int value;
138cabdff1aSopenharmony_ci
139cabdff1aSopenharmony_ci        value = get_vlc2(gb, block_tab.table, BLOCK_VLC_BITS, 1);
140cabdff1aSopenharmony_ci        if (value < 0)
141cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
142cabdff1aSopenharmony_ci        if (value == 0) {
143cabdff1aSopenharmony_ci            last = get_bits1(gb);
144cabdff1aSopenharmony_ci            len = get_bits(gb, 6);
145cabdff1aSopenharmony_ci            factor2 = get_sbits(gb, 8);
146cabdff1aSopenharmony_ci        } else {
147cabdff1aSopenharmony_ci            factor2 = value & 0x7F;
148cabdff1aSopenharmony_ci            last = (value >> 14) & 1;
149cabdff1aSopenharmony_ci            len = (value >> 7) & 0x3F;
150cabdff1aSopenharmony_ci            if (get_bits1(gb))
151cabdff1aSopenharmony_ci                factor2 = -factor2;
152cabdff1aSopenharmony_ci        }
153cabdff1aSopenharmony_ci        i += len;
154cabdff1aSopenharmony_ci        if (i >= 64)
155cabdff1aSopenharmony_ci            break;
156cabdff1aSopenharmony_ci        s->block[block][scantable[i]] = offset * (factor2 < 0 ? -1 : 1) + factor * factor2;
157cabdff1aSopenharmony_ci        if (last)
158cabdff1aSopenharmony_ci            break;
159cabdff1aSopenharmony_ci    }
160cabdff1aSopenharmony_ci
161cabdff1aSopenharmony_ci    if (s->hi == 2 && flag2 && block < 4) {
162cabdff1aSopenharmony_ci        if (flag)
163cabdff1aSopenharmony_ci            s->block[block][scantable[0]]  *= 2;
164cabdff1aSopenharmony_ci        s->block[block][scantable[1]]  *= 2;
165cabdff1aSopenharmony_ci        s->block[block][scantable[8]]  *= 2;
166cabdff1aSopenharmony_ci        s->block[block][scantable[16]] *= 2;
167cabdff1aSopenharmony_ci    }
168cabdff1aSopenharmony_ci
169cabdff1aSopenharmony_ci    return 0;
170cabdff1aSopenharmony_ci}
171cabdff1aSopenharmony_ci
172cabdff1aSopenharmony_cistatic int decode_blocks(AVCodecContext *avctx, GetBitContext *gb,
173cabdff1aSopenharmony_ci                         unsigned cbp, int flag, int offset, unsigned flag2)
174cabdff1aSopenharmony_ci{
175cabdff1aSopenharmony_ci    IMM4Context *s = avctx->priv_data;
176cabdff1aSopenharmony_ci    const uint8_t *scantable = s->intra_scantable.permutated;
177cabdff1aSopenharmony_ci    int ret, i;
178cabdff1aSopenharmony_ci
179cabdff1aSopenharmony_ci    memset(s->block, 0, sizeof(s->block));
180cabdff1aSopenharmony_ci
181cabdff1aSopenharmony_ci    for (i = 0; i < 6; i++) {
182cabdff1aSopenharmony_ci        if (!flag) {
183cabdff1aSopenharmony_ci            int x = get_bits(gb, 8);
184cabdff1aSopenharmony_ci
185cabdff1aSopenharmony_ci            if (x == 255)
186cabdff1aSopenharmony_ci                x = 128;
187cabdff1aSopenharmony_ci            x *= 8;
188cabdff1aSopenharmony_ci
189cabdff1aSopenharmony_ci            s->block[i][scantable[0]] = x;
190cabdff1aSopenharmony_ci        }
191cabdff1aSopenharmony_ci
192cabdff1aSopenharmony_ci        if (cbp & (1 << (5 - i))) {
193cabdff1aSopenharmony_ci            ret = decode_block(avctx, gb, i, s->factor, flag, offset, flag2);
194cabdff1aSopenharmony_ci            if (ret < 0)
195cabdff1aSopenharmony_ci                return ret;
196cabdff1aSopenharmony_ci        }
197cabdff1aSopenharmony_ci    }
198cabdff1aSopenharmony_ci
199cabdff1aSopenharmony_ci    return 0;
200cabdff1aSopenharmony_ci}
201cabdff1aSopenharmony_ci
202cabdff1aSopenharmony_cistatic int decode_intra(AVCodecContext *avctx, GetBitContext *gb, AVFrame *frame)
203cabdff1aSopenharmony_ci{
204cabdff1aSopenharmony_ci    IMM4Context *s = avctx->priv_data;
205cabdff1aSopenharmony_ci    int ret, x, y, offset = 0;
206cabdff1aSopenharmony_ci
207cabdff1aSopenharmony_ci    if (s->hi == 0) {
208cabdff1aSopenharmony_ci        if (s->lo > 2)
209cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
210cabdff1aSopenharmony_ci        s->factor = intra_cb[s->lo];
211cabdff1aSopenharmony_ci    } else {
212cabdff1aSopenharmony_ci        s->factor = s->lo * 2;
213cabdff1aSopenharmony_ci    }
214cabdff1aSopenharmony_ci
215cabdff1aSopenharmony_ci    if (s->hi) {
216cabdff1aSopenharmony_ci        offset = s->factor;
217cabdff1aSopenharmony_ci        offset >>= 1;
218cabdff1aSopenharmony_ci        if (!(offset & 1))
219cabdff1aSopenharmony_ci            offset--;
220cabdff1aSopenharmony_ci    }
221cabdff1aSopenharmony_ci
222cabdff1aSopenharmony_ci    for (y = 0; y < avctx->height; y += 16) {
223cabdff1aSopenharmony_ci        for (x = 0; x < avctx->width; x += 16) {
224cabdff1aSopenharmony_ci            unsigned flag, cbphi, cbplo;
225cabdff1aSopenharmony_ci
226cabdff1aSopenharmony_ci            cbplo = get_vlc2(gb, cbplo_tab.table, CBPLO_VLC_BITS, 1);
227cabdff1aSopenharmony_ci            flag = get_bits1(gb);
228cabdff1aSopenharmony_ci
229cabdff1aSopenharmony_ci            cbphi = get_cbphi(gb, 1);
230cabdff1aSopenharmony_ci
231cabdff1aSopenharmony_ci            ret = decode_blocks(avctx, gb, cbplo | (cbphi << 2), 0, offset, flag);
232cabdff1aSopenharmony_ci            if (ret < 0)
233cabdff1aSopenharmony_ci                return ret;
234cabdff1aSopenharmony_ci
235cabdff1aSopenharmony_ci            s->idsp.idct_put(frame->data[0] + y * frame->linesize[0] + x,
236cabdff1aSopenharmony_ci                             frame->linesize[0], s->block[0]);
237cabdff1aSopenharmony_ci            s->idsp.idct_put(frame->data[0] + y * frame->linesize[0] + x + 8,
238cabdff1aSopenharmony_ci                             frame->linesize[0], s->block[1]);
239cabdff1aSopenharmony_ci            s->idsp.idct_put(frame->data[0] + (y + 8) * frame->linesize[0] + x,
240cabdff1aSopenharmony_ci                             frame->linesize[0], s->block[2]);
241cabdff1aSopenharmony_ci            s->idsp.idct_put(frame->data[0] + (y + 8) * frame->linesize[0] + x + 8,
242cabdff1aSopenharmony_ci                             frame->linesize[0], s->block[3]);
243cabdff1aSopenharmony_ci            s->idsp.idct_put(frame->data[1] + (y >> 1) * frame->linesize[1] + (x >> 1),
244cabdff1aSopenharmony_ci                             frame->linesize[1], s->block[4]);
245cabdff1aSopenharmony_ci            s->idsp.idct_put(frame->data[2] + (y >> 1) * frame->linesize[2] + (x >> 1),
246cabdff1aSopenharmony_ci                             frame->linesize[2], s->block[5]);
247cabdff1aSopenharmony_ci        }
248cabdff1aSopenharmony_ci    }
249cabdff1aSopenharmony_ci
250cabdff1aSopenharmony_ci    return 0;
251cabdff1aSopenharmony_ci}
252cabdff1aSopenharmony_ci
253cabdff1aSopenharmony_cistatic int decode_inter(AVCodecContext *avctx, GetBitContext *gb,
254cabdff1aSopenharmony_ci                        AVFrame *frame, AVFrame *prev)
255cabdff1aSopenharmony_ci{
256cabdff1aSopenharmony_ci    IMM4Context *s = avctx->priv_data;
257cabdff1aSopenharmony_ci    int ret, x, y, offset = 0;
258cabdff1aSopenharmony_ci
259cabdff1aSopenharmony_ci    if (s->hi == 0) {
260cabdff1aSopenharmony_ci        if (s->lo > 2)
261cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
262cabdff1aSopenharmony_ci        s->factor = inter_cb[s->lo];
263cabdff1aSopenharmony_ci    } else {
264cabdff1aSopenharmony_ci        s->factor = s->lo * 2;
265cabdff1aSopenharmony_ci    }
266cabdff1aSopenharmony_ci
267cabdff1aSopenharmony_ci    if (s->hi) {
268cabdff1aSopenharmony_ci        offset = s->factor;
269cabdff1aSopenharmony_ci        offset >>= 1;
270cabdff1aSopenharmony_ci        if (!(offset & 1))
271cabdff1aSopenharmony_ci            offset--;
272cabdff1aSopenharmony_ci    }
273cabdff1aSopenharmony_ci
274cabdff1aSopenharmony_ci    for (y = 0; y < avctx->height; y += 16) {
275cabdff1aSopenharmony_ci        for (x = 0; x < avctx->width; x += 16) {
276cabdff1aSopenharmony_ci            int reverse, intra_block, value;
277cabdff1aSopenharmony_ci            unsigned cbphi, cbplo, flag2 = 0;
278cabdff1aSopenharmony_ci
279cabdff1aSopenharmony_ci            if (get_bits1(gb)) {
280cabdff1aSopenharmony_ci                copy_block16(frame->data[0] + y * frame->linesize[0] + x,
281cabdff1aSopenharmony_ci                             prev->data[0] + y * prev->linesize[0] + x,
282cabdff1aSopenharmony_ci                             frame->linesize[0], prev->linesize[0], 16);
283cabdff1aSopenharmony_ci                copy_block8(frame->data[1] + (y >> 1) * frame->linesize[1] + (x >> 1),
284cabdff1aSopenharmony_ci                            prev->data[1] + (y >> 1) * prev->linesize[1] + (x >> 1),
285cabdff1aSopenharmony_ci                            frame->linesize[1], prev->linesize[1], 8);
286cabdff1aSopenharmony_ci                copy_block8(frame->data[2] + (y >> 1) * frame->linesize[2] + (x >> 1),
287cabdff1aSopenharmony_ci                            prev->data[2] + (y >> 1) * prev->linesize[2] + (x >> 1),
288cabdff1aSopenharmony_ci                            frame->linesize[2], prev->linesize[2], 8);
289cabdff1aSopenharmony_ci                continue;
290cabdff1aSopenharmony_ci            }
291cabdff1aSopenharmony_ci
292cabdff1aSopenharmony_ci            value = get_vlc2(gb, blktype_tab.table, BLKTYPE_VLC_BITS, 1);
293cabdff1aSopenharmony_ci            if (value < 0)
294cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
295cabdff1aSopenharmony_ci
296cabdff1aSopenharmony_ci            intra_block = value & 0x07;
297cabdff1aSopenharmony_ci            reverse = intra_block == 3;
298cabdff1aSopenharmony_ci            if (reverse)
299cabdff1aSopenharmony_ci                flag2 = get_bits1(gb);
300cabdff1aSopenharmony_ci
301cabdff1aSopenharmony_ci            cbplo = value >> 4;
302cabdff1aSopenharmony_ci            cbphi = get_cbphi(gb, reverse);
303cabdff1aSopenharmony_ci            if (intra_block) {
304cabdff1aSopenharmony_ci                ret = decode_blocks(avctx, gb, cbplo | (cbphi << 2), 0, offset, flag2);
305cabdff1aSopenharmony_ci                if (ret < 0)
306cabdff1aSopenharmony_ci                    return ret;
307cabdff1aSopenharmony_ci
308cabdff1aSopenharmony_ci                s->idsp.idct_put(frame->data[0] + y * frame->linesize[0] + x,
309cabdff1aSopenharmony_ci                                 frame->linesize[0], s->block[0]);
310cabdff1aSopenharmony_ci                s->idsp.idct_put(frame->data[0] + y * frame->linesize[0] + x + 8,
311cabdff1aSopenharmony_ci                                 frame->linesize[0], s->block[1]);
312cabdff1aSopenharmony_ci                s->idsp.idct_put(frame->data[0] + (y + 8) * frame->linesize[0] + x,
313cabdff1aSopenharmony_ci                                 frame->linesize[0], s->block[2]);
314cabdff1aSopenharmony_ci                s->idsp.idct_put(frame->data[0] + (y + 8) * frame->linesize[0] + x + 8,
315cabdff1aSopenharmony_ci                                 frame->linesize[0], s->block[3]);
316cabdff1aSopenharmony_ci                s->idsp.idct_put(frame->data[1] + (y >> 1) * frame->linesize[1] + (x >> 1),
317cabdff1aSopenharmony_ci                                 frame->linesize[1], s->block[4]);
318cabdff1aSopenharmony_ci                s->idsp.idct_put(frame->data[2] + (y >> 1) * frame->linesize[2] + (x >> 1),
319cabdff1aSopenharmony_ci                                 frame->linesize[2], s->block[5]);
320cabdff1aSopenharmony_ci            } else {
321cabdff1aSopenharmony_ci                flag2 = get_bits1(gb);
322cabdff1aSopenharmony_ci                skip_bits1(gb);
323cabdff1aSopenharmony_ci                ret = decode_blocks(avctx, gb, cbplo | (cbphi << 2), 1, offset, flag2);
324cabdff1aSopenharmony_ci                if (ret < 0)
325cabdff1aSopenharmony_ci                    return ret;
326cabdff1aSopenharmony_ci
327cabdff1aSopenharmony_ci                copy_block16(frame->data[0] + y * frame->linesize[0] + x,
328cabdff1aSopenharmony_ci                             prev->data[0] + y * prev->linesize[0] + x,
329cabdff1aSopenharmony_ci                             frame->linesize[0], prev->linesize[0], 16);
330cabdff1aSopenharmony_ci                copy_block8(frame->data[1] + (y >> 1) * frame->linesize[1] + (x >> 1),
331cabdff1aSopenharmony_ci                            prev->data[1] + (y >> 1) * prev->linesize[1] + (x >> 1),
332cabdff1aSopenharmony_ci                            frame->linesize[1], prev->linesize[1], 8);
333cabdff1aSopenharmony_ci                copy_block8(frame->data[2] + (y >> 1) * frame->linesize[2] + (x >> 1),
334cabdff1aSopenharmony_ci                            prev->data[2] + (y >> 1) * prev->linesize[2] + (x >> 1),
335cabdff1aSopenharmony_ci                            frame->linesize[2], prev->linesize[2], 8);
336cabdff1aSopenharmony_ci
337cabdff1aSopenharmony_ci                s->idsp.idct_add(frame->data[0] + y * frame->linesize[0] + x,
338cabdff1aSopenharmony_ci                                 frame->linesize[0], s->block[0]);
339cabdff1aSopenharmony_ci                s->idsp.idct_add(frame->data[0] + y * frame->linesize[0] + x + 8,
340cabdff1aSopenharmony_ci                                 frame->linesize[0], s->block[1]);
341cabdff1aSopenharmony_ci                s->idsp.idct_add(frame->data[0] + (y + 8) * frame->linesize[0] + x,
342cabdff1aSopenharmony_ci                                 frame->linesize[0], s->block[2]);
343cabdff1aSopenharmony_ci                s->idsp.idct_add(frame->data[0] + (y + 8) * frame->linesize[0] + x + 8,
344cabdff1aSopenharmony_ci                                 frame->linesize[0], s->block[3]);
345cabdff1aSopenharmony_ci                s->idsp.idct_add(frame->data[1] + (y >> 1) * frame->linesize[1] + (x >> 1),
346cabdff1aSopenharmony_ci                                 frame->linesize[1], s->block[4]);
347cabdff1aSopenharmony_ci                s->idsp.idct_add(frame->data[2] + (y >> 1) * frame->linesize[2] + (x >> 1),
348cabdff1aSopenharmony_ci                                 frame->linesize[2], s->block[5]);
349cabdff1aSopenharmony_ci            }
350cabdff1aSopenharmony_ci        }
351cabdff1aSopenharmony_ci    }
352cabdff1aSopenharmony_ci
353cabdff1aSopenharmony_ci    return 0;
354cabdff1aSopenharmony_ci}
355cabdff1aSopenharmony_ci
356cabdff1aSopenharmony_cistatic int decode_frame(AVCodecContext *avctx, AVFrame *frame,
357cabdff1aSopenharmony_ci                        int *got_frame, AVPacket *avpkt)
358cabdff1aSopenharmony_ci{
359cabdff1aSopenharmony_ci    IMM4Context *s = avctx->priv_data;
360cabdff1aSopenharmony_ci    GetBitContext *gb = &s->gb;
361cabdff1aSopenharmony_ci    int width, height;
362cabdff1aSopenharmony_ci    unsigned type;
363cabdff1aSopenharmony_ci    int ret, scaled;
364cabdff1aSopenharmony_ci
365cabdff1aSopenharmony_ci    if (avpkt->size <= 32)
366cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
367cabdff1aSopenharmony_ci
368cabdff1aSopenharmony_ci    av_fast_padded_malloc(&s->bitstream, &s->bitstream_size,
369cabdff1aSopenharmony_ci                          FFALIGN(avpkt->size, 4));
370cabdff1aSopenharmony_ci    if (!s->bitstream)
371cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
372cabdff1aSopenharmony_ci
373cabdff1aSopenharmony_ci    s->bdsp.bswap_buf((uint32_t *)s->bitstream,
374cabdff1aSopenharmony_ci                      (uint32_t *)avpkt->data,
375cabdff1aSopenharmony_ci                      (avpkt->size + 3) >> 2);
376cabdff1aSopenharmony_ci
377cabdff1aSopenharmony_ci    if ((ret = init_get_bits8(gb, s->bitstream, FFALIGN(avpkt->size, 4))) < 0)
378cabdff1aSopenharmony_ci        return ret;
379cabdff1aSopenharmony_ci
380cabdff1aSopenharmony_ci    avctx->pix_fmt = AV_PIX_FMT_YUV420P;
381cabdff1aSopenharmony_ci    avctx->color_range = AVCOL_RANGE_JPEG;
382cabdff1aSopenharmony_ci
383cabdff1aSopenharmony_ci    width = avctx->width;
384cabdff1aSopenharmony_ci    height = avctx->height;
385cabdff1aSopenharmony_ci
386cabdff1aSopenharmony_ci    scaled = avpkt->data[8];
387cabdff1aSopenharmony_ci    if (scaled < 2) {
388cabdff1aSopenharmony_ci        int mode = avpkt->data[10];
389cabdff1aSopenharmony_ci
390cabdff1aSopenharmony_ci        switch (mode) {
391cabdff1aSopenharmony_ci        case 1:
392cabdff1aSopenharmony_ci            width = 352;
393cabdff1aSopenharmony_ci            height = 240;
394cabdff1aSopenharmony_ci            break;
395cabdff1aSopenharmony_ci        case 2:
396cabdff1aSopenharmony_ci            width = 704;
397cabdff1aSopenharmony_ci            height = 240;
398cabdff1aSopenharmony_ci            break;
399cabdff1aSopenharmony_ci        case 4:
400cabdff1aSopenharmony_ci            width = 480;
401cabdff1aSopenharmony_ci            height = 704;
402cabdff1aSopenharmony_ci            break;
403cabdff1aSopenharmony_ci        case 17:
404cabdff1aSopenharmony_ci            width = 352;
405cabdff1aSopenharmony_ci            height = 288;
406cabdff1aSopenharmony_ci            break;
407cabdff1aSopenharmony_ci        case 18:
408cabdff1aSopenharmony_ci            width = 704;
409cabdff1aSopenharmony_ci            height = 288;
410cabdff1aSopenharmony_ci            break;
411cabdff1aSopenharmony_ci        default:
412cabdff1aSopenharmony_ci            width = 704;
413cabdff1aSopenharmony_ci            height = 576;
414cabdff1aSopenharmony_ci            break;
415cabdff1aSopenharmony_ci        }
416cabdff1aSopenharmony_ci    }
417cabdff1aSopenharmony_ci
418cabdff1aSopenharmony_ci    skip_bits_long(gb, 24 * 8);
419cabdff1aSopenharmony_ci    type = get_bits_long(gb, 32);
420cabdff1aSopenharmony_ci    s->hi = get_bits(gb, 16);
421cabdff1aSopenharmony_ci    s->lo = get_bits(gb, 16);
422cabdff1aSopenharmony_ci
423cabdff1aSopenharmony_ci    switch (type) {
424cabdff1aSopenharmony_ci    case 0x19781977:
425cabdff1aSopenharmony_ci        frame->key_frame = 1;
426cabdff1aSopenharmony_ci        frame->pict_type = AV_PICTURE_TYPE_I;
427cabdff1aSopenharmony_ci        break;
428cabdff1aSopenharmony_ci    case 0x12250926:
429cabdff1aSopenharmony_ci        frame->key_frame = 0;
430cabdff1aSopenharmony_ci        frame->pict_type = AV_PICTURE_TYPE_P;
431cabdff1aSopenharmony_ci        break;
432cabdff1aSopenharmony_ci    default:
433cabdff1aSopenharmony_ci        avpriv_request_sample(avctx, "type %X", type);
434cabdff1aSopenharmony_ci        return AVERROR_PATCHWELCOME;
435cabdff1aSopenharmony_ci    }
436cabdff1aSopenharmony_ci
437cabdff1aSopenharmony_ci    if (avctx->width  != width ||
438cabdff1aSopenharmony_ci        avctx->height != height) {
439cabdff1aSopenharmony_ci        if (!frame->key_frame) {
440cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_ERROR, "Frame size change is unsupported.\n");
441cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
442cabdff1aSopenharmony_ci        }
443cabdff1aSopenharmony_ci        av_frame_unref(s->prev_frame);
444cabdff1aSopenharmony_ci    }
445cabdff1aSopenharmony_ci
446cabdff1aSopenharmony_ci    ret = ff_set_dimensions(avctx, width, height);
447cabdff1aSopenharmony_ci    if (ret < 0)
448cabdff1aSopenharmony_ci        return ret;
449cabdff1aSopenharmony_ci
450cabdff1aSopenharmony_ci    if ((ret = ff_get_buffer(avctx, frame, frame->key_frame ? AV_GET_BUFFER_FLAG_REF : 0)) < 0)
451cabdff1aSopenharmony_ci        return ret;
452cabdff1aSopenharmony_ci
453cabdff1aSopenharmony_ci    if (frame->key_frame) {
454cabdff1aSopenharmony_ci        ret = decode_intra(avctx, gb, frame);
455cabdff1aSopenharmony_ci        if (ret < 0)
456cabdff1aSopenharmony_ci            return ret;
457cabdff1aSopenharmony_ci
458cabdff1aSopenharmony_ci        av_frame_unref(s->prev_frame);
459cabdff1aSopenharmony_ci        if ((ret = av_frame_ref(s->prev_frame, frame)) < 0)
460cabdff1aSopenharmony_ci            return ret;
461cabdff1aSopenharmony_ci    } else {
462cabdff1aSopenharmony_ci        if (!s->prev_frame->data[0]) {
463cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_ERROR, "Missing reference frame.\n");
464cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
465cabdff1aSopenharmony_ci        }
466cabdff1aSopenharmony_ci
467cabdff1aSopenharmony_ci        ret = decode_inter(avctx, gb, frame, s->prev_frame);
468cabdff1aSopenharmony_ci        if (ret < 0)
469cabdff1aSopenharmony_ci            return ret;
470cabdff1aSopenharmony_ci    }
471cabdff1aSopenharmony_ci
472cabdff1aSopenharmony_ci    *got_frame = 1;
473cabdff1aSopenharmony_ci
474cabdff1aSopenharmony_ci    return avpkt->size;
475cabdff1aSopenharmony_ci}
476cabdff1aSopenharmony_ci
477cabdff1aSopenharmony_cistatic av_cold void imm4_init_static_data(void)
478cabdff1aSopenharmony_ci{
479cabdff1aSopenharmony_ci    INIT_VLC_STATIC_FROM_LENGTHS(&cbplo_tab, CBPLO_VLC_BITS, FF_ARRAY_ELEMS(cbplo),
480cabdff1aSopenharmony_ci                                 &cbplo[0][1], 2, &cbplo[0][0], 2, 1,
481cabdff1aSopenharmony_ci                                 0, 0, 1 << CBPLO_VLC_BITS);
482cabdff1aSopenharmony_ci
483cabdff1aSopenharmony_ci    INIT_VLC_SPARSE_STATIC(&cbphi_tab, CBPHI_VLC_BITS, FF_ARRAY_ELEMS(cbphi_bits),
484cabdff1aSopenharmony_ci                           cbphi_bits, 1, 1, cbphi_codes, 1, 1, NULL, 0, 0, 64);
485cabdff1aSopenharmony_ci
486cabdff1aSopenharmony_ci    INIT_VLC_STATIC_FROM_LENGTHS(&blktype_tab, BLKTYPE_VLC_BITS, FF_ARRAY_ELEMS(blktype),
487cabdff1aSopenharmony_ci                                 &blktype[0][1], 2, &blktype[0][0], 2, 1,
488cabdff1aSopenharmony_ci                                 0, 0, 1 << BLKTYPE_VLC_BITS);
489cabdff1aSopenharmony_ci
490cabdff1aSopenharmony_ci    INIT_VLC_STATIC_FROM_LENGTHS(&block_tab, BLOCK_VLC_BITS, FF_ARRAY_ELEMS(block_bits),
491cabdff1aSopenharmony_ci                                 block_bits, 1, block_symbols, 2, 2,
492cabdff1aSopenharmony_ci                                 0, 0, 1 << BLOCK_VLC_BITS);
493cabdff1aSopenharmony_ci}
494cabdff1aSopenharmony_ci
495cabdff1aSopenharmony_cistatic av_cold int decode_init(AVCodecContext *avctx)
496cabdff1aSopenharmony_ci{
497cabdff1aSopenharmony_ci    static AVOnce init_static_once = AV_ONCE_INIT;
498cabdff1aSopenharmony_ci    IMM4Context *s = avctx->priv_data;
499cabdff1aSopenharmony_ci    uint8_t table[64];
500cabdff1aSopenharmony_ci
501cabdff1aSopenharmony_ci    for (int i = 0; i < 64; i++)
502cabdff1aSopenharmony_ci        table[i] = i;
503cabdff1aSopenharmony_ci
504cabdff1aSopenharmony_ci    ff_bswapdsp_init(&s->bdsp);
505cabdff1aSopenharmony_ci    ff_idctdsp_init(&s->idsp, avctx);
506cabdff1aSopenharmony_ci    ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable, table);
507cabdff1aSopenharmony_ci
508cabdff1aSopenharmony_ci    s->prev_frame = av_frame_alloc();
509cabdff1aSopenharmony_ci    if (!s->prev_frame)
510cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
511cabdff1aSopenharmony_ci
512cabdff1aSopenharmony_ci    ff_thread_once(&init_static_once, imm4_init_static_data);
513cabdff1aSopenharmony_ci
514cabdff1aSopenharmony_ci    return 0;
515cabdff1aSopenharmony_ci}
516cabdff1aSopenharmony_ci
517cabdff1aSopenharmony_cistatic void decode_flush(AVCodecContext *avctx)
518cabdff1aSopenharmony_ci{
519cabdff1aSopenharmony_ci    IMM4Context *s = avctx->priv_data;
520cabdff1aSopenharmony_ci
521cabdff1aSopenharmony_ci    av_frame_unref(s->prev_frame);
522cabdff1aSopenharmony_ci}
523cabdff1aSopenharmony_ci
524cabdff1aSopenharmony_cistatic av_cold int decode_close(AVCodecContext *avctx)
525cabdff1aSopenharmony_ci{
526cabdff1aSopenharmony_ci    IMM4Context *s = avctx->priv_data;
527cabdff1aSopenharmony_ci
528cabdff1aSopenharmony_ci    av_frame_free(&s->prev_frame);
529cabdff1aSopenharmony_ci    av_freep(&s->bitstream);
530cabdff1aSopenharmony_ci    s->bitstream_size = 0;
531cabdff1aSopenharmony_ci
532cabdff1aSopenharmony_ci    return 0;
533cabdff1aSopenharmony_ci}
534cabdff1aSopenharmony_ci
535cabdff1aSopenharmony_ciconst FFCodec ff_imm4_decoder = {
536cabdff1aSopenharmony_ci    .p.name           = "imm4",
537cabdff1aSopenharmony_ci    .p.long_name      = NULL_IF_CONFIG_SMALL("Infinity IMM4"),
538cabdff1aSopenharmony_ci    .p.type           = AVMEDIA_TYPE_VIDEO,
539cabdff1aSopenharmony_ci    .p.id             = AV_CODEC_ID_IMM4,
540cabdff1aSopenharmony_ci    .priv_data_size   = sizeof(IMM4Context),
541cabdff1aSopenharmony_ci    .init             = decode_init,
542cabdff1aSopenharmony_ci    .close            = decode_close,
543cabdff1aSopenharmony_ci    FF_CODEC_DECODE_CB(decode_frame),
544cabdff1aSopenharmony_ci    .flush            = decode_flush,
545cabdff1aSopenharmony_ci    .p.capabilities   = AV_CODEC_CAP_DR1,
546cabdff1aSopenharmony_ci    .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE |
547cabdff1aSopenharmony_ci                        FF_CODEC_CAP_INIT_CLEANUP,
548cabdff1aSopenharmony_ci};
549