1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * Argonaut Games Video decoder
3cabdff1aSopenharmony_ci * Copyright (c) 2020 Paul B Mahol
4cabdff1aSopenharmony_ci *
5cabdff1aSopenharmony_ci * This file is part of FFmpeg.
6cabdff1aSopenharmony_ci *
7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
11cabdff1aSopenharmony_ci *
12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15cabdff1aSopenharmony_ci * Lesser General Public License for more details.
16cabdff1aSopenharmony_ci *
17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20cabdff1aSopenharmony_ci */
21cabdff1aSopenharmony_ci
22cabdff1aSopenharmony_ci#include <stdio.h>
23cabdff1aSopenharmony_ci#include <stdlib.h>
24cabdff1aSopenharmony_ci#include <string.h>
25cabdff1aSopenharmony_ci
26cabdff1aSopenharmony_ci#include "libavutil/imgutils.h"
27cabdff1aSopenharmony_ci#include "libavutil/internal.h"
28cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h"
29cabdff1aSopenharmony_ci
30cabdff1aSopenharmony_ci#include "avcodec.h"
31cabdff1aSopenharmony_ci#include "bytestream.h"
32cabdff1aSopenharmony_ci#include "codec_internal.h"
33cabdff1aSopenharmony_ci#include "internal.h"
34cabdff1aSopenharmony_ci
35cabdff1aSopenharmony_citypedef struct ArgoContext {
36cabdff1aSopenharmony_ci    GetByteContext gb;
37cabdff1aSopenharmony_ci
38cabdff1aSopenharmony_ci    int bpp;
39cabdff1aSopenharmony_ci    int key;
40cabdff1aSopenharmony_ci    int mv0[128][2];
41cabdff1aSopenharmony_ci    int mv1[16][2];
42cabdff1aSopenharmony_ci    uint32_t pal[256];
43cabdff1aSopenharmony_ci    AVFrame *frame;
44cabdff1aSopenharmony_ci} ArgoContext;
45cabdff1aSopenharmony_ci
46cabdff1aSopenharmony_cistatic int decode_pal8(AVCodecContext *avctx, uint32_t *pal)
47cabdff1aSopenharmony_ci{
48cabdff1aSopenharmony_ci    ArgoContext *s = avctx->priv_data;
49cabdff1aSopenharmony_ci    GetByteContext *gb = &s->gb;
50cabdff1aSopenharmony_ci    int start, count;
51cabdff1aSopenharmony_ci
52cabdff1aSopenharmony_ci    start = bytestream2_get_le16(gb);
53cabdff1aSopenharmony_ci    count = bytestream2_get_le16(gb);
54cabdff1aSopenharmony_ci
55cabdff1aSopenharmony_ci    if (start + count > 256)
56cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
57cabdff1aSopenharmony_ci
58cabdff1aSopenharmony_ci    if (bytestream2_get_bytes_left(gb) < 3 * count)
59cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
60cabdff1aSopenharmony_ci
61cabdff1aSopenharmony_ci    for (int i = 0; i < count; i++)
62cabdff1aSopenharmony_ci        pal[start + i] = (0xFFU << 24) | bytestream2_get_be24u(gb);
63cabdff1aSopenharmony_ci
64cabdff1aSopenharmony_ci    return 0;
65cabdff1aSopenharmony_ci}
66cabdff1aSopenharmony_ci
67cabdff1aSopenharmony_cistatic int decode_avcf(AVCodecContext *avctx, AVFrame *frame)
68cabdff1aSopenharmony_ci{
69cabdff1aSopenharmony_ci    ArgoContext *s = avctx->priv_data;
70cabdff1aSopenharmony_ci    GetByteContext *gb = &s->gb;
71cabdff1aSopenharmony_ci    const int l = frame->linesize[0];
72cabdff1aSopenharmony_ci    const uint8_t *map = gb->buffer;
73cabdff1aSopenharmony_ci    uint8_t *dst = frame->data[0];
74cabdff1aSopenharmony_ci
75cabdff1aSopenharmony_ci    if (bytestream2_get_bytes_left(gb) < 1024 + (frame->width / 2) * (frame->height / 2))
76cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
77cabdff1aSopenharmony_ci
78cabdff1aSopenharmony_ci    bytestream2_skipu(gb, 1024);
79cabdff1aSopenharmony_ci    for (int y = 0; y < frame->height; y += 2) {
80cabdff1aSopenharmony_ci        for (int x = 0; x < frame->width; x += 2) {
81cabdff1aSopenharmony_ci            int index = bytestream2_get_byteu(gb);
82cabdff1aSopenharmony_ci            const uint8_t *block = map + index * 4;
83cabdff1aSopenharmony_ci
84cabdff1aSopenharmony_ci            dst[x+0]   = block[0];
85cabdff1aSopenharmony_ci            dst[x+1]   = block[1];
86cabdff1aSopenharmony_ci            dst[x+l]   = block[2];
87cabdff1aSopenharmony_ci            dst[x+l+1] = block[3];
88cabdff1aSopenharmony_ci        }
89cabdff1aSopenharmony_ci
90cabdff1aSopenharmony_ci        dst += frame->linesize[0] * 2;
91cabdff1aSopenharmony_ci    }
92cabdff1aSopenharmony_ci
93cabdff1aSopenharmony_ci    return 0;
94cabdff1aSopenharmony_ci}
95cabdff1aSopenharmony_ci
96cabdff1aSopenharmony_cistatic int decode_alcd(AVCodecContext *avctx, AVFrame *frame)
97cabdff1aSopenharmony_ci{
98cabdff1aSopenharmony_ci    ArgoContext *s = avctx->priv_data;
99cabdff1aSopenharmony_ci    GetByteContext *gb = &s->gb;
100cabdff1aSopenharmony_ci    GetByteContext sb;
101cabdff1aSopenharmony_ci    const int l = frame->linesize[0];
102cabdff1aSopenharmony_ci    const uint8_t *map = gb->buffer;
103cabdff1aSopenharmony_ci    uint8_t *dst = frame->data[0];
104cabdff1aSopenharmony_ci    uint8_t codes = 0;
105cabdff1aSopenharmony_ci    int count = 0;
106cabdff1aSopenharmony_ci
107cabdff1aSopenharmony_ci    if (bytestream2_get_bytes_left(gb) < 1024 + (((frame->width / 2) * (frame->height / 2) + 7) >> 3))
108cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
109cabdff1aSopenharmony_ci
110cabdff1aSopenharmony_ci    bytestream2_skipu(gb, 1024);
111cabdff1aSopenharmony_ci    sb = *gb;
112cabdff1aSopenharmony_ci    bytestream2_skipu(gb, ((frame->width / 2) * (frame->height / 2) + 7) >> 3);
113cabdff1aSopenharmony_ci
114cabdff1aSopenharmony_ci    for (int y = 0; y < frame->height; y += 2) {
115cabdff1aSopenharmony_ci        for (int x = 0; x < frame->width; x += 2) {
116cabdff1aSopenharmony_ci            const uint8_t *block;
117cabdff1aSopenharmony_ci            int index;
118cabdff1aSopenharmony_ci
119cabdff1aSopenharmony_ci            if (count == 0) {
120cabdff1aSopenharmony_ci                codes = bytestream2_get_byteu(&sb);
121cabdff1aSopenharmony_ci                count = 8;
122cabdff1aSopenharmony_ci            }
123cabdff1aSopenharmony_ci
124cabdff1aSopenharmony_ci            if (codes & 0x80) {
125cabdff1aSopenharmony_ci                index = bytestream2_get_byte(gb);
126cabdff1aSopenharmony_ci                block = map + index * 4;
127cabdff1aSopenharmony_ci
128cabdff1aSopenharmony_ci                dst[x+0]   = block[0];
129cabdff1aSopenharmony_ci                dst[x+1]   = block[1];
130cabdff1aSopenharmony_ci                dst[x+l]   = block[2];
131cabdff1aSopenharmony_ci                dst[x+l+1] = block[3];
132cabdff1aSopenharmony_ci            }
133cabdff1aSopenharmony_ci
134cabdff1aSopenharmony_ci            codes <<= 1;
135cabdff1aSopenharmony_ci            count--;
136cabdff1aSopenharmony_ci        }
137cabdff1aSopenharmony_ci
138cabdff1aSopenharmony_ci        dst += frame->linesize[0] * 2;
139cabdff1aSopenharmony_ci    }
140cabdff1aSopenharmony_ci
141cabdff1aSopenharmony_ci    return 0;
142cabdff1aSopenharmony_ci}
143cabdff1aSopenharmony_ci
144cabdff1aSopenharmony_cistatic int decode_mad1(AVCodecContext *avctx, AVFrame *frame)
145cabdff1aSopenharmony_ci{
146cabdff1aSopenharmony_ci    ArgoContext *s = avctx->priv_data;
147cabdff1aSopenharmony_ci    GetByteContext *gb = &s->gb;
148cabdff1aSopenharmony_ci    const int w = frame->width;
149cabdff1aSopenharmony_ci    const int h = frame->height;
150cabdff1aSopenharmony_ci    const int l = frame->linesize[0];
151cabdff1aSopenharmony_ci
152cabdff1aSopenharmony_ci    while (bytestream2_get_bytes_left(gb) > 0) {
153cabdff1aSopenharmony_ci        int size, type, pos, dy;
154cabdff1aSopenharmony_ci        uint8_t *dst;
155cabdff1aSopenharmony_ci
156cabdff1aSopenharmony_ci        type = bytestream2_get_byte(gb);
157cabdff1aSopenharmony_ci        if (type == 0xFF)
158cabdff1aSopenharmony_ci            break;
159cabdff1aSopenharmony_ci
160cabdff1aSopenharmony_ci        switch (type) {
161cabdff1aSopenharmony_ci        case 8:
162cabdff1aSopenharmony_ci            dst = frame->data[0];
163cabdff1aSopenharmony_ci            for (int y = 0; y < h; y += 8) {
164cabdff1aSopenharmony_ci                for (int x = 0; x < w; x += 8) {
165cabdff1aSopenharmony_ci                    int fill = bytestream2_get_byte(gb);
166cabdff1aSopenharmony_ci                    uint8_t *ddst = dst + x;
167cabdff1aSopenharmony_ci
168cabdff1aSopenharmony_ci                    for (int by = 0; by < 8; by++) {
169cabdff1aSopenharmony_ci                        memset(ddst, fill, 8);
170cabdff1aSopenharmony_ci                        ddst += l;
171cabdff1aSopenharmony_ci                    }
172cabdff1aSopenharmony_ci                }
173cabdff1aSopenharmony_ci
174cabdff1aSopenharmony_ci                dst += 8 * l;
175cabdff1aSopenharmony_ci            }
176cabdff1aSopenharmony_ci            break;
177cabdff1aSopenharmony_ci        case 7:
178cabdff1aSopenharmony_ci            while (bytestream2_get_bytes_left(gb) > 0) {
179cabdff1aSopenharmony_ci                int bsize = bytestream2_get_byte(gb);
180cabdff1aSopenharmony_ci                uint8_t *src;
181cabdff1aSopenharmony_ci                int count;
182cabdff1aSopenharmony_ci
183cabdff1aSopenharmony_ci                if (!bsize)
184cabdff1aSopenharmony_ci                    break;
185cabdff1aSopenharmony_ci
186cabdff1aSopenharmony_ci                count = bytestream2_get_be16(gb);
187cabdff1aSopenharmony_ci                while (count > 0) {
188cabdff1aSopenharmony_ci                    int mvx, mvy, a, b, c, mx, my;
189cabdff1aSopenharmony_ci                    int bsize_w, bsize_h;
190cabdff1aSopenharmony_ci
191cabdff1aSopenharmony_ci                    bsize_w = bsize_h = bsize;
192cabdff1aSopenharmony_ci                    if (bytestream2_get_bytes_left(gb) < 4)
193cabdff1aSopenharmony_ci                        return AVERROR_INVALIDDATA;
194cabdff1aSopenharmony_ci                    mvx = bytestream2_get_byte(gb) * bsize;
195cabdff1aSopenharmony_ci                    mvy = bytestream2_get_byte(gb) * bsize;
196cabdff1aSopenharmony_ci                    a = bytestream2_get_byte(gb);
197cabdff1aSopenharmony_ci                    b = bytestream2_get_byte(gb);
198cabdff1aSopenharmony_ci                    c = ((a & 0x3F) << 8) + b;
199cabdff1aSopenharmony_ci                    mx = mvx + (c  & 0x7F) - 64;
200cabdff1aSopenharmony_ci                    my = mvy + (c >>    7) - 64;
201cabdff1aSopenharmony_ci
202cabdff1aSopenharmony_ci                    if (mvy < 0 || mvy >= h)
203cabdff1aSopenharmony_ci                        return AVERROR_INVALIDDATA;
204cabdff1aSopenharmony_ci
205cabdff1aSopenharmony_ci                    if (mvx < 0 || mvx >= w)
206cabdff1aSopenharmony_ci                        return AVERROR_INVALIDDATA;
207cabdff1aSopenharmony_ci
208cabdff1aSopenharmony_ci                    if (my < 0 || my >= h)
209cabdff1aSopenharmony_ci                        return AVERROR_INVALIDDATA;
210cabdff1aSopenharmony_ci
211cabdff1aSopenharmony_ci                    if (mx < 0 || mx >= w)
212cabdff1aSopenharmony_ci                        return AVERROR_INVALIDDATA;
213cabdff1aSopenharmony_ci
214cabdff1aSopenharmony_ci                    dst = frame->data[0] + mvx + l * mvy;
215cabdff1aSopenharmony_ci                    src = frame->data[0] + mx  + l * my;
216cabdff1aSopenharmony_ci
217cabdff1aSopenharmony_ci                    bsize_w = FFMIN3(bsize_w, w - mvx, w - mx);
218cabdff1aSopenharmony_ci                    bsize_h = FFMIN3(bsize_h, h - mvy, h - my);
219cabdff1aSopenharmony_ci
220cabdff1aSopenharmony_ci                    if (mvy >= my && (mvy != my || mvx >= mx)) {
221cabdff1aSopenharmony_ci                        src += (bsize_h - 1) * l;
222cabdff1aSopenharmony_ci                        dst += (bsize_h - 1) * l;
223cabdff1aSopenharmony_ci                        for (int by = 0; by < bsize_h; by++) {
224cabdff1aSopenharmony_ci                            memmove(dst, src, bsize_w);
225cabdff1aSopenharmony_ci                            src -= l;
226cabdff1aSopenharmony_ci                            dst -= l;
227cabdff1aSopenharmony_ci                        }
228cabdff1aSopenharmony_ci                    } else {
229cabdff1aSopenharmony_ci                        for (int by = 0; by < bsize_h; by++) {
230cabdff1aSopenharmony_ci                            memmove(dst, src, bsize_w);
231cabdff1aSopenharmony_ci                            src += l;
232cabdff1aSopenharmony_ci                            dst += l;
233cabdff1aSopenharmony_ci                        }
234cabdff1aSopenharmony_ci                    }
235cabdff1aSopenharmony_ci
236cabdff1aSopenharmony_ci                    count--;
237cabdff1aSopenharmony_ci                }
238cabdff1aSopenharmony_ci            }
239cabdff1aSopenharmony_ci            break;
240cabdff1aSopenharmony_ci        case 6:
241cabdff1aSopenharmony_ci            dst = frame->data[0];
242cabdff1aSopenharmony_ci            if (bytestream2_get_bytes_left(gb) < w * h)
243cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
244cabdff1aSopenharmony_ci            for (int y = 0; y < h; y++) {
245cabdff1aSopenharmony_ci                bytestream2_get_bufferu(gb, dst, w);
246cabdff1aSopenharmony_ci                dst += l;
247cabdff1aSopenharmony_ci            }
248cabdff1aSopenharmony_ci            break;
249cabdff1aSopenharmony_ci        case 5:
250cabdff1aSopenharmony_ci            dst = frame->data[0];
251cabdff1aSopenharmony_ci            for (int y = 0; y < h; y += 2) {
252cabdff1aSopenharmony_ci                for (int x = 0; x < w; x += 2) {
253cabdff1aSopenharmony_ci                    int fill = bytestream2_get_byte(gb);
254cabdff1aSopenharmony_ci                    uint8_t *ddst = dst + x;
255cabdff1aSopenharmony_ci
256cabdff1aSopenharmony_ci                    fill = (fill << 8) | fill;
257cabdff1aSopenharmony_ci                    for (int by = 0; by < 2; by++) {
258cabdff1aSopenharmony_ci                            AV_WN16(ddst, fill);
259cabdff1aSopenharmony_ci
260cabdff1aSopenharmony_ci                        ddst += l;
261cabdff1aSopenharmony_ci                    }
262cabdff1aSopenharmony_ci                }
263cabdff1aSopenharmony_ci
264cabdff1aSopenharmony_ci                dst += 2 * l;
265cabdff1aSopenharmony_ci            }
266cabdff1aSopenharmony_ci            break;
267cabdff1aSopenharmony_ci        case 3:
268cabdff1aSopenharmony_ci            size = bytestream2_get_le16(gb);
269cabdff1aSopenharmony_ci            if (size > 0) {
270cabdff1aSopenharmony_ci                int x = bytestream2_get_byte(gb) * 4;
271cabdff1aSopenharmony_ci                int y = bytestream2_get_byte(gb) * 4;
272cabdff1aSopenharmony_ci                int count = bytestream2_get_byte(gb);
273cabdff1aSopenharmony_ci                int fill = bytestream2_get_byte(gb);
274cabdff1aSopenharmony_ci
275cabdff1aSopenharmony_ci                av_log(avctx, AV_LOG_DEBUG, "%d %d %d %d\n", x, y, count, fill);
276cabdff1aSopenharmony_ci                for (int i = 0; i < count; i++)
277cabdff1aSopenharmony_ci                    ;
278cabdff1aSopenharmony_ci                return AVERROR_PATCHWELCOME;
279cabdff1aSopenharmony_ci            }
280cabdff1aSopenharmony_ci            break;
281cabdff1aSopenharmony_ci        case 2:
282cabdff1aSopenharmony_ci            dst = frame->data[0];
283cabdff1aSopenharmony_ci            pos = 0;
284cabdff1aSopenharmony_ci            dy  = 0;
285cabdff1aSopenharmony_ci            while (bytestream2_get_bytes_left(gb) > 0) {
286cabdff1aSopenharmony_ci                int count = bytestream2_get_byteu(gb);
287cabdff1aSopenharmony_ci                int skip = count & 0x3F;
288cabdff1aSopenharmony_ci
289cabdff1aSopenharmony_ci                count = count >> 6;
290cabdff1aSopenharmony_ci                if (skip == 0x3F) {
291cabdff1aSopenharmony_ci                    pos += 0x3E;
292cabdff1aSopenharmony_ci                    while (pos >= w) {
293cabdff1aSopenharmony_ci                        pos -= w;
294cabdff1aSopenharmony_ci                        dst += l;
295cabdff1aSopenharmony_ci                        dy++;
296cabdff1aSopenharmony_ci                        if (dy >= h)
297cabdff1aSopenharmony_ci                            return 0;
298cabdff1aSopenharmony_ci                    }
299cabdff1aSopenharmony_ci                } else {
300cabdff1aSopenharmony_ci                    pos += skip;
301cabdff1aSopenharmony_ci                    while (pos >= w) {
302cabdff1aSopenharmony_ci                        pos -= w;
303cabdff1aSopenharmony_ci                        dst += l;
304cabdff1aSopenharmony_ci                        dy++;
305cabdff1aSopenharmony_ci                        if (dy >= h)
306cabdff1aSopenharmony_ci                            return 0;
307cabdff1aSopenharmony_ci                    }
308cabdff1aSopenharmony_ci                    while (count >= 0) {
309cabdff1aSopenharmony_ci                        int bits = bytestream2_get_byte(gb);
310cabdff1aSopenharmony_ci
311cabdff1aSopenharmony_ci                        for (int i = 0; i < 4; i++) {
312cabdff1aSopenharmony_ci                            switch (bits & 3) {
313cabdff1aSopenharmony_ci                            case 0:
314cabdff1aSopenharmony_ci                                break;
315cabdff1aSopenharmony_ci                            case 1:
316cabdff1aSopenharmony_ci                                if (dy < 1 && !pos)
317cabdff1aSopenharmony_ci                                    return AVERROR_INVALIDDATA;
318cabdff1aSopenharmony_ci                                else
319cabdff1aSopenharmony_ci                                    dst[pos] = pos ? dst[pos - 1] : dst[-l + w - 1];
320cabdff1aSopenharmony_ci                                break;
321cabdff1aSopenharmony_ci                            case 2:
322cabdff1aSopenharmony_ci                                if (dy < 1)
323cabdff1aSopenharmony_ci                                    return AVERROR_INVALIDDATA;
324cabdff1aSopenharmony_ci                                dst[pos] = dst[pos - l];
325cabdff1aSopenharmony_ci                                break;
326cabdff1aSopenharmony_ci                            case 3:
327cabdff1aSopenharmony_ci                                dst[pos] = bytestream2_get_byte(gb);
328cabdff1aSopenharmony_ci                                break;
329cabdff1aSopenharmony_ci                            }
330cabdff1aSopenharmony_ci
331cabdff1aSopenharmony_ci                            pos++;
332cabdff1aSopenharmony_ci                            if (pos >= w) {
333cabdff1aSopenharmony_ci                                pos -= w;
334cabdff1aSopenharmony_ci                                dst += l;
335cabdff1aSopenharmony_ci                                dy++;
336cabdff1aSopenharmony_ci                                if (dy >= h)
337cabdff1aSopenharmony_ci                                    return 0;
338cabdff1aSopenharmony_ci                            }
339cabdff1aSopenharmony_ci                            bits >>= 2;
340cabdff1aSopenharmony_ci                        }
341cabdff1aSopenharmony_ci                        count--;
342cabdff1aSopenharmony_ci                    }
343cabdff1aSopenharmony_ci                }
344cabdff1aSopenharmony_ci            }
345cabdff1aSopenharmony_ci            break;
346cabdff1aSopenharmony_ci        default:
347cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
348cabdff1aSopenharmony_ci        }
349cabdff1aSopenharmony_ci    }
350cabdff1aSopenharmony_ci
351cabdff1aSopenharmony_ci    return 0;
352cabdff1aSopenharmony_ci}
353cabdff1aSopenharmony_ci
354cabdff1aSopenharmony_cistatic int decode_mad1_24(AVCodecContext *avctx, AVFrame *frame)
355cabdff1aSopenharmony_ci{
356cabdff1aSopenharmony_ci    ArgoContext *s = avctx->priv_data;
357cabdff1aSopenharmony_ci    GetByteContext *gb = &s->gb;
358cabdff1aSopenharmony_ci    const int w = frame->width;
359cabdff1aSopenharmony_ci    const int h = frame->height;
360cabdff1aSopenharmony_ci    const int l = frame->linesize[0] / 4;
361cabdff1aSopenharmony_ci
362cabdff1aSopenharmony_ci    while (bytestream2_get_bytes_left(gb) > 0) {
363cabdff1aSopenharmony_ci        int osize, type, pos, dy, di, bcode, value, v14;
364cabdff1aSopenharmony_ci        const uint8_t *bits;
365cabdff1aSopenharmony_ci        uint32_t *dst;
366cabdff1aSopenharmony_ci
367cabdff1aSopenharmony_ci        type = bytestream2_get_byte(gb);
368cabdff1aSopenharmony_ci        if (type == 0xFF)
369cabdff1aSopenharmony_ci            return 0;
370cabdff1aSopenharmony_ci
371cabdff1aSopenharmony_ci        switch (type) {
372cabdff1aSopenharmony_ci        case 8:
373cabdff1aSopenharmony_ci            dst = (uint32_t *)frame->data[0];
374cabdff1aSopenharmony_ci            for (int y = 0; y + 12 <= h; y += 12) {
375cabdff1aSopenharmony_ci                for (int x = 0; x + 12 <= w; x += 12) {
376cabdff1aSopenharmony_ci                    int fill = bytestream2_get_be24(gb);
377cabdff1aSopenharmony_ci                    uint32_t *dstp = dst + x;
378cabdff1aSopenharmony_ci
379cabdff1aSopenharmony_ci                    for (int by = 0; by < 12; by++) {
380cabdff1aSopenharmony_ci                        for (int bx = 0; bx < 12; bx++)
381cabdff1aSopenharmony_ci                            dstp[bx] = fill;
382cabdff1aSopenharmony_ci
383cabdff1aSopenharmony_ci                        dstp += l;
384cabdff1aSopenharmony_ci                    }
385cabdff1aSopenharmony_ci                }
386cabdff1aSopenharmony_ci
387cabdff1aSopenharmony_ci                dst += 12 * l;
388cabdff1aSopenharmony_ci            }
389cabdff1aSopenharmony_ci            break;
390cabdff1aSopenharmony_ci        case 7:
391cabdff1aSopenharmony_ci            while (bytestream2_get_bytes_left(gb) > 0) {
392cabdff1aSopenharmony_ci                int bsize = bytestream2_get_byte(gb);
393cabdff1aSopenharmony_ci                uint32_t *src;
394cabdff1aSopenharmony_ci                int count;
395cabdff1aSopenharmony_ci
396cabdff1aSopenharmony_ci                if (!bsize)
397cabdff1aSopenharmony_ci                    break;
398cabdff1aSopenharmony_ci
399cabdff1aSopenharmony_ci                count = bytestream2_get_be16(gb);
400cabdff1aSopenharmony_ci                while (count > 0) {
401cabdff1aSopenharmony_ci                    int mvx, mvy, a, b, c, mx, my;
402cabdff1aSopenharmony_ci                    int bsize_w, bsize_h;
403cabdff1aSopenharmony_ci
404cabdff1aSopenharmony_ci                    bsize_w = bsize_h = bsize;
405cabdff1aSopenharmony_ci                    if (bytestream2_get_bytes_left(gb) < 4)
406cabdff1aSopenharmony_ci                        return AVERROR_INVALIDDATA;
407cabdff1aSopenharmony_ci                    mvx = bytestream2_get_byte(gb) * bsize;
408cabdff1aSopenharmony_ci                    mvy = bytestream2_get_byte(gb) * bsize;
409cabdff1aSopenharmony_ci                    a = bytestream2_get_byte(gb);
410cabdff1aSopenharmony_ci                    b = bytestream2_get_byte(gb);
411cabdff1aSopenharmony_ci                    c = ((a & 0x3F) << 8) + b;
412cabdff1aSopenharmony_ci                    mx = mvx + (c  & 0x7F) - 64;
413cabdff1aSopenharmony_ci                    my = mvy + (c >>    7) - 64;
414cabdff1aSopenharmony_ci
415cabdff1aSopenharmony_ci                    if (mvy < 0 || mvy >= h)
416cabdff1aSopenharmony_ci                        return AVERROR_INVALIDDATA;
417cabdff1aSopenharmony_ci
418cabdff1aSopenharmony_ci                    if (mvx < 0 || mvx >= w)
419cabdff1aSopenharmony_ci                        return AVERROR_INVALIDDATA;
420cabdff1aSopenharmony_ci
421cabdff1aSopenharmony_ci                    if (my < 0 || my >= h)
422cabdff1aSopenharmony_ci                        return AVERROR_INVALIDDATA;
423cabdff1aSopenharmony_ci
424cabdff1aSopenharmony_ci                    if (mx < 0 || mx >= w)
425cabdff1aSopenharmony_ci                        return AVERROR_INVALIDDATA;
426cabdff1aSopenharmony_ci
427cabdff1aSopenharmony_ci                    dst = (uint32_t *)frame->data[0] + mvx + l * mvy;
428cabdff1aSopenharmony_ci                    src = (uint32_t *)frame->data[0] + mx  + l * my;
429cabdff1aSopenharmony_ci
430cabdff1aSopenharmony_ci                    bsize_w = FFMIN3(bsize_w, w - mvx, w - mx);
431cabdff1aSopenharmony_ci                    bsize_h = FFMIN3(bsize_h, h - mvy, h - my);
432cabdff1aSopenharmony_ci
433cabdff1aSopenharmony_ci                    if (mvy >= my && (mvy != my || mvx >= mx)) {
434cabdff1aSopenharmony_ci                        src += (bsize_h - 1) * l;
435cabdff1aSopenharmony_ci                        dst += (bsize_h - 1) * l;
436cabdff1aSopenharmony_ci                        for (int by = 0; by < bsize_h; by++) {
437cabdff1aSopenharmony_ci                            memmove(dst, src, bsize_w * 4);
438cabdff1aSopenharmony_ci                            src -= l;
439cabdff1aSopenharmony_ci                            dst -= l;
440cabdff1aSopenharmony_ci                        }
441cabdff1aSopenharmony_ci                    } else {
442cabdff1aSopenharmony_ci                        for (int by = 0; by < bsize_h; by++) {
443cabdff1aSopenharmony_ci                            memmove(dst, src, bsize_w * 4);
444cabdff1aSopenharmony_ci                            src += l;
445cabdff1aSopenharmony_ci                            dst += l;
446cabdff1aSopenharmony_ci                        }
447cabdff1aSopenharmony_ci                    }
448cabdff1aSopenharmony_ci
449cabdff1aSopenharmony_ci                    count--;
450cabdff1aSopenharmony_ci                }
451cabdff1aSopenharmony_ci            }
452cabdff1aSopenharmony_ci            break;
453cabdff1aSopenharmony_ci        case 12:
454cabdff1aSopenharmony_ci            osize = ((h + 3) / 4) * ((w + 3) / 4) + 7;
455cabdff1aSopenharmony_ci            bits = gb->buffer;
456cabdff1aSopenharmony_ci            di   = 0;
457cabdff1aSopenharmony_ci            bcode = v14 = 0;
458cabdff1aSopenharmony_ci            if (bytestream2_get_bytes_left(gb) < osize >> 3)
459cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
460cabdff1aSopenharmony_ci            bytestream2_skip(gb, osize >> 3);
461cabdff1aSopenharmony_ci            for (int x = 0; x < w; x += 4) {
462cabdff1aSopenharmony_ci                for (int y = 0; y < h; y += 4) {
463cabdff1aSopenharmony_ci                    int astate = 0;
464cabdff1aSopenharmony_ci
465cabdff1aSopenharmony_ci                    if (bits[di >> 3] & (1 << (di & 7))) {
466cabdff1aSopenharmony_ci                        int codes = bytestream2_get_byte(gb);
467cabdff1aSopenharmony_ci
468cabdff1aSopenharmony_ci                        for (int count = 0; count < 4; count++) {
469cabdff1aSopenharmony_ci                            uint32_t *src = (uint32_t *)frame->data[0];
470cabdff1aSopenharmony_ci                            size_t src_size = l * (h - 1) + (w - 1);
471cabdff1aSopenharmony_ci                            int nv, v, code = codes & 3;
472cabdff1aSopenharmony_ci
473cabdff1aSopenharmony_ci                            pos = x;
474cabdff1aSopenharmony_ci                            dy  = y + count;
475cabdff1aSopenharmony_ci                            dst = (uint32_t *)frame->data[0] + pos + dy * l;
476cabdff1aSopenharmony_ci                            if (code & 1)
477cabdff1aSopenharmony_ci                                bcode = bytestream2_get_byte(gb);
478cabdff1aSopenharmony_ci                            if (code == 3) {
479cabdff1aSopenharmony_ci                                for (int j = 0; j < 4; j++) {
480cabdff1aSopenharmony_ci                                    switch (bcode & 3) {
481cabdff1aSopenharmony_ci                                    case 0:
482cabdff1aSopenharmony_ci                                        break;
483cabdff1aSopenharmony_ci                                    case 1:
484cabdff1aSopenharmony_ci                                        if (dy < 1 && !pos)
485cabdff1aSopenharmony_ci                                            return AVERROR_INVALIDDATA;
486cabdff1aSopenharmony_ci                                        dst[0] = dst[-1];
487cabdff1aSopenharmony_ci                                        break;
488cabdff1aSopenharmony_ci                                    case 2:
489cabdff1aSopenharmony_ci                                        if (dy < 1)
490cabdff1aSopenharmony_ci                                            return AVERROR_INVALIDDATA;
491cabdff1aSopenharmony_ci                                        dst[0] = dst[-l];
492cabdff1aSopenharmony_ci                                        break;
493cabdff1aSopenharmony_ci                                    case 3:
494cabdff1aSopenharmony_ci                                        if (astate) {
495cabdff1aSopenharmony_ci                                            nv = value >> 4;
496cabdff1aSopenharmony_ci                                        } else {
497cabdff1aSopenharmony_ci                                            value = bytestream2_get_byte(gb);
498cabdff1aSopenharmony_ci                                            nv = value & 0xF;
499cabdff1aSopenharmony_ci                                        }
500cabdff1aSopenharmony_ci                                        astate ^= 1;
501cabdff1aSopenharmony_ci                                        dst[0] = src[av_clip(l * (dy + s->mv1[nv][1]) + pos +
502cabdff1aSopenharmony_ci                                                             s->mv1[nv][0], 0, src_size)];
503cabdff1aSopenharmony_ci                                        break;
504cabdff1aSopenharmony_ci                                    }
505cabdff1aSopenharmony_ci
506cabdff1aSopenharmony_ci                                    bcode >>= 2;
507cabdff1aSopenharmony_ci                                    dst++;
508cabdff1aSopenharmony_ci                                    pos++;
509cabdff1aSopenharmony_ci                                }
510cabdff1aSopenharmony_ci                            } else if (code) {
511cabdff1aSopenharmony_ci                                if (code == 1)
512cabdff1aSopenharmony_ci                                    v14 = bcode;
513cabdff1aSopenharmony_ci                                else
514cabdff1aSopenharmony_ci                                    bcode = v14;
515cabdff1aSopenharmony_ci                                for (int j = 0; j < 4; j++) {
516cabdff1aSopenharmony_ci                                    switch (bcode & 3) {
517cabdff1aSopenharmony_ci                                    case 0:
518cabdff1aSopenharmony_ci                                        break;
519cabdff1aSopenharmony_ci                                    case 1:
520cabdff1aSopenharmony_ci                                        if (dy < 1 && !pos)
521cabdff1aSopenharmony_ci                                            return AVERROR_INVALIDDATA;
522cabdff1aSopenharmony_ci                                        dst[0] = dst[-1];
523cabdff1aSopenharmony_ci                                        break;
524cabdff1aSopenharmony_ci                                    case 2:
525cabdff1aSopenharmony_ci                                        if (dy < 1)
526cabdff1aSopenharmony_ci                                            return AVERROR_INVALIDDATA;
527cabdff1aSopenharmony_ci                                        dst[0] = dst[-l];
528cabdff1aSopenharmony_ci                                        break;
529cabdff1aSopenharmony_ci                                    case 3:
530cabdff1aSopenharmony_ci                                        v = bytestream2_get_byte(gb);
531cabdff1aSopenharmony_ci                                        if (v < 128) {
532cabdff1aSopenharmony_ci                                            dst[0] = src[av_clip(l * (dy + s->mv0[v][1]) + pos +
533cabdff1aSopenharmony_ci                                                                 s->mv0[v][0], 0, src_size)];
534cabdff1aSopenharmony_ci                                        } else {
535cabdff1aSopenharmony_ci                                            dst[0] = ((v & 0x7F) << 17) | bytestream2_get_be16(gb);
536cabdff1aSopenharmony_ci                                        }
537cabdff1aSopenharmony_ci                                        break;
538cabdff1aSopenharmony_ci                                    }
539cabdff1aSopenharmony_ci
540cabdff1aSopenharmony_ci                                    bcode >>= 2;
541cabdff1aSopenharmony_ci                                    dst++;
542cabdff1aSopenharmony_ci                                    pos++;
543cabdff1aSopenharmony_ci                                }
544cabdff1aSopenharmony_ci                            }
545cabdff1aSopenharmony_ci
546cabdff1aSopenharmony_ci                            codes >>= 2;
547cabdff1aSopenharmony_ci                        }
548cabdff1aSopenharmony_ci                    }
549cabdff1aSopenharmony_ci
550cabdff1aSopenharmony_ci                    di++;
551cabdff1aSopenharmony_ci                }
552cabdff1aSopenharmony_ci            }
553cabdff1aSopenharmony_ci            break;
554cabdff1aSopenharmony_ci        default:
555cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
556cabdff1aSopenharmony_ci        }
557cabdff1aSopenharmony_ci    }
558cabdff1aSopenharmony_ci
559cabdff1aSopenharmony_ci    return AVERROR_INVALIDDATA;
560cabdff1aSopenharmony_ci}
561cabdff1aSopenharmony_ci
562cabdff1aSopenharmony_cistatic int decode_rle(AVCodecContext *avctx, AVFrame *frame)
563cabdff1aSopenharmony_ci{
564cabdff1aSopenharmony_ci    ArgoContext *s = avctx->priv_data;
565cabdff1aSopenharmony_ci    GetByteContext *gb = &s->gb;
566cabdff1aSopenharmony_ci    const int w = frame->width;
567cabdff1aSopenharmony_ci    const int h = frame->height;
568cabdff1aSopenharmony_ci    const int l = frame->linesize[0];
569cabdff1aSopenharmony_ci    uint8_t *dst = frame->data[0];
570cabdff1aSopenharmony_ci    int pos = 0, y = 0;
571cabdff1aSopenharmony_ci
572cabdff1aSopenharmony_ci    while (bytestream2_get_bytes_left(gb) > 0) {
573cabdff1aSopenharmony_ci        int count = bytestream2_get_byte(gb);
574cabdff1aSopenharmony_ci        int pixel = bytestream2_get_byte(gb);
575cabdff1aSopenharmony_ci
576cabdff1aSopenharmony_ci        if (!count) {
577cabdff1aSopenharmony_ci            pos += pixel;
578cabdff1aSopenharmony_ci            while (pos >= w) {
579cabdff1aSopenharmony_ci                pos -= w;
580cabdff1aSopenharmony_ci                y++;
581cabdff1aSopenharmony_ci                if (y >= h)
582cabdff1aSopenharmony_ci                    return 0;
583cabdff1aSopenharmony_ci            }
584cabdff1aSopenharmony_ci        } else {
585cabdff1aSopenharmony_ci            while (count > 0) {
586cabdff1aSopenharmony_ci                dst[pos + y * l] = pixel;
587cabdff1aSopenharmony_ci                count--;
588cabdff1aSopenharmony_ci                pos++;
589cabdff1aSopenharmony_ci                if (pos >= w) {
590cabdff1aSopenharmony_ci                    pos = 0;
591cabdff1aSopenharmony_ci                    y++;
592cabdff1aSopenharmony_ci                    if (y >= h)
593cabdff1aSopenharmony_ci                        return 0;
594cabdff1aSopenharmony_ci                }
595cabdff1aSopenharmony_ci            }
596cabdff1aSopenharmony_ci        }
597cabdff1aSopenharmony_ci    }
598cabdff1aSopenharmony_ci
599cabdff1aSopenharmony_ci    return 0;
600cabdff1aSopenharmony_ci}
601cabdff1aSopenharmony_ci
602cabdff1aSopenharmony_cistatic int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
603cabdff1aSopenharmony_ci                        int *got_frame, AVPacket *avpkt)
604cabdff1aSopenharmony_ci{
605cabdff1aSopenharmony_ci    ArgoContext *s = avctx->priv_data;
606cabdff1aSopenharmony_ci    GetByteContext *gb = &s->gb;
607cabdff1aSopenharmony_ci    AVFrame *frame = s->frame;
608cabdff1aSopenharmony_ci    uint32_t chunk;
609cabdff1aSopenharmony_ci    int ret;
610cabdff1aSopenharmony_ci
611cabdff1aSopenharmony_ci    if (avpkt->size < 4)
612cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
613cabdff1aSopenharmony_ci
614cabdff1aSopenharmony_ci    bytestream2_init(gb, avpkt->data, avpkt->size);
615cabdff1aSopenharmony_ci
616cabdff1aSopenharmony_ci    if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0)
617cabdff1aSopenharmony_ci        return ret;
618cabdff1aSopenharmony_ci
619cabdff1aSopenharmony_ci    chunk = bytestream2_get_be32(gb);
620cabdff1aSopenharmony_ci    switch (chunk) {
621cabdff1aSopenharmony_ci    case MKBETAG('P', 'A', 'L', '8'):
622cabdff1aSopenharmony_ci        for (int y = 0; y < frame->height; y++)
623cabdff1aSopenharmony_ci            memset(frame->data[0] + y * frame->linesize[0], 0, frame->width * s->bpp);
624cabdff1aSopenharmony_ci        if (avctx->pix_fmt == AV_PIX_FMT_PAL8)
625cabdff1aSopenharmony_ci            memset(frame->data[1], 0, AVPALETTE_SIZE);
626cabdff1aSopenharmony_ci        return decode_pal8(avctx, s->pal);
627cabdff1aSopenharmony_ci    case MKBETAG('M', 'A', 'D', '1'):
628cabdff1aSopenharmony_ci        if (avctx->pix_fmt == AV_PIX_FMT_PAL8)
629cabdff1aSopenharmony_ci            ret = decode_mad1(avctx, frame);
630cabdff1aSopenharmony_ci        else
631cabdff1aSopenharmony_ci            ret = decode_mad1_24(avctx, frame);
632cabdff1aSopenharmony_ci        break;
633cabdff1aSopenharmony_ci    case MKBETAG('A', 'V', 'C', 'F'):
634cabdff1aSopenharmony_ci        if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
635cabdff1aSopenharmony_ci            s->key = 1;
636cabdff1aSopenharmony_ci            ret = decode_avcf(avctx, frame);
637cabdff1aSopenharmony_ci            break;
638cabdff1aSopenharmony_ci        }
639cabdff1aSopenharmony_ci    case MKBETAG('A', 'L', 'C', 'D'):
640cabdff1aSopenharmony_ci        if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
641cabdff1aSopenharmony_ci            s->key = 0;
642cabdff1aSopenharmony_ci            ret = decode_alcd(avctx, frame);
643cabdff1aSopenharmony_ci            break;
644cabdff1aSopenharmony_ci        }
645cabdff1aSopenharmony_ci    case MKBETAG('R', 'L', 'E', 'F'):
646cabdff1aSopenharmony_ci        if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
647cabdff1aSopenharmony_ci            s->key = 1;
648cabdff1aSopenharmony_ci            ret = decode_rle(avctx, frame);
649cabdff1aSopenharmony_ci            break;
650cabdff1aSopenharmony_ci        }
651cabdff1aSopenharmony_ci    case MKBETAG('R', 'L', 'E', 'D'):
652cabdff1aSopenharmony_ci        if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
653cabdff1aSopenharmony_ci            s->key = 0;
654cabdff1aSopenharmony_ci            ret = decode_rle(avctx, frame);
655cabdff1aSopenharmony_ci            break;
656cabdff1aSopenharmony_ci        }
657cabdff1aSopenharmony_ci    default:
658cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_DEBUG, "unknown chunk 0x%X\n", chunk);
659cabdff1aSopenharmony_ci        break;
660cabdff1aSopenharmony_ci    }
661cabdff1aSopenharmony_ci
662cabdff1aSopenharmony_ci    if (ret < 0)
663cabdff1aSopenharmony_ci        return ret;
664cabdff1aSopenharmony_ci
665cabdff1aSopenharmony_ci    if (avctx->pix_fmt == AV_PIX_FMT_PAL8)
666cabdff1aSopenharmony_ci        memcpy(frame->data[1], s->pal, AVPALETTE_SIZE);
667cabdff1aSopenharmony_ci
668cabdff1aSopenharmony_ci    if ((ret = av_frame_ref(rframe, s->frame)) < 0)
669cabdff1aSopenharmony_ci        return ret;
670cabdff1aSopenharmony_ci
671cabdff1aSopenharmony_ci    frame->pict_type = s->key ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
672cabdff1aSopenharmony_ci    frame->key_frame = s->key;
673cabdff1aSopenharmony_ci    *got_frame = 1;
674cabdff1aSopenharmony_ci
675cabdff1aSopenharmony_ci    return avpkt->size;
676cabdff1aSopenharmony_ci}
677cabdff1aSopenharmony_ci
678cabdff1aSopenharmony_cistatic av_cold int decode_init(AVCodecContext *avctx)
679cabdff1aSopenharmony_ci{
680cabdff1aSopenharmony_ci    ArgoContext *s = avctx->priv_data;
681cabdff1aSopenharmony_ci
682cabdff1aSopenharmony_ci    switch (avctx->bits_per_coded_sample) {
683cabdff1aSopenharmony_ci    case  8: s->bpp = 1;
684cabdff1aSopenharmony_ci             avctx->pix_fmt = AV_PIX_FMT_PAL8; break;
685cabdff1aSopenharmony_ci    case 24: s->bpp = 4;
686cabdff1aSopenharmony_ci             avctx->pix_fmt = AV_PIX_FMT_BGR0; break;
687cabdff1aSopenharmony_ci    default: avpriv_request_sample(s, "depth == %u", avctx->bits_per_coded_sample);
688cabdff1aSopenharmony_ci             return AVERROR_PATCHWELCOME;
689cabdff1aSopenharmony_ci    }
690cabdff1aSopenharmony_ci
691cabdff1aSopenharmony_ci    if (avctx->width % 2 || avctx->height % 2) {
692cabdff1aSopenharmony_ci        avpriv_request_sample(s, "Odd dimensions\n");
693cabdff1aSopenharmony_ci        return AVERROR_PATCHWELCOME;
694cabdff1aSopenharmony_ci    }
695cabdff1aSopenharmony_ci
696cabdff1aSopenharmony_ci    s->frame = av_frame_alloc();
697cabdff1aSopenharmony_ci    if (!s->frame)
698cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
699cabdff1aSopenharmony_ci
700cabdff1aSopenharmony_ci    for (int n = 0, i = -4; i < 4; i++) {
701cabdff1aSopenharmony_ci        for (int j = -14; j < 2; j++) {
702cabdff1aSopenharmony_ci            s->mv0[n][0] = j;
703cabdff1aSopenharmony_ci            s->mv0[n++][1] = i;
704cabdff1aSopenharmony_ci        }
705cabdff1aSopenharmony_ci    }
706cabdff1aSopenharmony_ci
707cabdff1aSopenharmony_ci    for (int n = 0, i = -5; i <= 1; i += 2) {
708cabdff1aSopenharmony_ci        int j = -5;
709cabdff1aSopenharmony_ci
710cabdff1aSopenharmony_ci        while (j <= 1) {
711cabdff1aSopenharmony_ci            s->mv1[n][0] = j;
712cabdff1aSopenharmony_ci            s->mv1[n++][1] = i;
713cabdff1aSopenharmony_ci            j += 2;
714cabdff1aSopenharmony_ci        }
715cabdff1aSopenharmony_ci    }
716cabdff1aSopenharmony_ci
717cabdff1aSopenharmony_ci    return 0;
718cabdff1aSopenharmony_ci}
719cabdff1aSopenharmony_ci
720cabdff1aSopenharmony_cistatic void decode_flush(AVCodecContext *avctx)
721cabdff1aSopenharmony_ci{
722cabdff1aSopenharmony_ci    ArgoContext *s = avctx->priv_data;
723cabdff1aSopenharmony_ci
724cabdff1aSopenharmony_ci    av_frame_unref(s->frame);
725cabdff1aSopenharmony_ci}
726cabdff1aSopenharmony_ci
727cabdff1aSopenharmony_cistatic av_cold int decode_close(AVCodecContext *avctx)
728cabdff1aSopenharmony_ci{
729cabdff1aSopenharmony_ci    ArgoContext *s = avctx->priv_data;
730cabdff1aSopenharmony_ci
731cabdff1aSopenharmony_ci    av_frame_free(&s->frame);
732cabdff1aSopenharmony_ci
733cabdff1aSopenharmony_ci    return 0;
734cabdff1aSopenharmony_ci}
735cabdff1aSopenharmony_ci
736cabdff1aSopenharmony_ciconst FFCodec ff_argo_decoder = {
737cabdff1aSopenharmony_ci    .p.name         = "argo",
738cabdff1aSopenharmony_ci    .p.long_name    = NULL_IF_CONFIG_SMALL("Argonaut Games Video"),
739cabdff1aSopenharmony_ci    .p.type         = AVMEDIA_TYPE_VIDEO,
740cabdff1aSopenharmony_ci    .p.id           = AV_CODEC_ID_ARGO,
741cabdff1aSopenharmony_ci    .priv_data_size = sizeof(ArgoContext),
742cabdff1aSopenharmony_ci    .init           = decode_init,
743cabdff1aSopenharmony_ci    FF_CODEC_DECODE_CB(decode_frame),
744cabdff1aSopenharmony_ci    .flush          = decode_flush,
745cabdff1aSopenharmony_ci    .close          = decode_close,
746cabdff1aSopenharmony_ci    .p.capabilities = AV_CODEC_CAP_DR1,
747cabdff1aSopenharmony_ci    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
748cabdff1aSopenharmony_ci};
749