xref: /third_party/ffmpeg/libavcodec/rasc.c (revision cabdff1a)
1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * RemotelyAnywhere Screen Capture 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/imgutils.h"
28cabdff1aSopenharmony_ci#include "libavutil/opt.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#include "zlib_wrapper.h"
35cabdff1aSopenharmony_ci
36cabdff1aSopenharmony_ci#include <zlib.h>
37cabdff1aSopenharmony_ci
38cabdff1aSopenharmony_ci#define KBND MKTAG('K', 'B', 'N', 'D')
39cabdff1aSopenharmony_ci#define FINT MKTAG('F', 'I', 'N', 'T')
40cabdff1aSopenharmony_ci#define INIT MKTAG('I', 'N', 'I', 'T')
41cabdff1aSopenharmony_ci#define BNDL MKTAG('B', 'N', 'D', 'L')
42cabdff1aSopenharmony_ci#define KFRM MKTAG('K', 'F', 'R', 'M')
43cabdff1aSopenharmony_ci#define DLTA MKTAG('D', 'L', 'T', 'A')
44cabdff1aSopenharmony_ci#define MOUS MKTAG('M', 'O', 'U', 'S')
45cabdff1aSopenharmony_ci#define MPOS MKTAG('M', 'P', 'O', 'S')
46cabdff1aSopenharmony_ci#define MOVE MKTAG('M', 'O', 'V', 'E')
47cabdff1aSopenharmony_ci#define EMPT MKTAG('E', 'M', 'P', 'T')
48cabdff1aSopenharmony_ci
49cabdff1aSopenharmony_citypedef struct RASCContext {
50cabdff1aSopenharmony_ci    AVClass        *class;
51cabdff1aSopenharmony_ci    int             skip_cursor;
52cabdff1aSopenharmony_ci    GetByteContext  gb;
53cabdff1aSopenharmony_ci    uint8_t        *delta;
54cabdff1aSopenharmony_ci    int             delta_size;
55cabdff1aSopenharmony_ci    uint8_t        *cursor;
56cabdff1aSopenharmony_ci    int             cursor_size;
57cabdff1aSopenharmony_ci    unsigned        cursor_w;
58cabdff1aSopenharmony_ci    unsigned        cursor_h;
59cabdff1aSopenharmony_ci    unsigned        cursor_x;
60cabdff1aSopenharmony_ci    unsigned        cursor_y;
61cabdff1aSopenharmony_ci    int             stride;
62cabdff1aSopenharmony_ci    int             bpp;
63cabdff1aSopenharmony_ci    AVFrame        *frame;
64cabdff1aSopenharmony_ci    AVFrame        *frame1;
65cabdff1aSopenharmony_ci    AVFrame        *frame2;
66cabdff1aSopenharmony_ci    FFZStream       zstream;
67cabdff1aSopenharmony_ci} RASCContext;
68cabdff1aSopenharmony_ci
69cabdff1aSopenharmony_cistatic void clear_plane(AVCodecContext *avctx, AVFrame *frame)
70cabdff1aSopenharmony_ci{
71cabdff1aSopenharmony_ci    RASCContext *s = avctx->priv_data;
72cabdff1aSopenharmony_ci    uint8_t *dst = frame->data[0];
73cabdff1aSopenharmony_ci
74cabdff1aSopenharmony_ci    if (!dst)
75cabdff1aSopenharmony_ci        return;
76cabdff1aSopenharmony_ci
77cabdff1aSopenharmony_ci    for (int y = 0; y < avctx->height; y++) {
78cabdff1aSopenharmony_ci        memset(dst, 0, avctx->width * s->bpp);
79cabdff1aSopenharmony_ci        dst += frame->linesize[0];
80cabdff1aSopenharmony_ci    }
81cabdff1aSopenharmony_ci}
82cabdff1aSopenharmony_ci
83cabdff1aSopenharmony_cistatic void copy_plane(AVCodecContext *avctx, AVFrame *src, AVFrame *dst)
84cabdff1aSopenharmony_ci{
85cabdff1aSopenharmony_ci    RASCContext *s = avctx->priv_data;
86cabdff1aSopenharmony_ci    uint8_t *srcp = src->data[0];
87cabdff1aSopenharmony_ci    uint8_t *dstp = dst->data[0];
88cabdff1aSopenharmony_ci
89cabdff1aSopenharmony_ci    for (int y = 0; y < avctx->height; y++) {
90cabdff1aSopenharmony_ci        memcpy(dstp, srcp, s->stride);
91cabdff1aSopenharmony_ci        srcp += src->linesize[0];
92cabdff1aSopenharmony_ci        dstp += dst->linesize[0];
93cabdff1aSopenharmony_ci    }
94cabdff1aSopenharmony_ci}
95cabdff1aSopenharmony_ci
96cabdff1aSopenharmony_cistatic int init_frames(AVCodecContext *avctx)
97cabdff1aSopenharmony_ci{
98cabdff1aSopenharmony_ci    RASCContext *s = avctx->priv_data;
99cabdff1aSopenharmony_ci    int ret;
100cabdff1aSopenharmony_ci
101cabdff1aSopenharmony_ci    av_frame_unref(s->frame1);
102cabdff1aSopenharmony_ci    av_frame_unref(s->frame2);
103cabdff1aSopenharmony_ci    if ((ret = ff_get_buffer(avctx, s->frame1, 0)) < 0)
104cabdff1aSopenharmony_ci        return ret;
105cabdff1aSopenharmony_ci
106cabdff1aSopenharmony_ci    if ((ret = ff_get_buffer(avctx, s->frame2, 0)) < 0)
107cabdff1aSopenharmony_ci        return ret;
108cabdff1aSopenharmony_ci
109cabdff1aSopenharmony_ci    clear_plane(avctx, s->frame2);
110cabdff1aSopenharmony_ci    clear_plane(avctx, s->frame1);
111cabdff1aSopenharmony_ci
112cabdff1aSopenharmony_ci    return 0;
113cabdff1aSopenharmony_ci}
114cabdff1aSopenharmony_ci
115cabdff1aSopenharmony_cistatic int decode_fint(AVCodecContext *avctx,
116cabdff1aSopenharmony_ci                       const AVPacket *avpkt, unsigned size)
117cabdff1aSopenharmony_ci{
118cabdff1aSopenharmony_ci    RASCContext *s = avctx->priv_data;
119cabdff1aSopenharmony_ci    GetByteContext *gb = &s->gb;
120cabdff1aSopenharmony_ci    unsigned w, h, fmt;
121cabdff1aSopenharmony_ci    int ret;
122cabdff1aSopenharmony_ci
123cabdff1aSopenharmony_ci    if (bytestream2_peek_le32(gb) != 0x65) {
124cabdff1aSopenharmony_ci        if (!s->frame2->data[0] || !s->frame1->data[0])
125cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
126cabdff1aSopenharmony_ci
127cabdff1aSopenharmony_ci        clear_plane(avctx, s->frame2);
128cabdff1aSopenharmony_ci        clear_plane(avctx, s->frame1);
129cabdff1aSopenharmony_ci        return 0;
130cabdff1aSopenharmony_ci    }
131cabdff1aSopenharmony_ci    if (bytestream2_get_bytes_left(gb) < 72)
132cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
133cabdff1aSopenharmony_ci
134cabdff1aSopenharmony_ci    bytestream2_skip(gb, 8);
135cabdff1aSopenharmony_ci    w = bytestream2_get_le32(gb);
136cabdff1aSopenharmony_ci    h = bytestream2_get_le32(gb);
137cabdff1aSopenharmony_ci    bytestream2_skip(gb, 30);
138cabdff1aSopenharmony_ci    fmt = bytestream2_get_le16(gb);
139cabdff1aSopenharmony_ci    bytestream2_skip(gb, 24);
140cabdff1aSopenharmony_ci
141cabdff1aSopenharmony_ci    switch (fmt) {
142cabdff1aSopenharmony_ci    case 8:  s->stride = FFALIGN(w, 4);
143cabdff1aSopenharmony_ci             s->bpp    = 1;
144cabdff1aSopenharmony_ci             fmt = AV_PIX_FMT_PAL8; break;
145cabdff1aSopenharmony_ci    case 16: s->stride = w * 2;
146cabdff1aSopenharmony_ci             s->bpp    = 2;
147cabdff1aSopenharmony_ci             fmt = AV_PIX_FMT_RGB555LE; break;
148cabdff1aSopenharmony_ci    case 32: s->stride = w * 4;
149cabdff1aSopenharmony_ci             s->bpp    = 4;
150cabdff1aSopenharmony_ci             fmt = AV_PIX_FMT_BGR0; break;
151cabdff1aSopenharmony_ci    default: return AVERROR_INVALIDDATA;
152cabdff1aSopenharmony_ci    }
153cabdff1aSopenharmony_ci
154cabdff1aSopenharmony_ci    ret = ff_set_dimensions(avctx, w, h);
155cabdff1aSopenharmony_ci    if (ret < 0)
156cabdff1aSopenharmony_ci        return ret;
157cabdff1aSopenharmony_ci    avctx->width  = w;
158cabdff1aSopenharmony_ci    avctx->height = h;
159cabdff1aSopenharmony_ci    avctx->pix_fmt = fmt;
160cabdff1aSopenharmony_ci
161cabdff1aSopenharmony_ci    ret = init_frames(avctx);
162cabdff1aSopenharmony_ci    if (ret < 0)
163cabdff1aSopenharmony_ci        return ret;
164cabdff1aSopenharmony_ci
165cabdff1aSopenharmony_ci    if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
166cabdff1aSopenharmony_ci        uint32_t *pal = (uint32_t *)s->frame2->data[1];
167cabdff1aSopenharmony_ci
168cabdff1aSopenharmony_ci        for (int i = 0; i < 256; i++)
169cabdff1aSopenharmony_ci            pal[i] = bytestream2_get_le32(gb) | 0xFF000000u;
170cabdff1aSopenharmony_ci    }
171cabdff1aSopenharmony_ci
172cabdff1aSopenharmony_ci    return 0;
173cabdff1aSopenharmony_ci}
174cabdff1aSopenharmony_ci
175cabdff1aSopenharmony_cistatic int decode_zlib(AVCodecContext *avctx, const AVPacket *avpkt,
176cabdff1aSopenharmony_ci                       unsigned size, unsigned uncompressed_size)
177cabdff1aSopenharmony_ci{
178cabdff1aSopenharmony_ci    RASCContext *s = avctx->priv_data;
179cabdff1aSopenharmony_ci    z_stream *const zstream = &s->zstream.zstream;
180cabdff1aSopenharmony_ci    GetByteContext *gb = &s->gb;
181cabdff1aSopenharmony_ci    int zret;
182cabdff1aSopenharmony_ci
183cabdff1aSopenharmony_ci    zret = inflateReset(zstream);
184cabdff1aSopenharmony_ci    if (zret != Z_OK) {
185cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret);
186cabdff1aSopenharmony_ci        return AVERROR_EXTERNAL;
187cabdff1aSopenharmony_ci    }
188cabdff1aSopenharmony_ci
189cabdff1aSopenharmony_ci    av_fast_padded_malloc(&s->delta, &s->delta_size, uncompressed_size);
190cabdff1aSopenharmony_ci    if (!s->delta)
191cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
192cabdff1aSopenharmony_ci
193cabdff1aSopenharmony_ci    zstream->next_in  = avpkt->data + bytestream2_tell(gb);
194cabdff1aSopenharmony_ci    zstream->avail_in = FFMIN(size, bytestream2_get_bytes_left(gb));
195cabdff1aSopenharmony_ci
196cabdff1aSopenharmony_ci    zstream->next_out  = s->delta;
197cabdff1aSopenharmony_ci    zstream->avail_out = s->delta_size;
198cabdff1aSopenharmony_ci
199cabdff1aSopenharmony_ci    zret = inflate(zstream, Z_FINISH);
200cabdff1aSopenharmony_ci    if (zret != Z_STREAM_END) {
201cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR,
202cabdff1aSopenharmony_ci               "Inflate failed with return code: %d.\n", zret);
203cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
204cabdff1aSopenharmony_ci    }
205cabdff1aSopenharmony_ci
206cabdff1aSopenharmony_ci    return 0;
207cabdff1aSopenharmony_ci}
208cabdff1aSopenharmony_ci
209cabdff1aSopenharmony_cistatic int decode_move(AVCodecContext *avctx,
210cabdff1aSopenharmony_ci                       const AVPacket *avpkt, unsigned size)
211cabdff1aSopenharmony_ci{
212cabdff1aSopenharmony_ci    RASCContext *s = avctx->priv_data;
213cabdff1aSopenharmony_ci    GetByteContext *gb = &s->gb;
214cabdff1aSopenharmony_ci    GetByteContext mc;
215cabdff1aSopenharmony_ci    unsigned pos, compression, nb_moves;
216cabdff1aSopenharmony_ci    unsigned uncompressed_size;
217cabdff1aSopenharmony_ci    int ret;
218cabdff1aSopenharmony_ci
219cabdff1aSopenharmony_ci    pos = bytestream2_tell(gb);
220cabdff1aSopenharmony_ci    bytestream2_skip(gb, 8);
221cabdff1aSopenharmony_ci    nb_moves = bytestream2_get_le32(gb);
222cabdff1aSopenharmony_ci    bytestream2_skip(gb, 8);
223cabdff1aSopenharmony_ci    compression = bytestream2_get_le32(gb);
224cabdff1aSopenharmony_ci
225cabdff1aSopenharmony_ci    if (nb_moves > INT32_MAX / 16 || nb_moves > avctx->width * avctx->height)
226cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
227cabdff1aSopenharmony_ci
228cabdff1aSopenharmony_ci    uncompressed_size = 16 * nb_moves;
229cabdff1aSopenharmony_ci
230cabdff1aSopenharmony_ci    if (compression == 1) {
231cabdff1aSopenharmony_ci        ret = decode_zlib(avctx, avpkt,
232cabdff1aSopenharmony_ci                          size - (bytestream2_tell(gb) - pos),
233cabdff1aSopenharmony_ci                          uncompressed_size);
234cabdff1aSopenharmony_ci        if (ret < 0)
235cabdff1aSopenharmony_ci            return ret;
236cabdff1aSopenharmony_ci        bytestream2_init(&mc, s->delta, uncompressed_size);
237cabdff1aSopenharmony_ci    } else if (compression == 0) {
238cabdff1aSopenharmony_ci        bytestream2_init(&mc, avpkt->data + bytestream2_tell(gb),
239cabdff1aSopenharmony_ci                         bytestream2_get_bytes_left(gb));
240cabdff1aSopenharmony_ci    } else if (compression == 2) {
241cabdff1aSopenharmony_ci        avpriv_request_sample(avctx, "compression %d", compression);
242cabdff1aSopenharmony_ci        return AVERROR_PATCHWELCOME;
243cabdff1aSopenharmony_ci    } else {
244cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
245cabdff1aSopenharmony_ci    }
246cabdff1aSopenharmony_ci
247cabdff1aSopenharmony_ci    if (bytestream2_get_bytes_left(&mc) < uncompressed_size)
248cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
249cabdff1aSopenharmony_ci
250cabdff1aSopenharmony_ci    for (int i = 0; i < nb_moves; i++) {
251cabdff1aSopenharmony_ci        int type, start_x, start_y, end_x, end_y, mov_x, mov_y;
252cabdff1aSopenharmony_ci        uint8_t *e2, *b1, *b2;
253cabdff1aSopenharmony_ci        int w, h;
254cabdff1aSopenharmony_ci
255cabdff1aSopenharmony_ci        type = bytestream2_get_le16(&mc);
256cabdff1aSopenharmony_ci        start_x = bytestream2_get_le16(&mc);
257cabdff1aSopenharmony_ci        start_y = bytestream2_get_le16(&mc);
258cabdff1aSopenharmony_ci        end_x = bytestream2_get_le16(&mc);
259cabdff1aSopenharmony_ci        end_y = bytestream2_get_le16(&mc);
260cabdff1aSopenharmony_ci        mov_x = bytestream2_get_le16(&mc);
261cabdff1aSopenharmony_ci        mov_y = bytestream2_get_le16(&mc);
262cabdff1aSopenharmony_ci        bytestream2_skip(&mc, 2);
263cabdff1aSopenharmony_ci
264cabdff1aSopenharmony_ci        if (start_x >= avctx->width || start_y >= avctx->height ||
265cabdff1aSopenharmony_ci            end_x >= avctx->width || end_y >= avctx->height ||
266cabdff1aSopenharmony_ci            mov_x >= avctx->width || mov_y >= avctx->height) {
267cabdff1aSopenharmony_ci            continue;
268cabdff1aSopenharmony_ci        }
269cabdff1aSopenharmony_ci
270cabdff1aSopenharmony_ci        if (start_x >= end_x || start_y >= end_y)
271cabdff1aSopenharmony_ci            continue;
272cabdff1aSopenharmony_ci
273cabdff1aSopenharmony_ci        w = end_x - start_x;
274cabdff1aSopenharmony_ci        h = end_y - start_y;
275cabdff1aSopenharmony_ci
276cabdff1aSopenharmony_ci        if (mov_x + w > avctx->width || mov_y + h > avctx->height)
277cabdff1aSopenharmony_ci            continue;
278cabdff1aSopenharmony_ci
279cabdff1aSopenharmony_ci        if (!s->frame2->data[0] || !s->frame1->data[0])
280cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
281cabdff1aSopenharmony_ci
282cabdff1aSopenharmony_ci        b1 = s->frame1->data[0] + s->frame1->linesize[0] * (start_y + h - 1) + start_x * s->bpp;
283cabdff1aSopenharmony_ci        b2 = s->frame2->data[0] + s->frame2->linesize[0] * (start_y + h - 1) + start_x * s->bpp;
284cabdff1aSopenharmony_ci        e2 = s->frame2->data[0] + s->frame2->linesize[0] * (mov_y + h - 1) + mov_x * s->bpp;
285cabdff1aSopenharmony_ci
286cabdff1aSopenharmony_ci        if (type == 2) {
287cabdff1aSopenharmony_ci            for (int j = 0; j < h; j++) {
288cabdff1aSopenharmony_ci                memcpy(b1, b2, w * s->bpp);
289cabdff1aSopenharmony_ci                b1 -= s->frame1->linesize[0];
290cabdff1aSopenharmony_ci                b2 -= s->frame2->linesize[0];
291cabdff1aSopenharmony_ci            }
292cabdff1aSopenharmony_ci        } else if (type == 1) {
293cabdff1aSopenharmony_ci            for (int j = 0; j < h; j++) {
294cabdff1aSopenharmony_ci                memset(b2, 0, w * s->bpp);
295cabdff1aSopenharmony_ci                b2 -= s->frame2->linesize[0];
296cabdff1aSopenharmony_ci            }
297cabdff1aSopenharmony_ci        } else if (type == 0) {
298cabdff1aSopenharmony_ci            uint8_t *buffer;
299cabdff1aSopenharmony_ci
300cabdff1aSopenharmony_ci            av_fast_padded_malloc(&s->delta, &s->delta_size, w * h * s->bpp);
301cabdff1aSopenharmony_ci            buffer = s->delta;
302cabdff1aSopenharmony_ci            if (!buffer)
303cabdff1aSopenharmony_ci                return AVERROR(ENOMEM);
304cabdff1aSopenharmony_ci
305cabdff1aSopenharmony_ci            for (int j = 0; j < h; j++) {
306cabdff1aSopenharmony_ci                memcpy(buffer + j * w * s->bpp, e2, w * s->bpp);
307cabdff1aSopenharmony_ci                e2 -= s->frame2->linesize[0];
308cabdff1aSopenharmony_ci            }
309cabdff1aSopenharmony_ci
310cabdff1aSopenharmony_ci            for (int j = 0; j < h; j++) {
311cabdff1aSopenharmony_ci                memcpy(b2, buffer + j * w * s->bpp, w * s->bpp);
312cabdff1aSopenharmony_ci                b2 -= s->frame2->linesize[0];
313cabdff1aSopenharmony_ci            }
314cabdff1aSopenharmony_ci        } else {
315cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
316cabdff1aSopenharmony_ci        }
317cabdff1aSopenharmony_ci    }
318cabdff1aSopenharmony_ci
319cabdff1aSopenharmony_ci    bytestream2_skip(gb, size - (bytestream2_tell(gb) - pos));
320cabdff1aSopenharmony_ci
321cabdff1aSopenharmony_ci    return 0;
322cabdff1aSopenharmony_ci}
323cabdff1aSopenharmony_ci
324cabdff1aSopenharmony_ci#define NEXT_LINE                        \
325cabdff1aSopenharmony_ci    if (cx >= w * s->bpp) {              \
326cabdff1aSopenharmony_ci        cx = 0;                          \
327cabdff1aSopenharmony_ci        cy--;                            \
328cabdff1aSopenharmony_ci        b1 -= s->frame1->linesize[0];    \
329cabdff1aSopenharmony_ci        b2 -= s->frame2->linesize[0];    \
330cabdff1aSopenharmony_ci    }                                    \
331cabdff1aSopenharmony_ci    len--;
332cabdff1aSopenharmony_ci
333cabdff1aSopenharmony_cistatic int decode_dlta(AVCodecContext *avctx,
334cabdff1aSopenharmony_ci                       const AVPacket *avpkt, unsigned size)
335cabdff1aSopenharmony_ci{
336cabdff1aSopenharmony_ci    RASCContext *s = avctx->priv_data;
337cabdff1aSopenharmony_ci    GetByteContext *gb = &s->gb;
338cabdff1aSopenharmony_ci    GetByteContext dc;
339cabdff1aSopenharmony_ci    unsigned uncompressed_size, pos;
340cabdff1aSopenharmony_ci    unsigned x, y, w, h;
341cabdff1aSopenharmony_ci    int ret, cx, cy, compression;
342cabdff1aSopenharmony_ci    uint8_t *b1, *b2;
343cabdff1aSopenharmony_ci
344cabdff1aSopenharmony_ci    pos = bytestream2_tell(gb);
345cabdff1aSopenharmony_ci    bytestream2_skip(gb, 12);
346cabdff1aSopenharmony_ci    uncompressed_size = bytestream2_get_le32(gb);
347cabdff1aSopenharmony_ci    x = bytestream2_get_le32(gb);
348cabdff1aSopenharmony_ci    y = bytestream2_get_le32(gb);
349cabdff1aSopenharmony_ci    w = bytestream2_get_le32(gb);
350cabdff1aSopenharmony_ci    h = bytestream2_get_le32(gb);
351cabdff1aSopenharmony_ci
352cabdff1aSopenharmony_ci    if (x >= avctx->width || y >= avctx->height ||
353cabdff1aSopenharmony_ci        w > avctx->width || h > avctx->height)
354cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
355cabdff1aSopenharmony_ci
356cabdff1aSopenharmony_ci    if (x + w > avctx->width || y + h > avctx->height)
357cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
358cabdff1aSopenharmony_ci
359cabdff1aSopenharmony_ci    bytestream2_skip(gb, 4);
360cabdff1aSopenharmony_ci    compression = bytestream2_get_le32(gb);
361cabdff1aSopenharmony_ci
362cabdff1aSopenharmony_ci    if (compression == 1) {
363cabdff1aSopenharmony_ci        if (w * h * s->bpp * 3 < uncompressed_size)
364cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
365cabdff1aSopenharmony_ci        ret = decode_zlib(avctx, avpkt, size, uncompressed_size);
366cabdff1aSopenharmony_ci        if (ret < 0)
367cabdff1aSopenharmony_ci            return ret;
368cabdff1aSopenharmony_ci        bytestream2_init(&dc, s->delta, uncompressed_size);
369cabdff1aSopenharmony_ci    } else if (compression == 0) {
370cabdff1aSopenharmony_ci        if (bytestream2_get_bytes_left(gb) < uncompressed_size)
371cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
372cabdff1aSopenharmony_ci        bytestream2_init(&dc, avpkt->data + bytestream2_tell(gb),
373cabdff1aSopenharmony_ci                         uncompressed_size);
374cabdff1aSopenharmony_ci    } else if (compression == 2) {
375cabdff1aSopenharmony_ci        avpriv_request_sample(avctx, "compression %d", compression);
376cabdff1aSopenharmony_ci        return AVERROR_PATCHWELCOME;
377cabdff1aSopenharmony_ci    } else {
378cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
379cabdff1aSopenharmony_ci    }
380cabdff1aSopenharmony_ci
381cabdff1aSopenharmony_ci    if (!s->frame2->data[0] || !s->frame1->data[0])
382cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
383cabdff1aSopenharmony_ci
384cabdff1aSopenharmony_ci    b1  = s->frame1->data[0] + s->frame1->linesize[0] * (y + h - 1) + x * s->bpp;
385cabdff1aSopenharmony_ci    b2  = s->frame2->data[0] + s->frame2->linesize[0] * (y + h - 1) + x * s->bpp;
386cabdff1aSopenharmony_ci    cx = 0, cy = h;
387cabdff1aSopenharmony_ci    while (bytestream2_get_bytes_left(&dc) > 0) {
388cabdff1aSopenharmony_ci        int type = bytestream2_get_byte(&dc);
389cabdff1aSopenharmony_ci        int len = bytestream2_get_byte(&dc);
390cabdff1aSopenharmony_ci        unsigned fill;
391cabdff1aSopenharmony_ci
392cabdff1aSopenharmony_ci        switch (type) {
393cabdff1aSopenharmony_ci        case 1:
394cabdff1aSopenharmony_ci            while (len > 0 && cy > 0) {
395cabdff1aSopenharmony_ci                cx++;
396cabdff1aSopenharmony_ci                NEXT_LINE
397cabdff1aSopenharmony_ci            }
398cabdff1aSopenharmony_ci            break;
399cabdff1aSopenharmony_ci        case 2:
400cabdff1aSopenharmony_ci            while (len > 0 && cy > 0) {
401cabdff1aSopenharmony_ci                int v0 = b1[cx];
402cabdff1aSopenharmony_ci                int v1 = b2[cx];
403cabdff1aSopenharmony_ci
404cabdff1aSopenharmony_ci                b2[cx] = v0;
405cabdff1aSopenharmony_ci                b1[cx] = v1;
406cabdff1aSopenharmony_ci                cx++;
407cabdff1aSopenharmony_ci                NEXT_LINE
408cabdff1aSopenharmony_ci            }
409cabdff1aSopenharmony_ci            break;
410cabdff1aSopenharmony_ci        case 3:
411cabdff1aSopenharmony_ci            while (len > 0 && cy > 0) {
412cabdff1aSopenharmony_ci                fill = bytestream2_get_byte(&dc);
413cabdff1aSopenharmony_ci                b1[cx] = b2[cx];
414cabdff1aSopenharmony_ci                b2[cx] = fill;
415cabdff1aSopenharmony_ci                cx++;
416cabdff1aSopenharmony_ci                NEXT_LINE
417cabdff1aSopenharmony_ci            }
418cabdff1aSopenharmony_ci            break;
419cabdff1aSopenharmony_ci        case 4:
420cabdff1aSopenharmony_ci            fill = bytestream2_get_byte(&dc);
421cabdff1aSopenharmony_ci            while (len > 0 && cy > 0) {
422cabdff1aSopenharmony_ci                AV_WL32(b1 + cx, AV_RL32(b2 + cx));
423cabdff1aSopenharmony_ci                AV_WL32(b2 + cx, fill);
424cabdff1aSopenharmony_ci                cx++;
425cabdff1aSopenharmony_ci                NEXT_LINE
426cabdff1aSopenharmony_ci            }
427cabdff1aSopenharmony_ci            break;
428cabdff1aSopenharmony_ci        case 7:
429cabdff1aSopenharmony_ci            fill = bytestream2_get_le32(&dc);
430cabdff1aSopenharmony_ci            while (len > 0 && cy > 0) {
431cabdff1aSopenharmony_ci                AV_WL32(b1 + cx, AV_RL32(b2 + cx));
432cabdff1aSopenharmony_ci                AV_WL32(b2 + cx, fill);
433cabdff1aSopenharmony_ci                cx += 4;
434cabdff1aSopenharmony_ci                NEXT_LINE
435cabdff1aSopenharmony_ci            }
436cabdff1aSopenharmony_ci            break;
437cabdff1aSopenharmony_ci        case 10:
438cabdff1aSopenharmony_ci            while (len > 0 && cy > 0) {
439cabdff1aSopenharmony_ci                cx += 4;
440cabdff1aSopenharmony_ci                NEXT_LINE
441cabdff1aSopenharmony_ci            }
442cabdff1aSopenharmony_ci            break;
443cabdff1aSopenharmony_ci        case 12:
444cabdff1aSopenharmony_ci            while (len > 0 && cy > 0) {
445cabdff1aSopenharmony_ci                unsigned v0, v1;
446cabdff1aSopenharmony_ci
447cabdff1aSopenharmony_ci                v0 = AV_RL32(b2 + cx);
448cabdff1aSopenharmony_ci                v1 = AV_RL32(b1 + cx);
449cabdff1aSopenharmony_ci                AV_WL32(b2 + cx, v1);
450cabdff1aSopenharmony_ci                AV_WL32(b1 + cx, v0);
451cabdff1aSopenharmony_ci                cx += 4;
452cabdff1aSopenharmony_ci                NEXT_LINE
453cabdff1aSopenharmony_ci            }
454cabdff1aSopenharmony_ci            break;
455cabdff1aSopenharmony_ci        case 13:
456cabdff1aSopenharmony_ci            while (len > 0 && cy > 0) {
457cabdff1aSopenharmony_ci                fill = bytestream2_get_le32(&dc);
458cabdff1aSopenharmony_ci                AV_WL32(b1 + cx, AV_RL32(b2 + cx));
459cabdff1aSopenharmony_ci                AV_WL32(b2 + cx, fill);
460cabdff1aSopenharmony_ci                cx += 4;
461cabdff1aSopenharmony_ci                NEXT_LINE
462cabdff1aSopenharmony_ci            }
463cabdff1aSopenharmony_ci            break;
464cabdff1aSopenharmony_ci        default:
465cabdff1aSopenharmony_ci            avpriv_request_sample(avctx, "runlen %d", type);
466cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
467cabdff1aSopenharmony_ci        }
468cabdff1aSopenharmony_ci    }
469cabdff1aSopenharmony_ci
470cabdff1aSopenharmony_ci    bytestream2_skip(gb, size - (bytestream2_tell(gb) - pos));
471cabdff1aSopenharmony_ci
472cabdff1aSopenharmony_ci    return 0;
473cabdff1aSopenharmony_ci}
474cabdff1aSopenharmony_ci
475cabdff1aSopenharmony_cistatic int decode_kfrm(AVCodecContext *avctx,
476cabdff1aSopenharmony_ci                       const AVPacket *avpkt, unsigned size)
477cabdff1aSopenharmony_ci{
478cabdff1aSopenharmony_ci    RASCContext *s = avctx->priv_data;
479cabdff1aSopenharmony_ci    z_stream *const zstream = &s->zstream.zstream;
480cabdff1aSopenharmony_ci    GetByteContext *gb = &s->gb;
481cabdff1aSopenharmony_ci    uint8_t *dst;
482cabdff1aSopenharmony_ci    unsigned pos;
483cabdff1aSopenharmony_ci    int zret, ret;
484cabdff1aSopenharmony_ci
485cabdff1aSopenharmony_ci    pos = bytestream2_tell(gb);
486cabdff1aSopenharmony_ci    if (bytestream2_peek_le32(gb) == 0x65) {
487cabdff1aSopenharmony_ci        ret = decode_fint(avctx, avpkt, size);
488cabdff1aSopenharmony_ci        if (ret < 0)
489cabdff1aSopenharmony_ci            return ret;
490cabdff1aSopenharmony_ci    }
491cabdff1aSopenharmony_ci
492cabdff1aSopenharmony_ci    if (!s->frame2->data[0])
493cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
494cabdff1aSopenharmony_ci
495cabdff1aSopenharmony_ci    zret = inflateReset(zstream);
496cabdff1aSopenharmony_ci    if (zret != Z_OK) {
497cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret);
498cabdff1aSopenharmony_ci        return AVERROR_EXTERNAL;
499cabdff1aSopenharmony_ci    }
500cabdff1aSopenharmony_ci
501cabdff1aSopenharmony_ci    zstream->next_in  = avpkt->data + bytestream2_tell(gb);
502cabdff1aSopenharmony_ci    zstream->avail_in = bytestream2_get_bytes_left(gb);
503cabdff1aSopenharmony_ci
504cabdff1aSopenharmony_ci    dst = s->frame2->data[0] + (avctx->height - 1) * s->frame2->linesize[0];
505cabdff1aSopenharmony_ci    for (int i = 0; i < avctx->height; i++) {
506cabdff1aSopenharmony_ci        zstream->next_out  = dst;
507cabdff1aSopenharmony_ci        zstream->avail_out = s->stride;
508cabdff1aSopenharmony_ci
509cabdff1aSopenharmony_ci        zret = inflate(zstream, Z_SYNC_FLUSH);
510cabdff1aSopenharmony_ci        if (zret != Z_OK && zret != Z_STREAM_END) {
511cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_ERROR,
512cabdff1aSopenharmony_ci                   "Inflate failed with return code: %d.\n", zret);
513cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
514cabdff1aSopenharmony_ci        }
515cabdff1aSopenharmony_ci
516cabdff1aSopenharmony_ci        dst -= s->frame2->linesize[0];
517cabdff1aSopenharmony_ci    }
518cabdff1aSopenharmony_ci
519cabdff1aSopenharmony_ci    dst = s->frame1->data[0] + (avctx->height - 1) * s->frame1->linesize[0];
520cabdff1aSopenharmony_ci    for (int i = 0; i < avctx->height; i++) {
521cabdff1aSopenharmony_ci        zstream->next_out  = dst;
522cabdff1aSopenharmony_ci        zstream->avail_out = s->stride;
523cabdff1aSopenharmony_ci
524cabdff1aSopenharmony_ci        zret = inflate(zstream, Z_SYNC_FLUSH);
525cabdff1aSopenharmony_ci        if (zret != Z_OK && zret != Z_STREAM_END) {
526cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_ERROR,
527cabdff1aSopenharmony_ci                   "Inflate failed with return code: %d.\n", zret);
528cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
529cabdff1aSopenharmony_ci        }
530cabdff1aSopenharmony_ci
531cabdff1aSopenharmony_ci        dst -= s->frame1->linesize[0];
532cabdff1aSopenharmony_ci    }
533cabdff1aSopenharmony_ci
534cabdff1aSopenharmony_ci    bytestream2_skip(gb, size - (bytestream2_tell(gb) - pos));
535cabdff1aSopenharmony_ci
536cabdff1aSopenharmony_ci    return 0;
537cabdff1aSopenharmony_ci}
538cabdff1aSopenharmony_ci
539cabdff1aSopenharmony_cistatic int decode_mous(AVCodecContext *avctx,
540cabdff1aSopenharmony_ci                       const AVPacket *avpkt, unsigned size)
541cabdff1aSopenharmony_ci{
542cabdff1aSopenharmony_ci    RASCContext *s = avctx->priv_data;
543cabdff1aSopenharmony_ci    GetByteContext *gb = &s->gb;
544cabdff1aSopenharmony_ci    unsigned w, h, pos, uncompressed_size;
545cabdff1aSopenharmony_ci    int ret;
546cabdff1aSopenharmony_ci
547cabdff1aSopenharmony_ci    pos = bytestream2_tell(gb);
548cabdff1aSopenharmony_ci    bytestream2_skip(gb, 8);
549cabdff1aSopenharmony_ci    w = bytestream2_get_le32(gb);
550cabdff1aSopenharmony_ci    h = bytestream2_get_le32(gb);
551cabdff1aSopenharmony_ci    bytestream2_skip(gb, 12);
552cabdff1aSopenharmony_ci    uncompressed_size = bytestream2_get_le32(gb);
553cabdff1aSopenharmony_ci
554cabdff1aSopenharmony_ci    if (w > avctx->width || h > avctx->height)
555cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
556cabdff1aSopenharmony_ci
557cabdff1aSopenharmony_ci    if (uncompressed_size != 3 * w * h)
558cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
559cabdff1aSopenharmony_ci
560cabdff1aSopenharmony_ci    av_fast_padded_malloc(&s->cursor, &s->cursor_size, uncompressed_size);
561cabdff1aSopenharmony_ci    if (!s->cursor)
562cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
563cabdff1aSopenharmony_ci
564cabdff1aSopenharmony_ci    ret = decode_zlib(avctx, avpkt,
565cabdff1aSopenharmony_ci                      size - (bytestream2_tell(gb) - pos),
566cabdff1aSopenharmony_ci                      uncompressed_size);
567cabdff1aSopenharmony_ci    if (ret < 0)
568cabdff1aSopenharmony_ci        return ret;
569cabdff1aSopenharmony_ci    memcpy(s->cursor, s->delta, uncompressed_size);
570cabdff1aSopenharmony_ci
571cabdff1aSopenharmony_ci    bytestream2_skip(gb, size - (bytestream2_tell(gb) - pos));
572cabdff1aSopenharmony_ci
573cabdff1aSopenharmony_ci    s->cursor_w = w;
574cabdff1aSopenharmony_ci    s->cursor_h = h;
575cabdff1aSopenharmony_ci
576cabdff1aSopenharmony_ci    return 0;
577cabdff1aSopenharmony_ci}
578cabdff1aSopenharmony_ci
579cabdff1aSopenharmony_cistatic int decode_mpos(AVCodecContext *avctx,
580cabdff1aSopenharmony_ci                       const AVPacket *avpkt, unsigned size)
581cabdff1aSopenharmony_ci{
582cabdff1aSopenharmony_ci    RASCContext *s = avctx->priv_data;
583cabdff1aSopenharmony_ci    GetByteContext *gb = &s->gb;
584cabdff1aSopenharmony_ci    unsigned pos;
585cabdff1aSopenharmony_ci
586cabdff1aSopenharmony_ci    pos = bytestream2_tell(gb);
587cabdff1aSopenharmony_ci    bytestream2_skip(gb, 8);
588cabdff1aSopenharmony_ci    s->cursor_x = bytestream2_get_le32(gb);
589cabdff1aSopenharmony_ci    s->cursor_y = bytestream2_get_le32(gb);
590cabdff1aSopenharmony_ci
591cabdff1aSopenharmony_ci    bytestream2_skip(gb, size - (bytestream2_tell(gb) - pos));
592cabdff1aSopenharmony_ci
593cabdff1aSopenharmony_ci    return 0;
594cabdff1aSopenharmony_ci}
595cabdff1aSopenharmony_ci
596cabdff1aSopenharmony_cistatic void draw_cursor(AVCodecContext *avctx)
597cabdff1aSopenharmony_ci{
598cabdff1aSopenharmony_ci    RASCContext *s = avctx->priv_data;
599cabdff1aSopenharmony_ci    uint8_t *dst, *pal;
600cabdff1aSopenharmony_ci
601cabdff1aSopenharmony_ci    if (!s->cursor)
602cabdff1aSopenharmony_ci        return;
603cabdff1aSopenharmony_ci
604cabdff1aSopenharmony_ci    if (s->cursor_x >= avctx->width || s->cursor_y >= avctx->height)
605cabdff1aSopenharmony_ci        return;
606cabdff1aSopenharmony_ci
607cabdff1aSopenharmony_ci    if (s->cursor_x + s->cursor_w > avctx->width ||
608cabdff1aSopenharmony_ci        s->cursor_y + s->cursor_h > avctx->height)
609cabdff1aSopenharmony_ci        return;
610cabdff1aSopenharmony_ci
611cabdff1aSopenharmony_ci    if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
612cabdff1aSopenharmony_ci        pal = s->frame->data[1];
613cabdff1aSopenharmony_ci        for (int i = 0; i < s->cursor_h; i++) {
614cabdff1aSopenharmony_ci            for (int j = 0; j < s->cursor_w; j++) {
615cabdff1aSopenharmony_ci                int cr = s->cursor[3 * s->cursor_w * (s->cursor_h - i - 1) + 3 * j + 0];
616cabdff1aSopenharmony_ci                int cg = s->cursor[3 * s->cursor_w * (s->cursor_h - i - 1) + 3 * j + 1];
617cabdff1aSopenharmony_ci                int cb = s->cursor[3 * s->cursor_w * (s->cursor_h - i - 1) + 3 * j + 2];
618cabdff1aSopenharmony_ci                int best = INT_MAX;
619cabdff1aSopenharmony_ci                int index = 0;
620cabdff1aSopenharmony_ci                int dist;
621cabdff1aSopenharmony_ci
622cabdff1aSopenharmony_ci                if (cr == s->cursor[0] && cg == s->cursor[1] && cb == s->cursor[2])
623cabdff1aSopenharmony_ci                    continue;
624cabdff1aSopenharmony_ci
625cabdff1aSopenharmony_ci                dst = s->frame->data[0] + s->frame->linesize[0] * (s->cursor_y + i) + (s->cursor_x + j);
626cabdff1aSopenharmony_ci                for (int k = 0; k < 256; k++) {
627cabdff1aSopenharmony_ci                    int pr = pal[k * 4 + 0];
628cabdff1aSopenharmony_ci                    int pg = pal[k * 4 + 1];
629cabdff1aSopenharmony_ci                    int pb = pal[k * 4 + 2];
630cabdff1aSopenharmony_ci
631cabdff1aSopenharmony_ci                    dist = FFABS(cr - pr) + FFABS(cg - pg) + FFABS(cb - pb);
632cabdff1aSopenharmony_ci                    if (dist < best) {
633cabdff1aSopenharmony_ci                        best = dist;
634cabdff1aSopenharmony_ci                        index = k;
635cabdff1aSopenharmony_ci                    }
636cabdff1aSopenharmony_ci                }
637cabdff1aSopenharmony_ci                dst[0] = index;
638cabdff1aSopenharmony_ci            }
639cabdff1aSopenharmony_ci        }
640cabdff1aSopenharmony_ci    } else if (avctx->pix_fmt == AV_PIX_FMT_RGB555LE) {
641cabdff1aSopenharmony_ci        for (int i = 0; i < s->cursor_h; i++) {
642cabdff1aSopenharmony_ci            for (int j = 0; j < s->cursor_w; j++) {
643cabdff1aSopenharmony_ci                int cr = s->cursor[3 * s->cursor_w * (s->cursor_h - i - 1) + 3 * j + 0];
644cabdff1aSopenharmony_ci                int cg = s->cursor[3 * s->cursor_w * (s->cursor_h - i - 1) + 3 * j + 1];
645cabdff1aSopenharmony_ci                int cb = s->cursor[3 * s->cursor_w * (s->cursor_h - i - 1) + 3 * j + 2];
646cabdff1aSopenharmony_ci
647cabdff1aSopenharmony_ci                if (cr == s->cursor[0] && cg == s->cursor[1] && cb == s->cursor[2])
648cabdff1aSopenharmony_ci                    continue;
649cabdff1aSopenharmony_ci
650cabdff1aSopenharmony_ci                cr >>= 3; cg >>=3; cb >>= 3;
651cabdff1aSopenharmony_ci                dst = s->frame->data[0] + s->frame->linesize[0] * (s->cursor_y + i) + 2 * (s->cursor_x + j);
652cabdff1aSopenharmony_ci                AV_WL16(dst, cr | cg << 5 | cb << 10);
653cabdff1aSopenharmony_ci            }
654cabdff1aSopenharmony_ci        }
655cabdff1aSopenharmony_ci    } else if (avctx->pix_fmt == AV_PIX_FMT_BGR0) {
656cabdff1aSopenharmony_ci        for (int i = 0; i < s->cursor_h; i++) {
657cabdff1aSopenharmony_ci            for (int j = 0; j < s->cursor_w; j++) {
658cabdff1aSopenharmony_ci                int cr = s->cursor[3 * s->cursor_w * (s->cursor_h - i - 1) + 3 * j + 0];
659cabdff1aSopenharmony_ci                int cg = s->cursor[3 * s->cursor_w * (s->cursor_h - i - 1) + 3 * j + 1];
660cabdff1aSopenharmony_ci                int cb = s->cursor[3 * s->cursor_w * (s->cursor_h - i - 1) + 3 * j + 2];
661cabdff1aSopenharmony_ci
662cabdff1aSopenharmony_ci                if (cr == s->cursor[0] && cg == s->cursor[1] && cb == s->cursor[2])
663cabdff1aSopenharmony_ci                    continue;
664cabdff1aSopenharmony_ci
665cabdff1aSopenharmony_ci                dst = s->frame->data[0] + s->frame->linesize[0] * (s->cursor_y + i) + 4 * (s->cursor_x + j);
666cabdff1aSopenharmony_ci                dst[0] = cb;
667cabdff1aSopenharmony_ci                dst[1] = cg;
668cabdff1aSopenharmony_ci                dst[2] = cr;
669cabdff1aSopenharmony_ci            }
670cabdff1aSopenharmony_ci        }
671cabdff1aSopenharmony_ci    }
672cabdff1aSopenharmony_ci}
673cabdff1aSopenharmony_ci
674cabdff1aSopenharmony_cistatic int decode_frame(AVCodecContext *avctx, AVFrame *frame,
675cabdff1aSopenharmony_ci                        int *got_frame, AVPacket *avpkt)
676cabdff1aSopenharmony_ci{
677cabdff1aSopenharmony_ci    RASCContext *s = avctx->priv_data;
678cabdff1aSopenharmony_ci    GetByteContext *gb = &s->gb;
679cabdff1aSopenharmony_ci    int ret, intra = 0;
680cabdff1aSopenharmony_ci
681cabdff1aSopenharmony_ci    bytestream2_init(gb, avpkt->data, avpkt->size);
682cabdff1aSopenharmony_ci
683cabdff1aSopenharmony_ci    if (bytestream2_peek_le32(gb) == EMPT)
684cabdff1aSopenharmony_ci        return avpkt->size;
685cabdff1aSopenharmony_ci
686cabdff1aSopenharmony_ci    s->frame = frame;
687cabdff1aSopenharmony_ci
688cabdff1aSopenharmony_ci    while (bytestream2_get_bytes_left(gb) > 0) {
689cabdff1aSopenharmony_ci        unsigned type, size = 0;
690cabdff1aSopenharmony_ci
691cabdff1aSopenharmony_ci        if (bytestream2_get_bytes_left(gb) < 8)
692cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
693cabdff1aSopenharmony_ci
694cabdff1aSopenharmony_ci        type = bytestream2_get_le32(gb);
695cabdff1aSopenharmony_ci        if (type == KBND || type == BNDL) {
696cabdff1aSopenharmony_ci            intra = type == KBND;
697cabdff1aSopenharmony_ci            type = bytestream2_get_le32(gb);
698cabdff1aSopenharmony_ci        }
699cabdff1aSopenharmony_ci
700cabdff1aSopenharmony_ci        size = bytestream2_get_le32(gb);
701cabdff1aSopenharmony_ci        if (bytestream2_get_bytes_left(gb) < size)
702cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
703cabdff1aSopenharmony_ci
704cabdff1aSopenharmony_ci        switch (type) {
705cabdff1aSopenharmony_ci        case FINT:
706cabdff1aSopenharmony_ci        case INIT:
707cabdff1aSopenharmony_ci            ret = decode_fint(avctx, avpkt, size);
708cabdff1aSopenharmony_ci            break;
709cabdff1aSopenharmony_ci        case KFRM:
710cabdff1aSopenharmony_ci            ret = decode_kfrm(avctx, avpkt, size);
711cabdff1aSopenharmony_ci            break;
712cabdff1aSopenharmony_ci        case DLTA:
713cabdff1aSopenharmony_ci            ret = decode_dlta(avctx, avpkt, size);
714cabdff1aSopenharmony_ci            break;
715cabdff1aSopenharmony_ci        case MOVE:
716cabdff1aSopenharmony_ci            ret = decode_move(avctx, avpkt, size);
717cabdff1aSopenharmony_ci            break;
718cabdff1aSopenharmony_ci        case MOUS:
719cabdff1aSopenharmony_ci            ret = decode_mous(avctx, avpkt, size);
720cabdff1aSopenharmony_ci            break;
721cabdff1aSopenharmony_ci        case MPOS:
722cabdff1aSopenharmony_ci            ret = decode_mpos(avctx, avpkt, size);
723cabdff1aSopenharmony_ci            break;
724cabdff1aSopenharmony_ci        default:
725cabdff1aSopenharmony_ci            bytestream2_skip(gb, size);
726cabdff1aSopenharmony_ci            ret = 0;
727cabdff1aSopenharmony_ci        }
728cabdff1aSopenharmony_ci
729cabdff1aSopenharmony_ci        if (ret < 0)
730cabdff1aSopenharmony_ci            return ret;
731cabdff1aSopenharmony_ci    }
732cabdff1aSopenharmony_ci
733cabdff1aSopenharmony_ci    if (!s->frame2->data[0] || !s->frame1->data[0])
734cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
735cabdff1aSopenharmony_ci
736cabdff1aSopenharmony_ci    if ((ret = ff_get_buffer(avctx, s->frame, 0)) < 0)
737cabdff1aSopenharmony_ci        return ret;
738cabdff1aSopenharmony_ci
739cabdff1aSopenharmony_ci    copy_plane(avctx, s->frame2, s->frame);
740cabdff1aSopenharmony_ci    if (avctx->pix_fmt == AV_PIX_FMT_PAL8)
741cabdff1aSopenharmony_ci        memcpy(s->frame->data[1], s->frame2->data[1], 1024);
742cabdff1aSopenharmony_ci    if (!s->skip_cursor)
743cabdff1aSopenharmony_ci        draw_cursor(avctx);
744cabdff1aSopenharmony_ci
745cabdff1aSopenharmony_ci    s->frame->key_frame = intra;
746cabdff1aSopenharmony_ci    s->frame->pict_type = intra ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
747cabdff1aSopenharmony_ci
748cabdff1aSopenharmony_ci    *got_frame = 1;
749cabdff1aSopenharmony_ci
750cabdff1aSopenharmony_ci    return avpkt->size;
751cabdff1aSopenharmony_ci}
752cabdff1aSopenharmony_ci
753cabdff1aSopenharmony_cistatic av_cold int decode_init(AVCodecContext *avctx)
754cabdff1aSopenharmony_ci{
755cabdff1aSopenharmony_ci    RASCContext *s = avctx->priv_data;
756cabdff1aSopenharmony_ci
757cabdff1aSopenharmony_ci    s->frame1 = av_frame_alloc();
758cabdff1aSopenharmony_ci    s->frame2 = av_frame_alloc();
759cabdff1aSopenharmony_ci    if (!s->frame1 || !s->frame2)
760cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
761cabdff1aSopenharmony_ci
762cabdff1aSopenharmony_ci    return ff_inflate_init(&s->zstream, avctx);
763cabdff1aSopenharmony_ci}
764cabdff1aSopenharmony_ci
765cabdff1aSopenharmony_cistatic av_cold int decode_close(AVCodecContext *avctx)
766cabdff1aSopenharmony_ci{
767cabdff1aSopenharmony_ci    RASCContext *s = avctx->priv_data;
768cabdff1aSopenharmony_ci
769cabdff1aSopenharmony_ci    av_freep(&s->cursor);
770cabdff1aSopenharmony_ci    s->cursor_size = 0;
771cabdff1aSopenharmony_ci    av_freep(&s->delta);
772cabdff1aSopenharmony_ci    s->delta_size = 0;
773cabdff1aSopenharmony_ci    av_frame_free(&s->frame1);
774cabdff1aSopenharmony_ci    av_frame_free(&s->frame2);
775cabdff1aSopenharmony_ci    ff_inflate_end(&s->zstream);
776cabdff1aSopenharmony_ci
777cabdff1aSopenharmony_ci    return 0;
778cabdff1aSopenharmony_ci}
779cabdff1aSopenharmony_ci
780cabdff1aSopenharmony_cistatic void decode_flush(AVCodecContext *avctx)
781cabdff1aSopenharmony_ci{
782cabdff1aSopenharmony_ci    RASCContext *s = avctx->priv_data;
783cabdff1aSopenharmony_ci
784cabdff1aSopenharmony_ci    clear_plane(avctx, s->frame1);
785cabdff1aSopenharmony_ci    clear_plane(avctx, s->frame2);
786cabdff1aSopenharmony_ci}
787cabdff1aSopenharmony_ci
788cabdff1aSopenharmony_cistatic const AVOption options[] = {
789cabdff1aSopenharmony_ci{ "skip_cursor", "skip the cursor", offsetof(RASCContext, skip_cursor), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM },
790cabdff1aSopenharmony_ci{ NULL },
791cabdff1aSopenharmony_ci};
792cabdff1aSopenharmony_ci
793cabdff1aSopenharmony_cistatic const AVClass rasc_decoder_class = {
794cabdff1aSopenharmony_ci    .class_name = "rasc decoder",
795cabdff1aSopenharmony_ci    .item_name  = av_default_item_name,
796cabdff1aSopenharmony_ci    .option     = options,
797cabdff1aSopenharmony_ci    .version    = LIBAVUTIL_VERSION_INT,
798cabdff1aSopenharmony_ci};
799cabdff1aSopenharmony_ci
800cabdff1aSopenharmony_ciconst FFCodec ff_rasc_decoder = {
801cabdff1aSopenharmony_ci    .p.name           = "rasc",
802cabdff1aSopenharmony_ci    .p.long_name      = NULL_IF_CONFIG_SMALL("RemotelyAnywhere Screen Capture"),
803cabdff1aSopenharmony_ci    .p.type           = AVMEDIA_TYPE_VIDEO,
804cabdff1aSopenharmony_ci    .p.id             = AV_CODEC_ID_RASC,
805cabdff1aSopenharmony_ci    .priv_data_size   = sizeof(RASCContext),
806cabdff1aSopenharmony_ci    .init             = decode_init,
807cabdff1aSopenharmony_ci    .close            = decode_close,
808cabdff1aSopenharmony_ci    FF_CODEC_DECODE_CB(decode_frame),
809cabdff1aSopenharmony_ci    .flush            = decode_flush,
810cabdff1aSopenharmony_ci    .p.capabilities   = AV_CODEC_CAP_DR1,
811cabdff1aSopenharmony_ci    .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE |
812cabdff1aSopenharmony_ci                        FF_CODEC_CAP_INIT_CLEANUP,
813cabdff1aSopenharmony_ci    .p.priv_class     = &rasc_decoder_class,
814cabdff1aSopenharmony_ci};
815