FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rasc.c
Go to the documentation of this file.
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/avassert.h"
28 #include "libavutil/imgutils.h"
29 #include "libavutil/opt.h"
30 
31 #include "avcodec.h"
32 #include "bytestream.h"
33 #include "internal.h"
34 
35 #include <zlib.h>
36 
37 #define KBND MKTAG('K', 'B', 'N', 'D')
38 #define FINT MKTAG('F', 'I', 'N', 'T')
39 #define INIT MKTAG('I', 'N', 'I', 'T')
40 #define BNDL MKTAG('B', 'N', 'D', 'L')
41 #define KFRM MKTAG('K', 'F', 'R', 'M')
42 #define DLTA MKTAG('D', 'L', 'T', 'A')
43 #define MOUS MKTAG('M', 'O', 'U', 'S')
44 #define MPOS MKTAG('M', 'P', 'O', 'S')
45 #define MOVE MKTAG('M', 'O', 'V', 'E')
46 #define EMPT MKTAG('E', 'M', 'P', 'T')
47 
48 typedef struct RASCContext {
49  AVClass *class;
56  unsigned cursor_w;
57  unsigned cursor_h;
58  unsigned cursor_x;
59  unsigned cursor_y;
60  int stride;
61  int bpp;
62  z_stream zstream;
66 } RASCContext;
67 
68 static void clear_plane(AVCodecContext *avctx, AVFrame *frame)
69 {
70  RASCContext *s = avctx->priv_data;
71  uint8_t *dst = frame->data[0];
72 
73  for (int y = 0; y < avctx->height; y++) {
74  memset(dst, 0, avctx->width * s->bpp);
75  dst += frame->linesize[0];
76  }
77 }
78 
79 static void copy_plane(AVCodecContext *avctx, AVFrame *src, AVFrame *dst)
80 {
81  RASCContext *s = avctx->priv_data;
82  uint8_t *srcp = src->data[0];
83  uint8_t *dstp = dst->data[0];
84 
85  for (int y = 0; y < avctx->height; y++) {
86  memcpy(dstp, srcp, s->stride);
87  srcp += src->linesize[0];
88  dstp += dst->linesize[0];
89  }
90 }
91 
92 static int init_frames(AVCodecContext *avctx)
93 {
94  RASCContext *s = avctx->priv_data;
95  int ret;
96 
99  if ((ret = ff_get_buffer(avctx, s->frame1, 0)) < 0)
100  return ret;
101 
102  if ((ret = ff_get_buffer(avctx, s->frame2, 0)) < 0)
103  return ret;
104 
105  clear_plane(avctx, s->frame2);
106  clear_plane(avctx, s->frame1);
107 
108  return 0;
109 }
110 
111 static int decode_fint(AVCodecContext *avctx,
112  AVPacket *avpkt, unsigned size)
113 {
114  RASCContext *s = avctx->priv_data;
115  GetByteContext *gb = &s->gb;
116  unsigned w, h, fmt;
117  int ret;
118 
119  if (bytestream2_peek_le32(gb) != 0x65) {
120  if (!s->frame2->data[0] || !s->frame1->data[0])
121  return AVERROR_INVALIDDATA;
122 
123  clear_plane(avctx, s->frame2);
124  clear_plane(avctx, s->frame1);
125  return 0;
126  }
127 
128  bytestream2_skip(gb, 8);
129  w = bytestream2_get_le32(gb);
130  h = bytestream2_get_le32(gb);
131  bytestream2_skip(gb, 30);
132  fmt = bytestream2_get_le16(gb);
133  bytestream2_skip(gb, 24);
134 
135  switch (fmt) {
136  case 8: s->stride = FFALIGN(w, 4);
137  s->bpp = 1;
138  fmt = AV_PIX_FMT_PAL8; break;
139  case 16: s->stride = w * 2;
140  s->bpp = 2;
141  fmt = AV_PIX_FMT_RGB555LE; break;
142  case 32: s->stride = w * 4;
143  s->bpp = 4;
144  fmt = AV_PIX_FMT_BGR0; break;
145  default: return AVERROR_INVALIDDATA;
146  }
147 
148  ret = ff_set_dimensions(avctx, w, h);
149  if (ret < 0)
150  return ret;
151  avctx->width = w;
152  avctx->height = h;
153  avctx->pix_fmt = fmt;
154 
155  ret = init_frames(avctx);
156  if (ret < 0)
157  return ret;
158 
159  if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
160  uint32_t *pal = (uint32_t *)s->frame2->data[1];
161 
162  for (int i = 0; i < 256; i++)
163  pal[i] = bytestream2_get_le32(gb) | 0xFF000000u;
164  }
165 
166  return 0;
167 }
168 
169 static int decode_zlib(AVCodecContext *avctx, AVPacket *avpkt,
170  unsigned size, unsigned uncompressed_size)
171 {
172  RASCContext *s = avctx->priv_data;
173  GetByteContext *gb = &s->gb;
174  int zret;
175 
176  zret = inflateReset(&s->zstream);
177  if (zret != Z_OK) {
178  av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret);
179  return AVERROR_EXTERNAL;
180  }
181 
182  av_fast_padded_malloc(&s->delta, &s->delta_size, uncompressed_size);
183  if (!s->delta)
184  return AVERROR(ENOMEM);
185 
186  s->zstream.next_in = avpkt->data + bytestream2_tell(gb);
187  s->zstream.avail_in = FFMIN(size, bytestream2_get_bytes_left(gb));
188 
189  s->zstream.next_out = s->delta;
190  s->zstream.avail_out = s->delta_size;
191 
192  zret = inflate(&s->zstream, Z_FINISH);
193  if (zret != Z_STREAM_END) {
194  av_log(avctx, AV_LOG_ERROR,
195  "Inflate failed with return code: %d.\n", zret);
196  return AVERROR_INVALIDDATA;
197  }
198 
199  return 0;
200 }
201 
202 static int decode_move(AVCodecContext *avctx,
203  AVPacket *avpkt, unsigned size)
204 {
205  RASCContext *s = avctx->priv_data;
206  GetByteContext *gb = &s->gb;
208  unsigned pos, compression, nb_moves;
209  unsigned uncompressed_size;
210  int ret;
211 
212  pos = bytestream2_tell(gb);
213  bytestream2_skip(gb, 8);
214  nb_moves = bytestream2_get_le32(gb);
215  bytestream2_skip(gb, 8);
216  compression = bytestream2_get_le32(gb);
217 
218  if (nb_moves > INT32_MAX / 16)
219  return AVERROR_INVALIDDATA;
220 
221  uncompressed_size = 16 * nb_moves;
222 
223  if (compression == 1) {
224  ret = decode_zlib(avctx, avpkt,
225  size - (bytestream2_tell(gb) - pos),
226  uncompressed_size);
227  if (ret < 0)
228  return ret;
229  bytestream2_init(&mc, s->delta, uncompressed_size);
230  } else if (compression == 0) {
231  bytestream2_init(&mc, avpkt->data + bytestream2_tell(gb),
233  } else if (compression == 2) {
234  avpriv_request_sample(avctx, "compression %d", compression);
235  return AVERROR_PATCHWELCOME;
236  } else {
237  return AVERROR_INVALIDDATA;
238  }
239 
240  if (bytestream2_get_bytes_left(&mc) < uncompressed_size)
241  return AVERROR_INVALIDDATA;
242 
243  for (int i = 0; i < nb_moves; i++) {
244  int type, start_x, start_y, end_x, end_y, mov_x, mov_y;
245  uint8_t *e2, *b1, *b2;
246  int w, h;
247 
248  type = bytestream2_get_le16(&mc);
249  start_x = bytestream2_get_le16(&mc);
250  start_y = bytestream2_get_le16(&mc);
251  end_x = bytestream2_get_le16(&mc);
252  end_y = bytestream2_get_le16(&mc);
253  mov_x = bytestream2_get_le16(&mc);
254  mov_y = bytestream2_get_le16(&mc);
255  bytestream2_skip(&mc, 2);
256 
257  if (start_x >= avctx->width || start_y >= avctx->height ||
258  end_x >= avctx->width || end_y >= avctx->height ||
259  mov_x >= avctx->width || mov_y >= avctx->height) {
260  continue;
261  }
262 
263  if (start_x >= end_x || start_y >= end_y)
264  continue;
265 
266  w = end_x - start_x;
267  h = end_y - start_y;
268 
269  if (mov_x + w > avctx->width || mov_y + h > avctx->height)
270  continue;
271 
272  if (!s->frame2->data[0] || !s->frame1->data[0])
273  return AVERROR_INVALIDDATA;
274 
275  b1 = s->frame1->data[0] + s->frame1->linesize[0] * (start_y + h - 1) + start_x * s->bpp;
276  b2 = s->frame2->data[0] + s->frame2->linesize[0] * (start_y + h - 1) + start_x * s->bpp;
277  e2 = s->frame2->data[0] + s->frame2->linesize[0] * (mov_y + h - 1) + mov_x * s->bpp;
278 
279  if (type == 2) {
280  for (int j = 0; j < h; j++) {
281  memcpy(b1, b2, w * s->bpp);
282  b1 -= s->frame1->linesize[0];
283  b2 -= s->frame2->linesize[0];
284  }
285  } else if (type == 1) {
286  for (int j = 0; j < h; j++) {
287  memset(b2, 0, w * s->bpp);
288  b2 -= s->frame2->linesize[0];
289  }
290  } else if (type == 0) {
291  uint8_t *buffer;
292 
293  av_fast_padded_malloc(&s->delta, &s->delta_size, w * h * s->bpp);
294  buffer = s->delta;
295  if (!buffer)
296  return AVERROR(ENOMEM);
297 
298  for (int j = 0; j < h; j++) {
299  memcpy(buffer + j * w * s->bpp, e2, w * s->bpp);
300  e2 -= s->frame2->linesize[0];
301  }
302 
303  for (int j = 0; j < h; j++) {
304  memcpy(b2, buffer + j * w * s->bpp, w * s->bpp);
305  b2 -= s->frame2->linesize[0];
306  }
307  } else {
308  return AVERROR_INVALIDDATA;
309  }
310  }
311 
312  bytestream2_skip(gb, size - (bytestream2_tell(gb) - pos));
313 
314  return 0;
315 }
316 
317 #define NEXT_LINE \
318  if (cx >= w * s->bpp) { \
319  cx = 0; \
320  cy--; \
321  b1 -= s->frame1->linesize[0]; \
322  b2 -= s->frame2->linesize[0]; \
323  } \
324  len--;
325 
326 static int decode_dlta(AVCodecContext *avctx,
327  AVPacket *avpkt, unsigned size)
328 {
329  RASCContext *s = avctx->priv_data;
330  GetByteContext *gb = &s->gb;
332  unsigned uncompressed_size, pos;
333  unsigned x, y, w, h;
334  int ret, cx, cy, compression;
335  uint8_t *b1, *b2;
336 
337  pos = bytestream2_tell(gb);
338  bytestream2_skip(gb, 12);
339  uncompressed_size = bytestream2_get_le32(gb);
340  x = bytestream2_get_le32(gb);
341  y = bytestream2_get_le32(gb);
342  w = bytestream2_get_le32(gb);
343  h = bytestream2_get_le32(gb);
344 
345  if (x >= avctx->width || y >= avctx->height ||
346  w > avctx->width || h > avctx->height)
347  return AVERROR_INVALIDDATA;
348 
349  if (x + w > avctx->width || y + h > avctx->height)
350  return AVERROR_INVALIDDATA;
351 
352  bytestream2_skip(gb, 4);
353  compression = bytestream2_get_le32(gb);
354 
355  if (compression == 1) {
356  ret = decode_zlib(avctx, avpkt, size, uncompressed_size);
357  if (ret < 0)
358  return ret;
359  bytestream2_init(&dc, s->delta, uncompressed_size);
360  } else if (compression == 0) {
361  if (bytestream2_get_bytes_left(gb) < uncompressed_size)
362  return AVERROR_INVALIDDATA;
363  bytestream2_init(&dc, avpkt->data + bytestream2_tell(gb),
364  uncompressed_size);
365  } else if (compression == 2) {
366  avpriv_request_sample(avctx, "compression %d", compression);
367  return AVERROR_PATCHWELCOME;
368  } else {
369  return AVERROR_INVALIDDATA;
370  }
371 
372  if (!s->frame2->data[0] || !s->frame1->data[0])
373  return AVERROR_INVALIDDATA;
374 
375  b1 = s->frame1->data[0] + s->frame1->linesize[0] * (y + h - 1) + x * s->bpp;
376  b2 = s->frame2->data[0] + s->frame2->linesize[0] * (y + h - 1) + x * s->bpp;
377  cx = 0, cy = h;
378  while (bytestream2_get_bytes_left(&dc) > 0) {
379  int type = bytestream2_get_byte(&dc);
380  int len = bytestream2_get_byte(&dc);
381  unsigned fill;
382 
383  switch (type) {
384  case 1:
385  while (len > 0 && cy > 0) {
386  cx++;
387  NEXT_LINE
388  }
389  break;
390  case 2:
391  while (len > 0 && cy > 0) {
392  int v0 = b1[cx];
393  int v1 = b2[cx];
394 
395  b2[cx] = v0;
396  b1[cx] = v1;
397  cx++;
398  NEXT_LINE
399  }
400  break;
401  case 3:
402  while (len > 0 && cy > 0) {
403  fill = bytestream2_get_byte(&dc);
404  b1[cx] = b2[cx];
405  b2[cx] = fill;
406  cx++;
407  NEXT_LINE
408  }
409  break;
410  case 4:
411  fill = bytestream2_get_byte(&dc);
412  while (len > 0 && cy > 0) {
413  AV_WL32(b1 + cx, AV_RL32(b2 + cx));
414  AV_WL32(b2 + cx, fill);
415  cx++;
416  NEXT_LINE
417  }
418  break;
419  case 7:
420  fill = bytestream2_get_le32(&dc);
421  while (len > 0 && cy > 0) {
422  AV_WL32(b1 + cx, AV_RL32(b2 + cx));
423  AV_WL32(b2 + cx, fill);
424  cx += 4;
425  NEXT_LINE
426  }
427  break;
428  case 10:
429  while (len > 0 && cy > 0) {
430  cx += 4;
431  NEXT_LINE
432  }
433  break;
434  case 12:
435  while (len > 0 && cy > 0) {
436  unsigned v0, v1;
437 
438  v0 = AV_RL32(b2 + cx);
439  v1 = AV_RL32(b1 + cx);
440  AV_WL32(b2 + cx, v1);
441  AV_WL32(b1 + cx, v0);
442  cx += 4;
443  NEXT_LINE
444  }
445  break;
446  case 13:
447  while (len > 0 && cy > 0) {
448  fill = bytestream2_get_le32(&dc);
449  AV_WL32(b1 + cx, AV_RL32(b2 + cx));
450  AV_WL32(b2 + cx, fill);
451  cx += 4;
452  NEXT_LINE
453  }
454  break;
455  default:
456  avpriv_request_sample(avctx, "runlen %d", type);
457  return AVERROR_INVALIDDATA;
458  }
459  }
460 
461  bytestream2_skip(gb, size - (bytestream2_tell(gb) - pos));
462 
463  return 0;
464 }
465 
466 static int decode_kfrm(AVCodecContext *avctx,
467  AVPacket *avpkt, unsigned size)
468 {
469  RASCContext *s = avctx->priv_data;
470  GetByteContext *gb = &s->gb;
471  uint8_t *dst;
472  unsigned pos;
473  int zret, ret;
474 
475  pos = bytestream2_tell(gb);
476  if (bytestream2_peek_le32(gb) == 0x65) {
477  ret = decode_fint(avctx, avpkt, size);
478  if (ret < 0)
479  return ret;
480  }
481 
482  if (!s->frame2->data[0])
483  return AVERROR_INVALIDDATA;
484 
485  zret = inflateReset(&s->zstream);
486  if (zret != Z_OK) {
487  av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret);
488  return AVERROR_EXTERNAL;
489  }
490 
491  s->zstream.next_in = avpkt->data + bytestream2_tell(gb);
492  s->zstream.avail_in = bytestream2_get_bytes_left(gb);
493 
494  dst = s->frame2->data[0] + (avctx->height - 1) * s->frame2->linesize[0];
495  for (int i = 0; i < avctx->height; i++) {
496  s->zstream.next_out = dst;
497  s->zstream.avail_out = s->stride;
498 
499  zret = inflate(&s->zstream, Z_SYNC_FLUSH);
500  if (zret != Z_OK && zret != Z_STREAM_END) {
501  av_log(avctx, AV_LOG_ERROR,
502  "Inflate failed with return code: %d.\n", zret);
503  return AVERROR_INVALIDDATA;
504  }
505 
506  dst -= s->frame2->linesize[0];
507  }
508 
509  dst = s->frame1->data[0] + (avctx->height - 1) * s->frame1->linesize[0];
510  for (int i = 0; i < avctx->height; i++) {
511  s->zstream.next_out = dst;
512  s->zstream.avail_out = s->stride;
513 
514  zret = inflate(&s->zstream, Z_SYNC_FLUSH);
515  if (zret != Z_OK && zret != Z_STREAM_END) {
516  av_log(avctx, AV_LOG_ERROR,
517  "Inflate failed with return code: %d.\n", zret);
518  return AVERROR_INVALIDDATA;
519  }
520 
521  dst -= s->frame1->linesize[0];
522  }
523 
524  bytestream2_skip(gb, size - (bytestream2_tell(gb) - pos));
525 
526  return 0;
527 }
528 
529 static int decode_mous(AVCodecContext *avctx,
530  AVPacket *avpkt, unsigned size)
531 {
532  RASCContext *s = avctx->priv_data;
533  GetByteContext *gb = &s->gb;
534  unsigned w, h, pos, uncompressed_size;
535  int ret;
536 
537  pos = bytestream2_tell(gb);
538  bytestream2_skip(gb, 8);
539  w = bytestream2_get_le32(gb);
540  h = bytestream2_get_le32(gb);
541  bytestream2_skip(gb, 12);
542  uncompressed_size = bytestream2_get_le32(gb);
543 
544  if (w > avctx->width || h > avctx->height)
545  return AVERROR_INVALIDDATA;
546 
547  if (uncompressed_size != 3 * w * h)
548  return AVERROR_INVALIDDATA;
549 
550  av_fast_padded_malloc(&s->cursor, &s->cursor_size, uncompressed_size);
551  if (!s->cursor)
552  return AVERROR(ENOMEM);
553 
554  ret = decode_zlib(avctx, avpkt,
555  size - (bytestream2_tell(gb) - pos),
556  uncompressed_size);
557  if (ret < 0)
558  return ret;
559  memcpy(s->cursor, s->delta, uncompressed_size);
560 
561  bytestream2_skip(gb, size - (bytestream2_tell(gb) - pos));
562 
563  s->cursor_w = w;
564  s->cursor_h = h;
565 
566  return 0;
567 }
568 
569 static int decode_mpos(AVCodecContext *avctx,
570  AVPacket *avpkt, unsigned size)
571 {
572  RASCContext *s = avctx->priv_data;
573  GetByteContext *gb = &s->gb;
574  unsigned pos;
575 
576  pos = bytestream2_tell(gb);
577  bytestream2_skip(gb, 8);
578  s->cursor_x = bytestream2_get_le32(gb);
579  s->cursor_y = bytestream2_get_le32(gb);
580 
581  bytestream2_skip(gb, size - (bytestream2_tell(gb) - pos));
582 
583  return 0;
584 }
585 
586 static void draw_cursor(AVCodecContext *avctx)
587 {
588  RASCContext *s = avctx->priv_data;
589  uint8_t *dst, *pal;
590 
591  if (!s->cursor)
592  return;
593 
594  if (s->cursor_x >= avctx->width || s->cursor_y >= avctx->height)
595  return;
596 
597  if (s->cursor_x + s->cursor_w > avctx->width ||
598  s->cursor_y + s->cursor_h > avctx->height)
599  return;
600 
601  if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
602  pal = s->frame->data[1];
603  for (int i = 0; i < s->cursor_h; i++) {
604  for (int j = 0; j < s->cursor_w; j++) {
605  int cr = s->cursor[3 * s->cursor_w * (s->cursor_h - i - 1) + 3 * j + 0];
606  int cg = s->cursor[3 * s->cursor_w * (s->cursor_h - i - 1) + 3 * j + 1];
607  int cb = s->cursor[3 * s->cursor_w * (s->cursor_h - i - 1) + 3 * j + 2];
608  int best = INT_MAX;
609  int index = 0;
610  int dist;
611 
612  if (cr == s->cursor[0] && cg == s->cursor[1] && cb == s->cursor[2])
613  continue;
614 
615  dst = s->frame->data[0] + s->frame->linesize[0] * (s->cursor_y + i) + (s->cursor_x + j);
616  for (int k = 0; k < 256; k++) {
617  int pr = pal[k * 4 + 0];
618  int pg = pal[k * 4 + 1];
619  int pb = pal[k * 4 + 2];
620 
621  dist = FFABS(cr - pr) + FFABS(cg - pg) + FFABS(cb - pb);
622  if (dist < best) {
623  best = dist;
624  index = k;
625  }
626  }
627  dst[0] = index;
628  }
629  }
630  } else if (avctx->pix_fmt == AV_PIX_FMT_RGB555LE) {
631  for (int i = 0; i < s->cursor_h; i++) {
632  for (int j = 0; j < s->cursor_w; j++) {
633  int cr = s->cursor[3 * s->cursor_w * (s->cursor_h - i - 1) + 3 * j + 0];
634  int cg = s->cursor[3 * s->cursor_w * (s->cursor_h - i - 1) + 3 * j + 1];
635  int cb = s->cursor[3 * s->cursor_w * (s->cursor_h - i - 1) + 3 * j + 2];
636 
637  if (cr == s->cursor[0] && cg == s->cursor[1] && cb == s->cursor[2])
638  continue;
639 
640  cr >>= 3; cg >>=3; cb >>= 3;
641  dst = s->frame->data[0] + s->frame->linesize[0] * (s->cursor_y + i) + 2 * (s->cursor_x + j);
642  AV_WL16(dst, cr | cg << 5 | cb << 10);
643  }
644  }
645  } else if (avctx->pix_fmt == AV_PIX_FMT_BGR0) {
646  for (int i = 0; i < s->cursor_h; i++) {
647  for (int j = 0; j < s->cursor_w; j++) {
648  int cr = s->cursor[3 * s->cursor_w * (s->cursor_h - i - 1) + 3 * j + 0];
649  int cg = s->cursor[3 * s->cursor_w * (s->cursor_h - i - 1) + 3 * j + 1];
650  int cb = s->cursor[3 * s->cursor_w * (s->cursor_h - i - 1) + 3 * j + 2];
651 
652  if (cr == s->cursor[0] && cg == s->cursor[1] && cb == s->cursor[2])
653  continue;
654 
655  dst = s->frame->data[0] + s->frame->linesize[0] * (s->cursor_y + i) + 4 * (s->cursor_x + j);
656  dst[0] = cb;
657  dst[1] = cg;
658  dst[2] = cr;
659  }
660  }
661  }
662 }
663 
664 static int decode_frame(AVCodecContext *avctx,
665  void *data, int *got_frame,
666  AVPacket *avpkt)
667 {
668  RASCContext *s = avctx->priv_data;
669  GetByteContext *gb = &s->gb;
670  int ret, intra = 0;
671  AVFrame *frame = data;
672 
673  bytestream2_init(gb, avpkt->data, avpkt->size);
674 
675  if (bytestream2_peek_le32(gb) == EMPT)
676  return avpkt->size;
677 
678  s->frame = frame;
679 
680  while (bytestream2_get_bytes_left(gb) > 0) {
681  unsigned type, size = 0;
682 
683  type = bytestream2_get_le32(gb);
684  if (type == KBND || type == BNDL) {
685  intra = type == KBND;
686  type = bytestream2_get_le32(gb);
687  }
688 
689  size = bytestream2_get_le32(gb);
690  if (bytestream2_get_bytes_left(gb) < size)
691  return AVERROR_INVALIDDATA;
692 
693  switch (type) {
694  case FINT:
695  case INIT:
696  ret = decode_fint(avctx, avpkt, size);
697  break;
698  case KFRM:
699  ret = decode_kfrm(avctx, avpkt, size);
700  break;
701  case DLTA:
702  ret = decode_dlta(avctx, avpkt, size);
703  break;
704  case MOVE:
705  ret = decode_move(avctx, avpkt, size);
706  break;
707  case MOUS:
708  ret = decode_mous(avctx, avpkt, size);
709  break;
710  case MPOS:
711  ret = decode_mpos(avctx, avpkt, size);
712  break;
713  default:
714  bytestream2_skip(gb, size);
715  }
716 
717  if (ret < 0)
718  return ret;
719  }
720 
721  if ((ret = ff_get_buffer(avctx, s->frame, 0)) < 0)
722  return ret;
723 
724  if (!s->frame2->data[0] || !s->frame1->data[0])
725  return AVERROR_INVALIDDATA;
726 
727  copy_plane(avctx, s->frame2, s->frame);
728  if (avctx->pix_fmt == AV_PIX_FMT_PAL8)
729  memcpy(s->frame->data[1], s->frame2->data[1], 1024);
730  if (!s->skip_cursor)
731  draw_cursor(avctx);
732 
733  s->frame->key_frame = intra;
735 
736  *got_frame = 1;
737 
738  return avpkt->size;
739 }
740 
742 {
743  RASCContext *s = avctx->priv_data;
744  int zret;
745 
746  s->zstream.zalloc = Z_NULL;
747  s->zstream.zfree = Z_NULL;
748  s->zstream.opaque = Z_NULL;
749  zret = inflateInit(&s->zstream);
750  if (zret != Z_OK) {
751  av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret);
752  return AVERROR_EXTERNAL;
753  }
754 
755  s->frame1 = av_frame_alloc();
756  s->frame2 = av_frame_alloc();
757  if (!s->frame1 || !s->frame2)
758  return AVERROR(ENOMEM);
759 
760  return 0;
761 }
762 
764 {
765  RASCContext *s = avctx->priv_data;
766 
767  av_freep(&s->cursor);
768  s->cursor_size = 0;
769  av_freep(&s->delta);
770  s->delta_size = 0;
771  av_frame_free(&s->frame1);
772  av_frame_free(&s->frame2);
773  inflateEnd(&s->zstream);
774 
775  return 0;
776 }
777 
778 static void decode_flush(AVCodecContext *avctx)
779 {
780  RASCContext *s = avctx->priv_data;
781 
782  clear_plane(avctx, s->frame1);
783  clear_plane(avctx, s->frame2);
784 }
785 
786 static const AVOption options[] = {
787 { "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 },
788 { NULL },
789 };
790 
791 static const AVClass rasc_decoder_class = {
792  .class_name = "rasc decoder",
793  .item_name = av_default_item_name,
794  .option = options,
795  .version = LIBAVUTIL_VERSION_INT,
796 };
797 
799  .name = "rasc",
800  .long_name = NULL_IF_CONFIG_SMALL("RemotelyAnywhere Screen Capture"),
801  .type = AVMEDIA_TYPE_VIDEO,
802  .id = AV_CODEC_ID_RASC,
803  .priv_data_size = sizeof(RASCContext),
804  .init = decode_init,
805  .close = decode_close,
806  .decode = decode_frame,
807  .flush = decode_flush,
808  .capabilities = AV_CODEC_CAP_DR1,
809  .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |
811  .priv_class = &rasc_decoder_class,
812 };
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
Definition: internal.h:48
#define EMPT
Definition: rasc.c:46
#define NULL
Definition: coverity.c:32
static void draw_cursor(AVCodecContext *avctx)
Definition: rasc.c:586
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
This structure describes decoded (raw) audio or video data.
Definition: frame.h:226
static av_cold int decode_close(AVCodecContext *avctx)
Definition: rasc.c:763
AVOption.
Definition: opt.h:246
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:101
static void flush(AVCodecContext *avctx)
const char * fmt
Definition: avisynth_c.h:769
misc image utilities
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
int ff_set_dimensions(AVCodecContext *s, int width, int height)
Check that the provided frame dimensions are valid and set them on the codec context.
Definition: utils.c:104
static const AVClass rasc_decoder_class
Definition: rasc.c:791
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
unsigned cursor_y
Definition: rasc.c:59
packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefined ...
Definition: pixfmt.h:108
int size
Definition: avcodec.h:1446
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:191
uint8_t * delta
Definition: rasc.c:52
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:1743
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:133
void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size)
Same behaviour av_fast_malloc but the buffer has additional AV_INPUT_BUFFER_PADDING_SIZE at the end w...
Definition: utils.c:70
GLfloat v0
Definition: opengl_enc.c:107
#define src
Definition: vp8dsp.c:254
static int decode_dlta(AVCodecContext *avctx, AVPacket *avpkt, unsigned size)
Definition: rasc.c:326
AVCodec.
Definition: avcodec.h:3424
static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: rasc.c:664
static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame, FILE *outfile)
Definition: decode_audio.c:42
AVCodec ff_rasc_decoder
Definition: rasc.c:798
#define INIT
Definition: rasc.c:39
#define MOVE
Definition: rasc.c:45
BYTE int const BYTE * srcp
Definition: avisynth_c.h:813
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:72
static void clear_plane(AVCodecContext *avctx, AVFrame *frame)
Definition: rasc.c:68
static double cb(void *priv, double x, double y)
Definition: vf_geq.c:112
void void avpriv_request_sample(void *avc, const char *msg,...) av_printf_format(2
Log a generic warning message about a missing feature.
#define KBND
Definition: rasc.c:37
#define FF_CODEC_CAP_INIT_THREADSAFE
The codec does not modify any global variables in the init function, allowing to call the init functi...
Definition: internal.h:40
uint8_t
#define av_cold
Definition: attributes.h:82
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:189
8 bits with AV_PIX_FMT_RGB32 palette
Definition: pixfmt.h:77
AVOptions.
unsigned cursor_w
Definition: rasc.c:56
#define u(width, name, range_min, range_max)
Definition: cbs_h2645.c:253
static AVFrame * frame
int cursor_size
Definition: rasc.c:55
uint8_t * data
Definition: avcodec.h:1445
static void inflate(uint8_t *dst, const uint8_t *p1, int width, int threshold, const uint8_t *coordinates[], int coord)
Definition: vf_neighbor.c:189
static av_cold int decode_init(AVCodecContext *avctx)
Definition: rasc.c:741
int stride
Definition: rasc.c:60
ptrdiff_t size
Definition: opengl_enc.c:101
#define MPOS
Definition: rasc.c:44
#define BNDL
Definition: rasc.c:40
#define FFALIGN(x, a)
Definition: macros.h:48
#define av_log(a,...)
uint8_t * cursor
Definition: rasc.c:54
#define KFRM
Definition: rasc.c:41
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
AVFrame * frame1
Definition: rasc.c:64
unsigned cursor_x
Definition: rasc.c:58
#define DLTA
Definition: rasc.c:42
BYTE * dstp
Definition: avisynth_c.h:813
#define AVERROR(e)
Definition: error.h:43
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:164
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:202
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
int bpp
Definition: rasc.c:61
static av_always_inline unsigned int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:154
#define NEXT_LINE
Definition: rasc.c:317
simple assert() macros that are a bit more flexible than ISO C assert().
static int decode_kfrm(AVCodecContext *avctx, AVPacket *avpkt, unsigned size)
Definition: rasc.c:466
const char * name
Name of the codec implementation.
Definition: avcodec.h:3431
enum AVPictureType pict_type
Picture type of the frame.
Definition: frame.h:309
int skip_cursor
Definition: rasc.c:50
#define FFMIN(a, b)
Definition: common.h:96
int width
picture width / height.
Definition: avcodec.h:1706
uint8_t w
Definition: llviddspenc.c:38
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:72
#define s(width, name)
Definition: cbs_vp9.c:257
static int decode_zlib(AVCodecContext *avctx, AVPacket *avpkt, unsigned size, unsigned uncompressed_size)
Definition: rasc.c:169
#define mc
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
static av_always_inline int bytestream2_tell(GetByteContext *g)
Definition: bytestream.h:188
Libavcodec external API header.
static int decode_move(AVCodecContext *avctx, AVPacket *avpkt, unsigned size)
Definition: rasc.c:202
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:257
#define AV_OPT_FLAG_VIDEO_PARAM
Definition: opt.h:279
main external API structure.
Definition: avcodec.h:1533
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1918
GLint GLenum type
Definition: opengl_enc.c:105
static void copy_plane(AVCodecContext *avctx, AVFrame *src, AVFrame *dst)
Definition: rasc.c:79
Describe the class of an AVClass context structure.
Definition: log.h:67
int index
Definition: gxfenc.c:89
#define AV_OPT_FLAG_DECODING_PARAM
a generic parameter which can be set by the user for demuxing or decoding
Definition: opt.h:277
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition: pixfmt.h:240
static int init_frames(AVCodecContext *avctx)
Definition: rasc.c:92
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition: frame.c:553
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:240
static void decode_flush(AVCodecContext *avctx)
Definition: rasc.c:778
static int decode_mous(AVCodecContext *avctx, AVPacket *avpkt, unsigned size)
Definition: rasc.c:529
static int decode_fint(AVCodecContext *avctx, AVPacket *avpkt, unsigned size)
Definition: rasc.c:111
common internal api header.
if(ret< 0)
Definition: vf_mcdeint.c:279
#define AV_WL16(p, v)
Definition: intreadwrite.h:412
#define FINT
Definition: rasc.c:38
AVFrame * frame2
Definition: rasc.c:65
void * priv_data
Definition: avcodec.h:1560
static const AVOption options[]
Definition: rasc.c:786
int len
unsigned cursor_h
Definition: rasc.c:57
int key_frame
1 -> keyframe, 0-> not
Definition: frame.h:304
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(constint16_t *) pi >>8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(constint32_t *) pi >>24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(constfloat *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(constfloat *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(constfloat *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(constdouble *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(constdouble *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(constdouble *) pi *(1U<< 31))))#defineSET_CONV_FUNC_GROUP(ofmt, ifmt) staticvoidset_generic_function(AudioConvert *ac){}voidff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enumAVSampleFormatout_fmt, enumAVSampleFormatin_fmt, intchannels, intsample_rate, intapply_map){AudioConvert *ac;intin_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) returnNULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt)>2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);returnNULL;}returnac;}in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}elseif(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;elseac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);returnac;}intff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){intuse_generic=1;intlen=in->nb_samples;intp;if(ac->dc){av_log(ac->avr, AV_LOG_TRACE,"%dsamples-audio_convert:%sto%s(dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));returnff_convert_dither(ac-> dc
static int decode_mpos(AVCodecContext *avctx, AVPacket *avpkt, unsigned size)
Definition: rasc.c:569
z_stream zstream
Definition: rasc.c:62
#define av_freep(p)
static double cr(void *priv, double x, double y)
Definition: vf_geq.c:113
int delta_size
Definition: rasc.c:53
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:57
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Definition: bytestream.h:87
This structure stores compressed data.
Definition: avcodec.h:1422
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
Definition: avcodec.h:968
GetByteContext gb
Definition: rasc.c:51
for(j=16;j >0;--j)
Predicted.
Definition: avutil.h:275
GLuint buffer
Definition: opengl_enc.c:102
#define AV_WL32(p, v)
Definition: intreadwrite.h:426
AVFrame * frame
Definition: rasc.c:63
#define MOUS
Definition: rasc.c:43