1 /*
2 * FM Screen Capture Codec decoder
3 *
4 * Copyright (c) 2017 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 "avcodec.h"
28 #include "bytestream.h"
29 #include "codec_internal.h"
30 #include "internal.h"
31
32 #define BLOCK_HEIGHT 112u
33 #define BLOCK_WIDTH 84u
34
35 typedef struct InterBlock {
36 int w, h;
37 int size;
38 int xor;
39 } InterBlock;
40
41 typedef struct FMVCContext {
42 GetByteContext gb;
43 PutByteContext pb;
44 uint8_t *buffer;
45 size_t buffer_size;
46 uint8_t *pbuffer;
47 size_t pbuffer_size;
48 ptrdiff_t stride;
49 int bpp;
50 int yb, xb;
51 InterBlock *blocks;
52 unsigned nb_blocks;
53 } FMVCContext;
54
decode_type2(GetByteContext *gb, PutByteContext *pb)55 static int decode_type2(GetByteContext *gb, PutByteContext *pb)
56 {
57 unsigned repeat = 0, first = 1, opcode = 0;
58 int i, len, pos;
59
60 while (bytestream2_get_bytes_left(gb) > 0) {
61 GetByteContext gbc;
62
63 while (bytestream2_get_bytes_left(gb) > 0) {
64 if (first) {
65 first = 0;
66 if (bytestream2_peek_byte(gb) > 17) {
67 len = bytestream2_get_byte(gb) - 17;
68 if (len < 4) {
69 do {
70 bytestream2_put_byte(pb, bytestream2_get_byte(gb));
71 --len;
72 } while (len);
73 opcode = bytestream2_peek_byte(gb);
74 continue;
75 } else {
76 do {
77 bytestream2_put_byte(pb, bytestream2_get_byte(gb));
78 --len;
79 } while (len);
80 opcode = bytestream2_peek_byte(gb);
81 if (opcode < 0x10) {
82 bytestream2_skip(gb, 1);
83 pos = - (opcode >> 2) - 4 * bytestream2_get_byte(gb) - 2049;
84
85 bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
86 bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
87
88 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
89 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
90 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
91 len = opcode & 3;
92 if (!len) {
93 repeat = 1;
94 } else {
95 do {
96 bytestream2_put_byte(pb, bytestream2_get_byte(gb));
97 --len;
98 } while (len);
99 opcode = bytestream2_peek_byte(gb);
100 }
101 continue;
102 }
103 }
104 repeat = 0;
105 }
106 repeat = 1;
107 }
108 if (repeat) {
109 repeat = 0;
110 opcode = bytestream2_peek_byte(gb);
111 if (opcode < 0x10) {
112 bytestream2_skip(gb, 1);
113 if (!opcode) {
114 if (!bytestream2_peek_byte(gb)) {
115 do {
116 bytestream2_skip(gb, 1);
117 opcode += 255;
118 } while (!bytestream2_peek_byte(gb) && bytestream2_get_bytes_left(gb) > 0);
119 }
120 opcode += bytestream2_get_byte(gb) + 15;
121 }
122 bytestream2_put_le32(pb, bytestream2_get_le32(gb));
123 for (i = opcode - 1; i > 0; --i)
124 bytestream2_put_byte(pb, bytestream2_get_byte(gb));
125 opcode = bytestream2_peek_byte(gb);
126 if (opcode < 0x10) {
127 bytestream2_skip(gb, 1);
128 pos = - (opcode >> 2) - 4 * bytestream2_get_byte(gb) - 2049;
129
130 bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
131 bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
132
133 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
134 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
135 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
136 len = opcode & 3;
137 if (!len) {
138 repeat = 1;
139 } else {
140 do {
141 bytestream2_put_byte(pb, bytestream2_get_byte(gb));
142 --len;
143 } while (len);
144 opcode = bytestream2_peek_byte(gb);
145 }
146 continue;
147 }
148 }
149 }
150
151 if (opcode >= 0x40) {
152 bytestream2_skip(gb, 1);
153 pos = - ((opcode >> 2) & 7) - 1 - 8 * bytestream2_get_byte(gb);
154 len = (opcode >> 5) - 1;
155
156 bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
157 bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
158
159 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
160 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
161 do {
162 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
163 --len;
164 } while (len);
165
166 len = opcode & 3;
167
168 if (!len) {
169 repeat = 1;
170 } else {
171 do {
172 bytestream2_put_byte(pb, bytestream2_get_byte(gb));
173 --len;
174 } while (len);
175 opcode = bytestream2_peek_byte(gb);
176 }
177 continue;
178 } else if (opcode < 0x20) {
179 break;
180 }
181 len = opcode & 0x1F;
182 bytestream2_skip(gb, 1);
183 if (!len) {
184 if (!bytestream2_peek_byte(gb)) {
185 do {
186 bytestream2_skip(gb, 1);
187 len += 255;
188 } while (!bytestream2_peek_byte(gb) && bytestream2_get_bytes_left(gb) > 0);
189 }
190 len += bytestream2_get_byte(gb) + 31;
191 }
192 i = bytestream2_get_le16(gb);
193 pos = - (i >> 2) - 1;
194
195 bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
196 bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
197
198 if (len < 6 || bytestream2_tell_p(pb) - bytestream2_tell(&gbc) < 4) {
199 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
200 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
201 do {
202 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
203 --len;
204 } while (len);
205 } else {
206 bytestream2_put_le32(pb, bytestream2_get_le32(&gbc));
207 for (len = len - 2; len; --len)
208 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
209 }
210 len = i & 3;
211 if (!len) {
212 repeat = 1;
213 } else {
214 do {
215 bytestream2_put_byte(pb, bytestream2_get_byte(gb));
216 --len;
217 } while (len);
218 opcode = bytestream2_peek_byte(gb);
219 }
220 }
221 bytestream2_skip(gb, 1);
222 if (opcode < 0x10) {
223 pos = -(opcode >> 2) - 1 - 4 * bytestream2_get_byte(gb);
224
225 bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
226 bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
227
228 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
229 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
230 len = opcode & 3;
231 if (!len) {
232 repeat = 1;
233 } else {
234 do {
235 bytestream2_put_byte(pb, bytestream2_get_byte(gb));
236 --len;
237 } while (len);
238 opcode = bytestream2_peek_byte(gb);
239 }
240 continue;
241 }
242 len = opcode & 7;
243 if (!len) {
244 if (!bytestream2_peek_byte(gb)) {
245 do {
246 bytestream2_skip(gb, 1);
247 len += 255;
248 } while (!bytestream2_peek_byte(gb) && bytestream2_get_bytes_left(gb) > 0);
249 }
250 len += bytestream2_get_byte(gb) + 7;
251 }
252 i = bytestream2_get_le16(gb);
253 pos = bytestream2_tell_p(pb) - 2048 * (opcode & 8);
254 pos = pos - (i >> 2);
255 if (pos == bytestream2_tell_p(pb))
256 break;
257
258 pos = pos - 0x4000;
259 bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
260 bytestream2_seek(&gbc, pos, SEEK_SET);
261
262 if (len < 6 || bytestream2_tell_p(pb) - bytestream2_tell(&gbc) < 4) {
263 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
264 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
265 do {
266 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
267 --len;
268 } while (len);
269 } else {
270 bytestream2_put_le32(pb, bytestream2_get_le32(&gbc));
271 for (len = len - 2; len; --len)
272 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
273 }
274
275 len = i & 3;
276 if (!len) {
277 repeat = 1;
278 } else {
279 do {
280 bytestream2_put_byte(pb, bytestream2_get_byte(gb));
281 --len;
282 } while (len);
283 opcode = bytestream2_peek_byte(gb);
284 }
285 }
286
287 return 0;
288 }
289
decode_type1(GetByteContext *gb, PutByteContext *pb)290 static int decode_type1(GetByteContext *gb, PutByteContext *pb)
291 {
292 unsigned opcode = 0, len;
293 int high = 0;
294 int i, pos;
295
296 while (bytestream2_get_bytes_left(gb) > 0) {
297 GetByteContext gbc;
298
299 while (bytestream2_get_bytes_left(gb) > 0) {
300 while (bytestream2_get_bytes_left(gb) > 0) {
301 opcode = bytestream2_get_byte(gb);
302 high = opcode >= 0x20;
303 if (high)
304 break;
305 if (opcode)
306 break;
307 opcode = bytestream2_get_byte(gb);
308 if (opcode < 0xF8) {
309 opcode += 32;
310 break;
311 }
312 i = opcode - 0xF8;
313 if (i) {
314 len = 256;
315 do {
316 len *= 2;
317 --i;
318 } while (i);
319 } else {
320 len = 280;
321 }
322 do {
323 bytestream2_put_le32(pb, bytestream2_get_le32(gb));
324 bytestream2_put_le32(pb, bytestream2_get_le32(gb));
325 len -= 8;
326 } while (len && bytestream2_get_bytes_left(gb) > 0);
327 }
328
329 if (!high) {
330 do {
331 bytestream2_put_byte(pb, bytestream2_get_byte(gb));
332 --opcode;
333 } while (opcode && bytestream2_get_bytes_left(gb) > 0);
334
335 while (bytestream2_get_bytes_left(gb) > 0) {
336 GetByteContext gbc;
337
338 opcode = bytestream2_get_byte(gb);
339 if (opcode >= 0x20)
340 break;
341 bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
342
343 pos = -(opcode | 32 * bytestream2_get_byte(gb)) - 1;
344 bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
345 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
346 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
347 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
348 bytestream2_put_byte(pb, bytestream2_get_byte(gb));
349 }
350 }
351 high = 0;
352 if (opcode < 0x40)
353 break;
354 bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
355 pos = (-((opcode & 0x1F) | 32 * bytestream2_get_byte(gb)) - 1);
356 bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
357 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
358 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
359 len = (opcode >> 5) - 1;
360 do {
361 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
362 --len;
363 } while (len && bytestream2_get_bytes_left(&gbc) > 0);
364 }
365 len = opcode & 0x1F;
366 if (!len) {
367 if (!bytestream2_peek_byte(gb)) {
368 do {
369 bytestream2_skip(gb, 1);
370 len += 255;
371 } while (!bytestream2_peek_byte(gb) && bytestream2_get_bytes_left(gb) > 0);
372 }
373 len += bytestream2_get_byte(gb) + 31;
374 }
375 pos = -bytestream2_get_byte(gb);
376 bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
377 bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos - (bytestream2_get_byte(gb) << 8), SEEK_SET);
378 if (bytestream2_tell_p(pb) == bytestream2_tell(&gbc))
379 break;
380 if (len < 5 || bytestream2_tell_p(pb) - bytestream2_tell(&gbc) < 4) {
381 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
382 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
383 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
384 } else {
385 bytestream2_put_le32(pb, bytestream2_get_le32(&gbc));
386 len--;
387 }
388 do {
389 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
390 len--;
391 } while (len && bytestream2_get_bytes_left(&gbc) > 0);
392 }
393
394 return 0;
395 }
396
decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt)397 static int decode_frame(AVCodecContext *avctx, AVFrame *frame,
398 int *got_frame, AVPacket *avpkt)
399 {
400 FMVCContext *s = avctx->priv_data;
401 GetByteContext *gb = &s->gb;
402 PutByteContext *pb = &s->pb;
403 int ret, y, x;
404 int key_frame;
405
406 if (avpkt->size < 8)
407 return AVERROR_INVALIDDATA;
408
409 bytestream2_init(gb, avpkt->data, avpkt->size);
410 bytestream2_skip(gb, 2);
411
412 key_frame = !!bytestream2_get_le16(gb);
413
414 if (key_frame) {
415 const uint8_t *src;
416 unsigned type, size;
417 uint8_t *dst;
418
419 type = bytestream2_get_le16(gb);
420 size = bytestream2_get_le16(gb);
421 if (size > bytestream2_get_bytes_left(gb))
422 return AVERROR_INVALIDDATA;
423
424 bytestream2_init_writer(pb, s->buffer, s->buffer_size);
425 if (type == 1) {
426 decode_type1(gb, pb);
427 } else if (type == 2){
428 decode_type2(gb, pb);
429 } else {
430 avpriv_report_missing_feature(avctx, "Compression type %d", type);
431 return AVERROR_PATCHWELCOME;
432 }
433
434 if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
435 return ret;
436
437 frame->key_frame = 1;
438 frame->pict_type = AV_PICTURE_TYPE_I;
439
440 src = s->buffer;
441 dst = frame->data[0] + (avctx->height - 1) * frame->linesize[0];
442 for (y = 0; y < avctx->height; y++) {
443 memcpy(dst, src, avctx->width * s->bpp);
444 dst -= frame->linesize[0];
445 src += s->stride * 4;
446 if (bytestream2_tell_p(pb) < y*s->stride * 4)
447 break;
448 }
449 } else {
450 unsigned block, nb_blocks;
451 int type, k, l;
452 uint8_t *ssrc, *ddst;
453 const uint32_t *src;
454 uint32_t *dst;
455
456 for (block = 0; block < s->nb_blocks; block++)
457 s->blocks[block].xor = 0;
458
459 nb_blocks = bytestream2_get_le16(gb);
460 if (nb_blocks > s->nb_blocks)
461 return AVERROR_INVALIDDATA;
462
463 bytestream2_init_writer(pb, s->pbuffer, s->pbuffer_size);
464
465 type = bytestream2_get_le16(gb);
466 for (block = 0; block < nb_blocks; block++) {
467 unsigned size, offset;
468 int start = 0;
469
470 offset = bytestream2_get_le16(gb);
471 if (offset >= s->nb_blocks)
472 return AVERROR_INVALIDDATA;
473
474 size = bytestream2_get_le16(gb);
475 if (size > bytestream2_get_bytes_left(gb))
476 return AVERROR_INVALIDDATA;
477
478 start = bytestream2_tell_p(pb);
479 if (type == 1) {
480 decode_type1(gb, pb);
481 } else if (type == 2){
482 decode_type2(gb, pb);
483 } else {
484 avpriv_report_missing_feature(avctx, "Compression type %d", type);
485 return AVERROR_PATCHWELCOME;
486 }
487
488 if (s->blocks[offset].size * 4 != bytestream2_tell_p(pb) - start)
489 return AVERROR_INVALIDDATA;
490
491 s->blocks[offset].xor = 1;
492 }
493
494 src = (const uint32_t *)s->pbuffer;
495 dst = (uint32_t *)s->buffer;
496
497 for (block = 0, y = 0; y < s->yb; y++) {
498 int block_h = s->blocks[block].h;
499 uint32_t *rect = dst;
500
501 for (x = 0; x < s->xb; x++) {
502 int block_w = s->blocks[block].w;
503 uint32_t *row = dst;
504
505 block_h = s->blocks[block].h;
506 if (s->blocks[block].xor) {
507 for (k = 0; k < block_h; k++) {
508 uint32_t *column = dst;
509 for (l = 0; l < block_w; l++)
510 *dst++ ^= *src++;
511 dst = &column[s->stride];
512 }
513 }
514 dst = &row[block_w];
515 ++block;
516 }
517 dst = &rect[block_h * s->stride];
518 }
519
520 if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
521 return ret;
522
523 frame->key_frame = 0;
524 frame->pict_type = AV_PICTURE_TYPE_P;
525
526 ssrc = s->buffer;
527 ddst = frame->data[0] + (avctx->height - 1) * frame->linesize[0];
528 for (y = 0; y < avctx->height; y++) {
529 memcpy(ddst, ssrc, avctx->width * s->bpp);
530 ddst -= frame->linesize[0];
531 ssrc += s->stride * 4;
532 }
533 }
534
535 *got_frame = 1;
536
537 return avpkt->size;
538 }
539
decode_init(AVCodecContext *avctx)540 static av_cold int decode_init(AVCodecContext *avctx)
541 {
542 FMVCContext *s = avctx->priv_data;
543 int i, j, m, block = 0, h = BLOCK_HEIGHT, w = BLOCK_WIDTH;
544
545 switch (avctx->bits_per_coded_sample) {
546 case 16:
547 avctx->pix_fmt = AV_PIX_FMT_RGB555LE;
548 break;
549 case 24:
550 avctx->pix_fmt = AV_PIX_FMT_BGR24;
551 break;
552 case 32:
553 avctx->pix_fmt = AV_PIX_FMT_BGRA;
554 break;
555 default:
556 av_log(avctx, AV_LOG_ERROR, "Unsupported bitdepth %i\n",
557 avctx->bits_per_coded_sample);
558 return AVERROR_INVALIDDATA;
559 }
560
561 s->stride = (avctx->width * avctx->bits_per_coded_sample + 31) / 32;
562 s->xb = s->stride / BLOCK_WIDTH;
563 m = s->stride % BLOCK_WIDTH;
564 if (m) {
565 if (m < 37) {
566 w = m + BLOCK_WIDTH;
567 } else {
568 w = m;
569 s->xb++;
570 }
571 }
572
573 s->yb = avctx->height / BLOCK_HEIGHT;
574 m = avctx->height % BLOCK_HEIGHT;
575 if (m) {
576 if (m < 49) {
577 h = m + BLOCK_HEIGHT;
578 } else {
579 h = m;
580 s->yb++;
581 }
582 }
583
584 s->nb_blocks = s->xb * s->yb;
585 if (!s->nb_blocks)
586 return AVERROR_INVALIDDATA;
587 s->blocks = av_calloc(s->nb_blocks, sizeof(*s->blocks));
588 if (!s->blocks)
589 return AVERROR(ENOMEM);
590
591 for (i = 0; i < s->yb; i++) {
592 for (j = 0; j < s->xb; j++) {
593 if (i != (s->yb - 1) || j != (s->xb - 1)) {
594 if (i == s->yb - 1) {
595 s->blocks[block].w = BLOCK_WIDTH;
596 s->blocks[block].h = h;
597 s->blocks[block].size = BLOCK_WIDTH * h;
598 } else if (j == s->xb - 1) {
599 s->blocks[block].w = w;
600 s->blocks[block].h = BLOCK_HEIGHT;
601 s->blocks[block].size = BLOCK_HEIGHT * w;
602 } else {
603 s->blocks[block].w = BLOCK_WIDTH;
604 s->blocks[block].h = BLOCK_HEIGHT;
605 s->blocks[block].size = BLOCK_WIDTH * BLOCK_HEIGHT;
606 }
607 } else {
608 s->blocks[block].w = w;
609 s->blocks[block].h = h;
610 s->blocks[block].size = w * h;
611 }
612 block++;
613 }
614 }
615
616 s->bpp = avctx->bits_per_coded_sample >> 3;
617 s->buffer_size = avctx->width * avctx->height * 4;
618 s->pbuffer_size = avctx->width * avctx->height * 4;
619 s->buffer = av_mallocz(s->buffer_size);
620 s->pbuffer = av_mallocz(s->pbuffer_size);
621 if (!s->buffer || !s->pbuffer)
622 return AVERROR(ENOMEM);
623
624 return 0;
625 }
626
decode_close(AVCodecContext *avctx)627 static av_cold int decode_close(AVCodecContext *avctx)
628 {
629 FMVCContext *s = avctx->priv_data;
630
631 av_freep(&s->buffer);
632 av_freep(&s->pbuffer);
633 av_freep(&s->blocks);
634
635 return 0;
636 }
637
638 const FFCodec ff_fmvc_decoder = {
639 .p.name = "fmvc",
640 .p.long_name = NULL_IF_CONFIG_SMALL("FM Screen Capture Codec"),
641 .p.type = AVMEDIA_TYPE_VIDEO,
642 .p.id = AV_CODEC_ID_FMVC,
643 .priv_data_size = sizeof(FMVCContext),
644 .init = decode_init,
645 .close = decode_close,
646 FF_CODEC_DECODE_CB(decode_frame),
647 .p.capabilities = AV_CODEC_CAP_DR1,
648 .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |
649 FF_CODEC_CAP_INIT_CLEANUP,
650 };
651