History

avcodec: add RemotelyAnywhere Screen Capture decoder

Paul B Mahol committed 8 years ago

Commit a5278b61 parent af71a3f9 files · +827 −2Browse files

Unified · Split

9 files
  1. Changelog +1 −0
  2. configure +1 −0
  3. libavcodec/Makefile +1 −0
  4. libavcodec/allcodecs.c +1 −0
  5. libavcodec/avcodec.h +1 −0
  6. libavcodec/codec_desc.c +7 −0
  7. libavcodec/rasc.c +812 −0
  8. libavcodec/version.h +2 −2
  9. libavformat/riff.c +1 −0
Changelog+1−0
@@ -22,6 +22,7 @@ version <next>: · 21 unmodified lines
2222 - MatchWare Screen Capture Codec decoder
2323 - WinCam Motion Video decoder
2424 - 1D LUT filter (lut1d)
25+- RemotelyAnywhere Screen Capture decoder
2526
2627
2728 version 4.0:
configure+1−0
@@ -2719,6 +2719,7 @@ qdm2_decoder_select="mdct rdft mpegaudiodsp" · 2718 unmodified lines
27192719 ra_144_decoder_select="audiodsp"
27202720 ra_144_encoder_select="audio_frame_queue lpc audiodsp"
27212721 ralf_decoder_select="golomb"
2722+rasc_decoder_deps="zlib"
27222723 rawvideo_decoder_select="bswapdsp"
27232724 rscc_decoder_deps="zlib"
27242725 rtjpeg_decoder_select="me_cmp"
libavcodec/Makefile+1−0
@@ -536,6 +536,7 @@ OBJS-$(CONFIG_RA_144_DECODER) += ra144dec.o ra144.o celp_filters.o · 535 unmodified lines
536536 OBJS-$(CONFIG_RA_144_ENCODER) += ra144enc.o ra144.o celp_filters.o
537537 OBJS-$(CONFIG_RA_288_DECODER) += ra288.o celp_filters.o
538538 OBJS-$(CONFIG_RALF_DECODER) += ralf.o
539+OBJS-$(CONFIG_RASC_DECODER) += rasc.o
539540 OBJS-$(CONFIG_RAWVIDEO_DECODER) += rawdec.o
540541 OBJS-$(CONFIG_RAWVIDEO_ENCODER) += rawenc.o
541542 OBJS-$(CONFIG_REALTEXT_DECODER) += realtextdec.o ass.o
libavcodec/allcodecs.c+1−0
@@ -248,6 +248,7 @@ extern AVCodec ff_r10k_encoder; · 247 unmodified lines
248248 extern AVCodec ff_r10k_decoder;
249249 extern AVCodec ff_r210_encoder;
250250 extern AVCodec ff_r210_decoder;
251+extern AVCodec ff_rasc_decoder;
251252 extern AVCodec ff_rawvideo_encoder;
252253 extern AVCodec ff_rawvideo_decoder;
253254 extern AVCodec ff_rl2_decoder;
libavcodec/avcodec.h+1−0
@@ -451,6 +451,7 @@ enum AVCodecID { · 450 unmodified lines
451451 AV_CODEC_ID_PROSUMER,
452452 AV_CODEC_ID_MWSC,
453453 AV_CODEC_ID_WCMV,
454+ AV_CODEC_ID_RASC,
454455
455456 /* various PCM "codecs" */
456457 AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs
libavcodec/codec_desc.c+7−0
@@ -1682,6 +1682,13 @@ static const AVCodecDescriptor codec_descriptors[] = { · 1681 unmodified lines
16821682 .long_name = NULL_IF_CONFIG_SMALL("WinCAM Motion Video"),
16831683 .props = AV_CODEC_PROP_LOSSLESS,
16841684 },
1685+ {
1686+ .id = AV_CODEC_ID_RASC,
1687+ .type = AVMEDIA_TYPE_VIDEO,
1688+ .name = "rasc",
1689+ .long_name = NULL_IF_CONFIG_SMALL("RemotelyAnywhere Screen Capture"),
1690+ .props = AV_CODEC_PROP_LOSSY,
1691+ },
16851692
16861693 /* various PCM "codecs" */
16871694 {
libavcodec/rasc.c+812−0
@@ -0,0 +1,812 @@
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;
50+ int skip_cursor;
51+ GetByteContext gb;
52+ uint8_t *delta;
53+ int delta_size;
54+ uint8_t *cursor;
55+ int cursor_size;
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;
63+ AVFrame *frame;
64+ AVFrame *frame1;
65+ AVFrame *frame2;
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+
97+ av_frame_unref(s->frame1);
98+ if ((ret = ff_get_buffer(avctx, s->frame1, 0)) < 0)
99+ return ret;
100+
101+ av_frame_unref(s->frame2);
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;
207+ GetByteContext mc;
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),
232+ bytestream2_get_bytes_left(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) + start_x * s->bpp;
276+ b2 = s->frame2->data[0] + s->frame2->linesize[0] * (start_y + h) + start_x * s->bpp;
277+ e2 = s->frame2->data[0] + s->frame2->linesize[0] * (mov_y + h) + 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;
331+ GetByteContext dc;
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;
734+ s->frame->pict_type = intra ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
735+
736+ *got_frame = 1;
737+
738+ return avpkt->size;
739+}
740+
741+static av_cold int decode_init(AVCodecContext *avctx)
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+
763+static av_cold int decode_close(AVCodecContext *avctx)
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+
798+AVCodec ff_rasc_decoder = {
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 |
810+ FF_CODEC_CAP_INIT_CLEANUP,
811+ .priv_class = &rasc_decoder_class,
812+};
libavcodec/version.h+2−2
@@ -28,8 +28,8 @@ · 27 unmodified lines
2828 #include "libavutil/version.h"
2929
3030 #define LIBAVCODEC_VERSION_MAJOR 58
31−#define LIBAVCODEC_VERSION_MINOR 27
32−#define LIBAVCODEC_VERSION_MICRO 101
31+#define LIBAVCODEC_VERSION_MINOR 28
32+#define LIBAVCODEC_VERSION_MICRO 100
3333
3434 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
3535 LIBAVCODEC_VERSION_MINOR, \
libavformat/riff.c+1−0
@@ -474,6 +474,7 @@ const AVCodecTag ff_codec_bmp_tags[] = { · 473 unmodified lines
474474 { AV_CODEC_ID_PROSUMER, MKTAG('B', 'T', '2', '0') },
475475 { AV_CODEC_ID_MWSC, MKTAG('M', 'W', 'S', 'C') },
476476 { AV_CODEC_ID_WCMV, MKTAG('W', 'C', 'M', 'V') },
477+ { AV_CODEC_ID_RASC, MKTAG('R', 'A', 'S', 'C') },
477478 { AV_CODEC_ID_NONE, 0 }
478479 };
479480

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t