1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * Gremlin Digital Video (GDV) decoder
3cabdff1aSopenharmony_ci * Copyright (c) 2017 Konstantin Shishkov
4cabdff1aSopenharmony_ci * Copyright (c) 2017 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 "libavutil/common.h"
24cabdff1aSopenharmony_ci#include "avcodec.h"
25cabdff1aSopenharmony_ci#include "bytestream.h"
26cabdff1aSopenharmony_ci#include "codec_internal.h"
27cabdff1aSopenharmony_ci#include "decode.h"
28cabdff1aSopenharmony_ci#include "internal.h"
29cabdff1aSopenharmony_ci
30cabdff1aSopenharmony_citypedef struct GDVContext {
31cabdff1aSopenharmony_ci    AVCodecContext *avctx;
32cabdff1aSopenharmony_ci
33cabdff1aSopenharmony_ci    GetByteContext gb;
34cabdff1aSopenharmony_ci    GetByteContext g2;
35cabdff1aSopenharmony_ci    PutByteContext pb;
36cabdff1aSopenharmony_ci
37cabdff1aSopenharmony_ci    uint32_t pal[256];
38cabdff1aSopenharmony_ci    uint8_t *frame;
39cabdff1aSopenharmony_ci    unsigned frame_size;
40cabdff1aSopenharmony_ci    unsigned scale_h, scale_v;
41cabdff1aSopenharmony_ci} GDVContext;
42cabdff1aSopenharmony_ci
43cabdff1aSopenharmony_citypedef struct Bits8 {
44cabdff1aSopenharmony_ci    uint8_t queue;
45cabdff1aSopenharmony_ci    uint8_t fill;
46cabdff1aSopenharmony_ci} Bits8;
47cabdff1aSopenharmony_ci
48cabdff1aSopenharmony_citypedef struct Bits32 {
49cabdff1aSopenharmony_ci    uint32_t queue;
50cabdff1aSopenharmony_ci    uint8_t  fill;
51cabdff1aSopenharmony_ci} Bits32;
52cabdff1aSopenharmony_ci
53cabdff1aSopenharmony_ci#define PREAMBLE_SIZE 4096
54cabdff1aSopenharmony_ci
55cabdff1aSopenharmony_cistatic av_cold int gdv_decode_init(AVCodecContext *avctx)
56cabdff1aSopenharmony_ci{
57cabdff1aSopenharmony_ci    GDVContext *gdv = avctx->priv_data;
58cabdff1aSopenharmony_ci    int i, j, k;
59cabdff1aSopenharmony_ci
60cabdff1aSopenharmony_ci    avctx->pix_fmt  = AV_PIX_FMT_PAL8;
61cabdff1aSopenharmony_ci    gdv->frame_size = avctx->width * avctx->height + PREAMBLE_SIZE;
62cabdff1aSopenharmony_ci    gdv->frame = av_calloc(gdv->frame_size, 1);
63cabdff1aSopenharmony_ci    if (!gdv->frame)
64cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
65cabdff1aSopenharmony_ci
66cabdff1aSopenharmony_ci    for (i = 0; i < 2; i++) {
67cabdff1aSopenharmony_ci        for (j = 0; j < 256; j++) {
68cabdff1aSopenharmony_ci            for (k = 0; k < 8; k++) {
69cabdff1aSopenharmony_ci                gdv->frame[i * 2048 + j * 8 + k] = j;
70cabdff1aSopenharmony_ci            }
71cabdff1aSopenharmony_ci        }
72cabdff1aSopenharmony_ci    }
73cabdff1aSopenharmony_ci
74cabdff1aSopenharmony_ci    return 0;
75cabdff1aSopenharmony_ci}
76cabdff1aSopenharmony_ci
77cabdff1aSopenharmony_cistatic void scaleup(uint8_t *dst, const uint8_t *src, int w)
78cabdff1aSopenharmony_ci{
79cabdff1aSopenharmony_ci    int x;
80cabdff1aSopenharmony_ci    for (x = 0; x < w - 7; x+=8) {
81cabdff1aSopenharmony_ci        dst[x + 0] =
82cabdff1aSopenharmony_ci        dst[x + 1] = src[(x>>1) + 0];
83cabdff1aSopenharmony_ci        dst[x + 2] =
84cabdff1aSopenharmony_ci        dst[x + 3] = src[(x>>1) + 1];
85cabdff1aSopenharmony_ci        dst[x + 4] =
86cabdff1aSopenharmony_ci        dst[x + 5] = src[(x>>1) + 2];
87cabdff1aSopenharmony_ci        dst[x + 6] =
88cabdff1aSopenharmony_ci        dst[x + 7] = src[(x>>1) + 3];
89cabdff1aSopenharmony_ci    }
90cabdff1aSopenharmony_ci    for (; x < w; x++) {
91cabdff1aSopenharmony_ci        dst[x] = src[(x>>1)];
92cabdff1aSopenharmony_ci    }
93cabdff1aSopenharmony_ci}
94cabdff1aSopenharmony_ci
95cabdff1aSopenharmony_cistatic void scaleup_rev(uint8_t *dst, const uint8_t *src, int w)
96cabdff1aSopenharmony_ci{
97cabdff1aSopenharmony_ci    int x;
98cabdff1aSopenharmony_ci
99cabdff1aSopenharmony_ci    for (x = w - 1; (x+1) & 7; x--) {
100cabdff1aSopenharmony_ci        dst[x] = src[(x>>1)];
101cabdff1aSopenharmony_ci    }
102cabdff1aSopenharmony_ci    for (x -= 7; x >= 0; x -= 8) {
103cabdff1aSopenharmony_ci        dst[x + 6] =
104cabdff1aSopenharmony_ci        dst[x + 7] = src[(x>>1) + 3];
105cabdff1aSopenharmony_ci        dst[x + 4] =
106cabdff1aSopenharmony_ci        dst[x + 5] = src[(x>>1) + 2];
107cabdff1aSopenharmony_ci        dst[x + 2] =
108cabdff1aSopenharmony_ci        dst[x + 3] = src[(x>>1) + 1];
109cabdff1aSopenharmony_ci        dst[x + 0] =
110cabdff1aSopenharmony_ci        dst[x + 1] = src[(x>>1) + 0];
111cabdff1aSopenharmony_ci    }
112cabdff1aSopenharmony_ci}
113cabdff1aSopenharmony_ci
114cabdff1aSopenharmony_cistatic void scaledown(uint8_t *dst, const uint8_t *src, int w)
115cabdff1aSopenharmony_ci{
116cabdff1aSopenharmony_ci    int x;
117cabdff1aSopenharmony_ci    for (x = 0; x < w - 7; x+=8) {
118cabdff1aSopenharmony_ci        dst[x + 0] = src[2*x + 0];
119cabdff1aSopenharmony_ci        dst[x + 1] = src[2*x + 2];
120cabdff1aSopenharmony_ci        dst[x + 2] = src[2*x + 4];
121cabdff1aSopenharmony_ci        dst[x + 3] = src[2*x + 6];
122cabdff1aSopenharmony_ci        dst[x + 4] = src[2*x + 8];
123cabdff1aSopenharmony_ci        dst[x + 5] = src[2*x +10];
124cabdff1aSopenharmony_ci        dst[x + 6] = src[2*x +12];
125cabdff1aSopenharmony_ci        dst[x + 7] = src[2*x +14];
126cabdff1aSopenharmony_ci    }
127cabdff1aSopenharmony_ci    for (; x < w; x++) {
128cabdff1aSopenharmony_ci        dst[x] = src[2*x];
129cabdff1aSopenharmony_ci    }
130cabdff1aSopenharmony_ci}
131cabdff1aSopenharmony_ci
132cabdff1aSopenharmony_cistatic void rescale(GDVContext *gdv, uint8_t *dst, int w, int h, int scale_v, int scale_h)
133cabdff1aSopenharmony_ci{
134cabdff1aSopenharmony_ci    int j, y;
135cabdff1aSopenharmony_ci
136cabdff1aSopenharmony_ci    if ((gdv->scale_v == scale_v) && (gdv->scale_h == scale_h)) {
137cabdff1aSopenharmony_ci        return;
138cabdff1aSopenharmony_ci    }
139cabdff1aSopenharmony_ci
140cabdff1aSopenharmony_ci    if (gdv->scale_v) {
141cabdff1aSopenharmony_ci        for (j = 0; j < h; j++) {
142cabdff1aSopenharmony_ci            int y = h - j - 1;
143cabdff1aSopenharmony_ci            uint8_t *dst1 = dst + PREAMBLE_SIZE + y * w;
144cabdff1aSopenharmony_ci            uint8_t *src1 = dst + PREAMBLE_SIZE + (y>>!!gdv->scale_h) * (w>>1);
145cabdff1aSopenharmony_ci
146cabdff1aSopenharmony_ci            scaleup_rev(dst1, src1, w);
147cabdff1aSopenharmony_ci        }
148cabdff1aSopenharmony_ci    } else if (gdv->scale_h) {
149cabdff1aSopenharmony_ci        for (j = 0; j < h; j++) {
150cabdff1aSopenharmony_ci            int y = h - j - 1;
151cabdff1aSopenharmony_ci            uint8_t *dst1 = dst + PREAMBLE_SIZE + y * w;
152cabdff1aSopenharmony_ci            uint8_t *src1 = dst + PREAMBLE_SIZE + (y>>1) * w;
153cabdff1aSopenharmony_ci            memcpy(dst1, src1, w);
154cabdff1aSopenharmony_ci        }
155cabdff1aSopenharmony_ci    }
156cabdff1aSopenharmony_ci
157cabdff1aSopenharmony_ci    if (scale_h && scale_v) {
158cabdff1aSopenharmony_ci        for (y = 0; y < (h>>1); y++) {
159cabdff1aSopenharmony_ci            uint8_t *dst1 = dst + PREAMBLE_SIZE + y * (w>>1);
160cabdff1aSopenharmony_ci            uint8_t *src1 = dst + PREAMBLE_SIZE + y*2 * w;
161cabdff1aSopenharmony_ci            scaledown(dst1, src1, w>>1);
162cabdff1aSopenharmony_ci        }
163cabdff1aSopenharmony_ci    } else if (scale_h) {
164cabdff1aSopenharmony_ci        for (y = 0; y < (h>>1); y++) {
165cabdff1aSopenharmony_ci            uint8_t *dst1 = dst + PREAMBLE_SIZE + y * w;
166cabdff1aSopenharmony_ci            uint8_t *src1 = dst + PREAMBLE_SIZE + y*2 * w;
167cabdff1aSopenharmony_ci            memcpy(dst1, src1, w);
168cabdff1aSopenharmony_ci        }
169cabdff1aSopenharmony_ci    } else if (scale_v) {
170cabdff1aSopenharmony_ci        for (y = 0; y < h; y++) {
171cabdff1aSopenharmony_ci            uint8_t *dst1 = dst + PREAMBLE_SIZE + y * w;
172cabdff1aSopenharmony_ci            scaledown(dst1, dst1, w>>1);
173cabdff1aSopenharmony_ci        }
174cabdff1aSopenharmony_ci    }
175cabdff1aSopenharmony_ci
176cabdff1aSopenharmony_ci    gdv->scale_v = scale_v;
177cabdff1aSopenharmony_ci    gdv->scale_h = scale_h;
178cabdff1aSopenharmony_ci}
179cabdff1aSopenharmony_ci
180cabdff1aSopenharmony_cistatic int read_bits2(Bits8 *bits, GetByteContext *gb)
181cabdff1aSopenharmony_ci{
182cabdff1aSopenharmony_ci    int res;
183cabdff1aSopenharmony_ci
184cabdff1aSopenharmony_ci    if (bits->fill == 0) {
185cabdff1aSopenharmony_ci        bits->queue |= bytestream2_get_byte(gb);
186cabdff1aSopenharmony_ci        bits->fill   = 8;
187cabdff1aSopenharmony_ci    }
188cabdff1aSopenharmony_ci    res = bits->queue >> 6;
189cabdff1aSopenharmony_ci    bits->queue <<= 2;
190cabdff1aSopenharmony_ci    bits->fill   -= 2;
191cabdff1aSopenharmony_ci
192cabdff1aSopenharmony_ci    return res;
193cabdff1aSopenharmony_ci}
194cabdff1aSopenharmony_ci
195cabdff1aSopenharmony_cistatic void fill_bits32(Bits32 *bits, GetByteContext *gb)
196cabdff1aSopenharmony_ci{
197cabdff1aSopenharmony_ci    bits->queue = bytestream2_get_le32(gb);
198cabdff1aSopenharmony_ci    bits->fill  = 32;
199cabdff1aSopenharmony_ci}
200cabdff1aSopenharmony_ci
201cabdff1aSopenharmony_cistatic int read_bits32(Bits32 *bits, GetByteContext *gb, int nbits)
202cabdff1aSopenharmony_ci{
203cabdff1aSopenharmony_ci    int res = bits->queue & ((1 << nbits) - 1);
204cabdff1aSopenharmony_ci
205cabdff1aSopenharmony_ci    bits->queue >>= nbits;
206cabdff1aSopenharmony_ci    bits->fill   -= nbits;
207cabdff1aSopenharmony_ci    if (bits->fill <= 16) {
208cabdff1aSopenharmony_ci        bits->queue |= bytestream2_get_le16(gb) << bits->fill;
209cabdff1aSopenharmony_ci        bits->fill  += 16;
210cabdff1aSopenharmony_ci    }
211cabdff1aSopenharmony_ci
212cabdff1aSopenharmony_ci    return res;
213cabdff1aSopenharmony_ci}
214cabdff1aSopenharmony_ci
215cabdff1aSopenharmony_cistatic void lz_copy(PutByteContext *pb, GetByteContext *g2, int offset, unsigned len)
216cabdff1aSopenharmony_ci{
217cabdff1aSopenharmony_ci    int i;
218cabdff1aSopenharmony_ci
219cabdff1aSopenharmony_ci    if (offset == -1) {
220cabdff1aSopenharmony_ci        int c;
221cabdff1aSopenharmony_ci
222cabdff1aSopenharmony_ci        bytestream2_seek(g2, bytestream2_tell_p(pb) - 1, SEEK_SET);
223cabdff1aSopenharmony_ci        c = bytestream2_get_byte(g2);
224cabdff1aSopenharmony_ci        for (i = 0; i < len; i++) {
225cabdff1aSopenharmony_ci            bytestream2_put_byte(pb, c);
226cabdff1aSopenharmony_ci        }
227cabdff1aSopenharmony_ci    } else if (offset < 0) {
228cabdff1aSopenharmony_ci        int start = bytestream2_tell_p(pb) - (-offset);
229cabdff1aSopenharmony_ci
230cabdff1aSopenharmony_ci        bytestream2_seek(g2, start, SEEK_SET);
231cabdff1aSopenharmony_ci        for (i = 0; i < len; i++) {
232cabdff1aSopenharmony_ci            bytestream2_put_byte(pb, bytestream2_get_byte(g2));
233cabdff1aSopenharmony_ci        }
234cabdff1aSopenharmony_ci    } else {
235cabdff1aSopenharmony_ci        int start = bytestream2_tell_p(pb) + offset;
236cabdff1aSopenharmony_ci
237cabdff1aSopenharmony_ci        bytestream2_seek(g2, start, SEEK_SET);
238cabdff1aSopenharmony_ci        for (i = 0; i < len; i++) {
239cabdff1aSopenharmony_ci            bytestream2_put_byte(pb, bytestream2_get_byte(g2));
240cabdff1aSopenharmony_ci        }
241cabdff1aSopenharmony_ci    }
242cabdff1aSopenharmony_ci}
243cabdff1aSopenharmony_ci
244cabdff1aSopenharmony_cistatic int decompress_2(AVCodecContext *avctx)
245cabdff1aSopenharmony_ci{
246cabdff1aSopenharmony_ci    GDVContext *gdv = avctx->priv_data;
247cabdff1aSopenharmony_ci    GetByteContext *gb = &gdv->gb;
248cabdff1aSopenharmony_ci    GetByteContext *g2 = &gdv->g2;
249cabdff1aSopenharmony_ci    PutByteContext *pb = &gdv->pb;
250cabdff1aSopenharmony_ci    Bits8 bits = { 0 };
251cabdff1aSopenharmony_ci    int c, i;
252cabdff1aSopenharmony_ci
253cabdff1aSopenharmony_ci    bytestream2_init(g2, gdv->frame, gdv->frame_size);
254cabdff1aSopenharmony_ci    bytestream2_skip_p(pb, PREAMBLE_SIZE);
255cabdff1aSopenharmony_ci
256cabdff1aSopenharmony_ci    for (c = 0; c < 256; c++) {
257cabdff1aSopenharmony_ci        for (i = 0; i < 16; i++) {
258cabdff1aSopenharmony_ci            gdv->frame[c * 16 + i] = c;
259cabdff1aSopenharmony_ci        }
260cabdff1aSopenharmony_ci    }
261cabdff1aSopenharmony_ci
262cabdff1aSopenharmony_ci    while (bytestream2_get_bytes_left_p(pb) > 0 && bytestream2_get_bytes_left(gb) > 0) {
263cabdff1aSopenharmony_ci        int tag = read_bits2(&bits, gb);
264cabdff1aSopenharmony_ci        if (tag == 0) {
265cabdff1aSopenharmony_ci            bytestream2_put_byte(pb, bytestream2_get_byte(gb));
266cabdff1aSopenharmony_ci        } else if (tag == 1) {
267cabdff1aSopenharmony_ci            int b = bytestream2_get_byte(gb);
268cabdff1aSopenharmony_ci            int len = (b & 0xF) + 3;
269cabdff1aSopenharmony_ci            int top = (b >> 4) & 0xF;
270cabdff1aSopenharmony_ci            int off = (bytestream2_get_byte(gb) << 4) + top - 4096;
271cabdff1aSopenharmony_ci            lz_copy(pb, g2, off, len);
272cabdff1aSopenharmony_ci        } else if (tag == 2) {
273cabdff1aSopenharmony_ci            int len = (bytestream2_get_byte(gb)) + 2;
274cabdff1aSopenharmony_ci            bytestream2_skip_p(pb, len);
275cabdff1aSopenharmony_ci        } else {
276cabdff1aSopenharmony_ci            break;
277cabdff1aSopenharmony_ci        }
278cabdff1aSopenharmony_ci    }
279cabdff1aSopenharmony_ci
280cabdff1aSopenharmony_ci    if (bytestream2_get_bytes_left_p(pb) > 0)
281cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
282cabdff1aSopenharmony_ci
283cabdff1aSopenharmony_ci    return 0;
284cabdff1aSopenharmony_ci}
285cabdff1aSopenharmony_ci
286cabdff1aSopenharmony_cistatic int decompress_5(AVCodecContext *avctx, unsigned skip)
287cabdff1aSopenharmony_ci{
288cabdff1aSopenharmony_ci    GDVContext *gdv = avctx->priv_data;
289cabdff1aSopenharmony_ci    GetByteContext *gb = &gdv->gb;
290cabdff1aSopenharmony_ci    GetByteContext *g2 = &gdv->g2;
291cabdff1aSopenharmony_ci    PutByteContext *pb = &gdv->pb;
292cabdff1aSopenharmony_ci    Bits8 bits = { 0 };
293cabdff1aSopenharmony_ci
294cabdff1aSopenharmony_ci    bytestream2_init(g2, gdv->frame, gdv->frame_size);
295cabdff1aSopenharmony_ci    bytestream2_skip_p(pb, skip + PREAMBLE_SIZE);
296cabdff1aSopenharmony_ci
297cabdff1aSopenharmony_ci    while (bytestream2_get_bytes_left_p(pb) > 0 && bytestream2_get_bytes_left(gb) > 0) {
298cabdff1aSopenharmony_ci        int tag = read_bits2(&bits, gb);
299cabdff1aSopenharmony_ci        if (bytestream2_get_bytes_left(gb) < 1)
300cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
301cabdff1aSopenharmony_ci        if (tag == 0) {
302cabdff1aSopenharmony_ci            bytestream2_put_byte(pb, bytestream2_get_byte(gb));
303cabdff1aSopenharmony_ci        } else if (tag == 1) {
304cabdff1aSopenharmony_ci            int b = bytestream2_get_byte(gb);
305cabdff1aSopenharmony_ci            int len = (b & 0xF) + 3;
306cabdff1aSopenharmony_ci            int top = b >> 4;
307cabdff1aSopenharmony_ci            int off = (bytestream2_get_byte(gb) << 4) + top - 4096;
308cabdff1aSopenharmony_ci            lz_copy(pb, g2, off, len);
309cabdff1aSopenharmony_ci        } else if (tag == 2) {
310cabdff1aSopenharmony_ci            int len;
311cabdff1aSopenharmony_ci            int b = bytestream2_get_byte(gb);
312cabdff1aSopenharmony_ci            if (b == 0) {
313cabdff1aSopenharmony_ci                return 0;
314cabdff1aSopenharmony_ci            }
315cabdff1aSopenharmony_ci            if (b != 0xFF) {
316cabdff1aSopenharmony_ci                len = b;
317cabdff1aSopenharmony_ci            } else {
318cabdff1aSopenharmony_ci                len = bytestream2_get_le16(gb);
319cabdff1aSopenharmony_ci            }
320cabdff1aSopenharmony_ci            bytestream2_skip_p(pb, len + 1);
321cabdff1aSopenharmony_ci        } else {
322cabdff1aSopenharmony_ci            int b = bytestream2_get_byte(gb);
323cabdff1aSopenharmony_ci            int len = (b & 0x3) + 2;
324cabdff1aSopenharmony_ci            int off = -(b >> 2) - 1;
325cabdff1aSopenharmony_ci            lz_copy(pb, g2, off, len);
326cabdff1aSopenharmony_ci        }
327cabdff1aSopenharmony_ci    }
328cabdff1aSopenharmony_ci    if (bytestream2_get_bytes_left_p(pb) > 0)
329cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
330cabdff1aSopenharmony_ci    return 0;
331cabdff1aSopenharmony_ci}
332cabdff1aSopenharmony_ci
333cabdff1aSopenharmony_cistatic int decompress_68(AVCodecContext *avctx, unsigned skip, unsigned use8)
334cabdff1aSopenharmony_ci{
335cabdff1aSopenharmony_ci    GDVContext *gdv = avctx->priv_data;
336cabdff1aSopenharmony_ci    GetByteContext *gb = &gdv->gb;
337cabdff1aSopenharmony_ci    GetByteContext *g2 = &gdv->g2;
338cabdff1aSopenharmony_ci    PutByteContext *pb = &gdv->pb;
339cabdff1aSopenharmony_ci    Bits32 bits;
340cabdff1aSopenharmony_ci
341cabdff1aSopenharmony_ci    bytestream2_init(g2, gdv->frame, gdv->frame_size);
342cabdff1aSopenharmony_ci    bytestream2_skip_p(pb, skip + PREAMBLE_SIZE);
343cabdff1aSopenharmony_ci    fill_bits32(&bits, gb);
344cabdff1aSopenharmony_ci
345cabdff1aSopenharmony_ci    while (bytestream2_get_bytes_left_p(pb) > 0 && bytestream2_get_bytes_left(gb) > 0) {
346cabdff1aSopenharmony_ci        int tag = read_bits32(&bits, gb, 2);
347cabdff1aSopenharmony_ci        if (tag == 0) {
348cabdff1aSopenharmony_ci            int b = read_bits32(&bits, gb, 1);
349cabdff1aSopenharmony_ci            if (b == 0) {
350cabdff1aSopenharmony_ci                bytestream2_put_byte(pb, bytestream2_get_byte(gb));
351cabdff1aSopenharmony_ci            } else {
352cabdff1aSopenharmony_ci                int i, len = 2;
353cabdff1aSopenharmony_ci                int lbits = 0;
354cabdff1aSopenharmony_ci                while (1) {
355cabdff1aSopenharmony_ci                    int val;
356cabdff1aSopenharmony_ci
357cabdff1aSopenharmony_ci                    lbits += 1;
358cabdff1aSopenharmony_ci                    val = read_bits32(&bits, gb, lbits);
359cabdff1aSopenharmony_ci                    len += val;
360cabdff1aSopenharmony_ci                    if (val != ((1 << lbits) - 1)) {
361cabdff1aSopenharmony_ci                        break;
362cabdff1aSopenharmony_ci                    }
363cabdff1aSopenharmony_ci                    if (lbits >= 16)
364cabdff1aSopenharmony_ci                        return AVERROR_INVALIDDATA;
365cabdff1aSopenharmony_ci                }
366cabdff1aSopenharmony_ci                for (i = 0; i < len; i++) {
367cabdff1aSopenharmony_ci                    bytestream2_put_byte(pb, bytestream2_get_byte(gb));
368cabdff1aSopenharmony_ci                }
369cabdff1aSopenharmony_ci            }
370cabdff1aSopenharmony_ci        } else if (tag == 1) {
371cabdff1aSopenharmony_ci            int b = read_bits32(&bits, gb, 1);
372cabdff1aSopenharmony_ci            int len;
373cabdff1aSopenharmony_ci
374cabdff1aSopenharmony_ci            if (b == 0) {
375cabdff1aSopenharmony_ci                len = (read_bits32(&bits, gb, 4)) + 2;
376cabdff1aSopenharmony_ci            } else {
377cabdff1aSopenharmony_ci                int bb = bytestream2_get_byte(gb);
378cabdff1aSopenharmony_ci                if ((bb & 0x80) == 0) {
379cabdff1aSopenharmony_ci                    len = bb + 18;
380cabdff1aSopenharmony_ci                } else {
381cabdff1aSopenharmony_ci                    int top = (bb & 0x7F) << 8;
382cabdff1aSopenharmony_ci                    len = top + bytestream2_get_byte(gb) + 146;
383cabdff1aSopenharmony_ci                }
384cabdff1aSopenharmony_ci            }
385cabdff1aSopenharmony_ci            bytestream2_skip_p(pb, len);
386cabdff1aSopenharmony_ci        } else if (tag == 2) {
387cabdff1aSopenharmony_ci            int i, subtag = read_bits32(&bits, gb, 2);
388cabdff1aSopenharmony_ci
389cabdff1aSopenharmony_ci            if (subtag != 3) {
390cabdff1aSopenharmony_ci                int top = (read_bits32(&bits, gb, 4)) << 8;
391cabdff1aSopenharmony_ci                int offs = top + bytestream2_get_byte(gb);
392cabdff1aSopenharmony_ci                if ((subtag != 0) || (offs <= 0xF80)) {
393cabdff1aSopenharmony_ci                    int len = (subtag) + 3;
394cabdff1aSopenharmony_ci                    lz_copy(pb, g2, (offs) - 4096, len);
395cabdff1aSopenharmony_ci                } else {
396cabdff1aSopenharmony_ci                    int real_off, len, c1, c2;
397cabdff1aSopenharmony_ci
398cabdff1aSopenharmony_ci                    if (offs == 0xFFF) {
399cabdff1aSopenharmony_ci                        return 0;
400cabdff1aSopenharmony_ci                    }
401cabdff1aSopenharmony_ci
402cabdff1aSopenharmony_ci                    real_off = ((offs >> 4) & 0x7) + 1;
403cabdff1aSopenharmony_ci                    len = ((offs & 0xF) + 2) * 2;
404cabdff1aSopenharmony_ci                    c1 = gdv->frame[bytestream2_tell_p(pb) - real_off];
405cabdff1aSopenharmony_ci                    c2 = gdv->frame[bytestream2_tell_p(pb) - real_off + 1];
406cabdff1aSopenharmony_ci                    for (i = 0; i < len/2; i++) {
407cabdff1aSopenharmony_ci                        bytestream2_put_byte(pb, c1);
408cabdff1aSopenharmony_ci                        bytestream2_put_byte(pb, c2);
409cabdff1aSopenharmony_ci                    }
410cabdff1aSopenharmony_ci                }
411cabdff1aSopenharmony_ci            } else {
412cabdff1aSopenharmony_ci                int b = bytestream2_get_byte(gb);
413cabdff1aSopenharmony_ci                int off = ((b & 0x7F)) + 1;
414cabdff1aSopenharmony_ci                int len = ((b & 0x80) == 0) ? 2 : 3;
415cabdff1aSopenharmony_ci
416cabdff1aSopenharmony_ci                lz_copy(pb, g2, -off, len);
417cabdff1aSopenharmony_ci            }
418cabdff1aSopenharmony_ci        } else {
419cabdff1aSopenharmony_ci            int len;
420cabdff1aSopenharmony_ci            int off;
421cabdff1aSopenharmony_ci            if (use8) {
422cabdff1aSopenharmony_ci                int q, b = bytestream2_get_byte(gb);
423cabdff1aSopenharmony_ci                if ((b & 0xC0) == 0xC0) {
424cabdff1aSopenharmony_ci                    len = ((b & 0x3F)) + 8;
425cabdff1aSopenharmony_ci                    q = read_bits32(&bits, gb, 4);
426cabdff1aSopenharmony_ci                    off = (q << 8) + (bytestream2_get_byte(gb)) + 1;
427cabdff1aSopenharmony_ci                } else {
428cabdff1aSopenharmony_ci                    int ofs1;
429cabdff1aSopenharmony_ci                    if ((b & 0x80) == 0) {
430cabdff1aSopenharmony_ci                        len = ((b >> 4)) + 6;
431cabdff1aSopenharmony_ci                        ofs1 = (b & 0xF);
432cabdff1aSopenharmony_ci                    } else {
433cabdff1aSopenharmony_ci                        len = ((b & 0x3F)) + 14;
434cabdff1aSopenharmony_ci                        ofs1 = read_bits32(&bits, gb, 4);
435cabdff1aSopenharmony_ci                    }
436cabdff1aSopenharmony_ci                    off = (ofs1 << 8) + (bytestream2_get_byte(gb)) - 4096;
437cabdff1aSopenharmony_ci                }
438cabdff1aSopenharmony_ci            } else {
439cabdff1aSopenharmony_ci                int ofs1, b = bytestream2_get_byte(gb);
440cabdff1aSopenharmony_ci
441cabdff1aSopenharmony_ci                if ((b >> 4) == 0xF) {
442cabdff1aSopenharmony_ci                    len = bytestream2_get_byte(gb) + 21;
443cabdff1aSopenharmony_ci                } else {
444cabdff1aSopenharmony_ci                    len = (b >> 4) + 6;
445cabdff1aSopenharmony_ci                }
446cabdff1aSopenharmony_ci                ofs1 = (b & 0xF);
447cabdff1aSopenharmony_ci                off = (ofs1 << 8) + bytestream2_get_byte(gb) - 4096;
448cabdff1aSopenharmony_ci            }
449cabdff1aSopenharmony_ci            lz_copy(pb, g2, off, len);
450cabdff1aSopenharmony_ci        }
451cabdff1aSopenharmony_ci    }
452cabdff1aSopenharmony_ci
453cabdff1aSopenharmony_ci    if (bytestream2_get_bytes_left_p(pb) > 0)
454cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
455cabdff1aSopenharmony_ci
456cabdff1aSopenharmony_ci    return 0;
457cabdff1aSopenharmony_ci}
458cabdff1aSopenharmony_ci
459cabdff1aSopenharmony_cistatic int gdv_decode_frame(AVCodecContext *avctx, AVFrame *frame,
460cabdff1aSopenharmony_ci                            int *got_frame, AVPacket *avpkt)
461cabdff1aSopenharmony_ci{
462cabdff1aSopenharmony_ci    GDVContext *gdv = avctx->priv_data;
463cabdff1aSopenharmony_ci    GetByteContext *gb = &gdv->gb;
464cabdff1aSopenharmony_ci    PutByteContext *pb = &gdv->pb;
465cabdff1aSopenharmony_ci    int ret, i;
466cabdff1aSopenharmony_ci    int compression;
467cabdff1aSopenharmony_ci    unsigned flags;
468cabdff1aSopenharmony_ci    uint8_t *dst;
469cabdff1aSopenharmony_ci
470cabdff1aSopenharmony_ci    bytestream2_init(gb, avpkt->data, avpkt->size);
471cabdff1aSopenharmony_ci    bytestream2_init_writer(pb, gdv->frame, gdv->frame_size);
472cabdff1aSopenharmony_ci
473cabdff1aSopenharmony_ci    flags = bytestream2_get_le32(gb);
474cabdff1aSopenharmony_ci    compression = flags & 0xF;
475cabdff1aSopenharmony_ci
476cabdff1aSopenharmony_ci    if (compression == 4 || compression == 7 || compression > 8)
477cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
478cabdff1aSopenharmony_ci
479cabdff1aSopenharmony_ci    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
480cabdff1aSopenharmony_ci        return ret;
481cabdff1aSopenharmony_ci    ff_copy_palette(gdv->pal, avpkt, avctx);
482cabdff1aSopenharmony_ci
483cabdff1aSopenharmony_ci    if (compression < 2 && bytestream2_get_bytes_left(gb) < 256*3)
484cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
485cabdff1aSopenharmony_ci    rescale(gdv, gdv->frame, avctx->width, avctx->height,
486cabdff1aSopenharmony_ci            !!(flags & 0x10), !!(flags & 0x20));
487cabdff1aSopenharmony_ci
488cabdff1aSopenharmony_ci    switch (compression) {
489cabdff1aSopenharmony_ci    case 1:
490cabdff1aSopenharmony_ci        memset(gdv->frame + PREAMBLE_SIZE, 0, gdv->frame_size - PREAMBLE_SIZE);
491cabdff1aSopenharmony_ci    case 0:
492cabdff1aSopenharmony_ci        for (i = 0; i < 256; i++) {
493cabdff1aSopenharmony_ci            unsigned r = bytestream2_get_byte(gb);
494cabdff1aSopenharmony_ci            unsigned g = bytestream2_get_byte(gb);
495cabdff1aSopenharmony_ci            unsigned b = bytestream2_get_byte(gb);
496cabdff1aSopenharmony_ci            gdv->pal[i] = 0xFFU << 24 | r << 18 | g << 10 | b << 2;
497cabdff1aSopenharmony_ci        }
498cabdff1aSopenharmony_ci        break;
499cabdff1aSopenharmony_ci    case 2:
500cabdff1aSopenharmony_ci        ret = decompress_2(avctx);
501cabdff1aSopenharmony_ci        break;
502cabdff1aSopenharmony_ci    case 3:
503cabdff1aSopenharmony_ci        break;
504cabdff1aSopenharmony_ci    case 5:
505cabdff1aSopenharmony_ci        ret = decompress_5(avctx, flags >> 8);
506cabdff1aSopenharmony_ci        break;
507cabdff1aSopenharmony_ci    case 6:
508cabdff1aSopenharmony_ci        ret = decompress_68(avctx, flags >> 8, 0);
509cabdff1aSopenharmony_ci        break;
510cabdff1aSopenharmony_ci    case 8:
511cabdff1aSopenharmony_ci        ret = decompress_68(avctx, flags >> 8, 1);
512cabdff1aSopenharmony_ci        break;
513cabdff1aSopenharmony_ci    default:
514cabdff1aSopenharmony_ci        av_assert0(0);
515cabdff1aSopenharmony_ci    }
516cabdff1aSopenharmony_ci    if (ret < 0)
517cabdff1aSopenharmony_ci        return ret;
518cabdff1aSopenharmony_ci
519cabdff1aSopenharmony_ci    memcpy(frame->data[1], gdv->pal, AVPALETTE_SIZE);
520cabdff1aSopenharmony_ci    dst = frame->data[0];
521cabdff1aSopenharmony_ci
522cabdff1aSopenharmony_ci    if (!gdv->scale_v && !gdv->scale_h) {
523cabdff1aSopenharmony_ci        int sidx = PREAMBLE_SIZE, didx = 0;
524cabdff1aSopenharmony_ci        int y;
525cabdff1aSopenharmony_ci
526cabdff1aSopenharmony_ci        for (y = 0; y < avctx->height; y++) {
527cabdff1aSopenharmony_ci            memcpy(dst + didx, gdv->frame + sidx, avctx->width);
528cabdff1aSopenharmony_ci            sidx += avctx->width;
529cabdff1aSopenharmony_ci            didx += frame->linesize[0];
530cabdff1aSopenharmony_ci        }
531cabdff1aSopenharmony_ci    } else {
532cabdff1aSopenharmony_ci        int sidx = PREAMBLE_SIZE, didx = 0;
533cabdff1aSopenharmony_ci        int y;
534cabdff1aSopenharmony_ci
535cabdff1aSopenharmony_ci        for (y = 0; y < avctx->height; y++) {
536cabdff1aSopenharmony_ci            if (!gdv->scale_v) {
537cabdff1aSopenharmony_ci                memcpy(dst + didx, gdv->frame + sidx, avctx->width);
538cabdff1aSopenharmony_ci            } else {
539cabdff1aSopenharmony_ci                uint8_t *dst2 = dst + didx;
540cabdff1aSopenharmony_ci                uint8_t *src2 = gdv->frame + sidx;
541cabdff1aSopenharmony_ci
542cabdff1aSopenharmony_ci                scaleup(dst2, src2, avctx->width);
543cabdff1aSopenharmony_ci            }
544cabdff1aSopenharmony_ci            if (!gdv->scale_h || ((y & 1) == 1)) {
545cabdff1aSopenharmony_ci                sidx += !gdv->scale_v ? avctx->width : avctx->width/2;
546cabdff1aSopenharmony_ci            }
547cabdff1aSopenharmony_ci            didx += frame->linesize[0];
548cabdff1aSopenharmony_ci        }
549cabdff1aSopenharmony_ci    }
550cabdff1aSopenharmony_ci
551cabdff1aSopenharmony_ci    *got_frame = 1;
552cabdff1aSopenharmony_ci
553cabdff1aSopenharmony_ci    return avpkt->size;
554cabdff1aSopenharmony_ci}
555cabdff1aSopenharmony_ci
556cabdff1aSopenharmony_cistatic av_cold int gdv_decode_close(AVCodecContext *avctx)
557cabdff1aSopenharmony_ci{
558cabdff1aSopenharmony_ci    GDVContext *gdv = avctx->priv_data;
559cabdff1aSopenharmony_ci    av_freep(&gdv->frame);
560cabdff1aSopenharmony_ci    return 0;
561cabdff1aSopenharmony_ci}
562cabdff1aSopenharmony_ci
563cabdff1aSopenharmony_ciconst FFCodec ff_gdv_decoder = {
564cabdff1aSopenharmony_ci    .p.name         = "gdv",
565cabdff1aSopenharmony_ci    .p.long_name    = NULL_IF_CONFIG_SMALL("Gremlin Digital Video"),
566cabdff1aSopenharmony_ci    .p.type         = AVMEDIA_TYPE_VIDEO,
567cabdff1aSopenharmony_ci    .p.id           = AV_CODEC_ID_GDV,
568cabdff1aSopenharmony_ci    .priv_data_size = sizeof(GDVContext),
569cabdff1aSopenharmony_ci    .init           = gdv_decode_init,
570cabdff1aSopenharmony_ci    .close          = gdv_decode_close,
571cabdff1aSopenharmony_ci    FF_CODEC_DECODE_CB(gdv_decode_frame),
572cabdff1aSopenharmony_ci    .p.capabilities = AV_CODEC_CAP_DR1,
573cabdff1aSopenharmony_ci    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
574cabdff1aSopenharmony_ci};
575