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