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