2 * FM Screen Capture Codec decoder
4 * Copyright (c) 2017 Paul B Mahol
6 * This file is part of FFmpeg.
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.
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.
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
28 #include "bytestream.h"
31 #define BLOCK_HEIGHT 112u
32 #define BLOCK_WIDTH 84u
34 typedef struct InterBlock {
40 typedef struct FMVCContext {
54 static int decode_type2(GetByteContext *gb, PutByteContext *pb)
56 unsigned repeat = 0, first = 1, opcode = 0;
59 while (bytestream2_get_bytes_left(gb) > 0) {
62 while (bytestream2_get_bytes_left(gb) > 0) {
65 if (bytestream2_peek_byte(gb) > 17) {
66 len = bytestream2_get_byte(gb) - 17;
69 bytestream2_put_byte(pb, bytestream2_get_byte(gb));
72 opcode = bytestream2_peek_byte(gb);
76 bytestream2_put_byte(pb, bytestream2_get_byte(gb));
79 opcode = bytestream2_peek_byte(gb);
81 bytestream2_skip(gb, 1);
82 pos = - (opcode >> 2) - 4 * bytestream2_get_byte(gb) - 2049;
84 bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
85 bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
87 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
88 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
89 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
95 bytestream2_put_byte(pb, bytestream2_get_byte(gb));
98 opcode = bytestream2_peek_byte(gb);
109 opcode = bytestream2_peek_byte(gb);
111 bytestream2_skip(gb, 1);
113 if (!bytestream2_peek_byte(gb)) {
115 bytestream2_skip(gb, 1);
117 } while (!bytestream2_peek_byte(gb) && bytestream2_get_bytes_left(gb) > 0);
119 opcode += bytestream2_get_byte(gb) + 15;
121 bytestream2_put_le32(pb, bytestream2_get_le32(gb));
122 for (i = opcode - 1; i > 0; --i)
123 bytestream2_put_byte(pb, bytestream2_get_byte(gb));
124 opcode = bytestream2_peek_byte(gb);
126 bytestream2_skip(gb, 1);
127 pos = - (opcode >> 2) - 4 * bytestream2_get_byte(gb) - 2049;
129 bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
130 bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
132 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
133 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
134 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
140 bytestream2_put_byte(pb, bytestream2_get_byte(gb));
143 opcode = bytestream2_peek_byte(gb);
150 if (opcode >= 0x40) {
151 bytestream2_skip(gb, 1);
152 pos = - ((opcode >> 2) & 7) - 1 - 8 * bytestream2_get_byte(gb);
153 len = (opcode >> 5) - 1;
155 bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
156 bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
158 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
159 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
161 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
171 bytestream2_put_byte(pb, bytestream2_get_byte(gb));
174 opcode = bytestream2_peek_byte(gb);
177 } else if (opcode < 0x20) {
181 bytestream2_skip(gb, 1);
183 if (!bytestream2_peek_byte(gb)) {
185 bytestream2_skip(gb, 1);
187 } while (!bytestream2_peek_byte(gb) && bytestream2_get_bytes_left(gb) > 0);
189 len += bytestream2_get_byte(gb) + 31;
191 i = bytestream2_get_le16(gb);
192 pos = - (i >> 2) - 1;
194 bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
195 bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
197 if (len < 6 || bytestream2_tell_p(pb) - bytestream2_tell(&gbc) < 4) {
198 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
199 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
201 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
205 bytestream2_put_le32(pb, bytestream2_get_le32(&gbc));
206 for (len = len - 2; len; --len)
207 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
214 bytestream2_put_byte(pb, bytestream2_get_byte(gb));
217 opcode = bytestream2_peek_byte(gb);
220 bytestream2_skip(gb, 1);
222 pos = -(opcode >> 2) - 1 - 4 * bytestream2_get_byte(gb);
224 bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
225 bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
227 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
228 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
234 bytestream2_put_byte(pb, bytestream2_get_byte(gb));
237 opcode = bytestream2_peek_byte(gb);
243 if (!bytestream2_peek_byte(gb)) {
245 bytestream2_skip(gb, 1);
247 } while (!bytestream2_peek_byte(gb) && bytestream2_get_bytes_left(gb) > 0);
249 len += bytestream2_get_byte(gb) + 7;
251 i = bytestream2_get_le16(gb);
252 pos = bytestream2_tell_p(pb) - 2048 * (opcode & 8);
253 pos = pos - (i >> 2);
254 if (pos == bytestream2_tell_p(pb))
258 bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
259 bytestream2_seek(&gbc, pos, SEEK_SET);
261 if (len < 6 || bytestream2_tell_p(pb) - bytestream2_tell(&gbc) < 4) {
262 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
263 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
265 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
269 bytestream2_put_le32(pb, bytestream2_get_le32(&gbc));
270 for (len = len - 2; len; --len)
271 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
279 bytestream2_put_byte(pb, bytestream2_get_byte(gb));
282 opcode = bytestream2_peek_byte(gb);
289 static int decode_type1(GetByteContext *gb, PutByteContext *pb)
291 unsigned opcode = 0, len;
295 while (bytestream2_get_bytes_left(gb) > 0) {
298 while (bytestream2_get_bytes_left(gb) > 0) {
299 while (bytestream2_get_bytes_left(gb) > 0) {
300 opcode = bytestream2_get_byte(gb);
301 high = opcode >= 0x20;
306 opcode = bytestream2_get_byte(gb);
308 opcode = opcode + 32;
322 bytestream2_put_le32(pb, bytestream2_get_le32(gb));
323 bytestream2_put_le32(pb, bytestream2_get_le32(gb));
325 } while (len && bytestream2_get_bytes_left(gb) > 0);
330 bytestream2_put_byte(pb, bytestream2_get_byte(gb));
332 } while (opcode && bytestream2_get_bytes_left(gb) > 0);
334 while (bytestream2_get_bytes_left(gb) > 0) {
337 opcode = bytestream2_get_byte(gb);
340 bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
342 pos = -(opcode | 32 * bytestream2_get_byte(gb)) - 1;
343 bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
344 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
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(gb));
353 bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
354 pos = (-((opcode & 0x1F) | 32 * bytestream2_get_byte(gb)) - 1);
355 bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);
356 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
357 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
358 len = (opcode >> 5) - 1;
360 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
362 } while (len && bytestream2_get_bytes_left(&gbc) > 0);
366 if (!bytestream2_peek_byte(gb)) {
368 bytestream2_skip(gb, 1);
370 } while (!bytestream2_peek_byte(gb) && bytestream2_get_bytes_left(gb) > 0);
372 len += bytestream2_get_byte(gb) + 31;
374 pos = -bytestream2_get_byte(gb);
375 bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);
376 bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos - (bytestream2_get_byte(gb) << 8), SEEK_SET);
377 if (bytestream2_tell_p(pb) == bytestream2_tell(&gbc))
379 if (len < 5 || bytestream2_tell_p(pb) - bytestream2_tell(&gbc) < 4) {
380 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
381 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
382 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
384 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
386 } while (len && bytestream2_get_bytes_left(&gbc) > 0);
388 bytestream2_put_le32(pb, bytestream2_get_le32(&gbc));
391 bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));
393 } while (len && bytestream2_get_bytes_left(&gbc) > 0);
400 static int decode_frame(AVCodecContext *avctx,
401 void *data, int *got_frame,
404 FMVCContext *s = avctx->priv_data;
405 GetByteContext *gb = &s->gb;
406 PutByteContext *pb = &s->pb;
407 AVFrame *frame = data;
410 if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
413 bytestream2_init(gb, avpkt->data, avpkt->size);
414 bytestream2_skip(gb, 2);
416 frame->key_frame = !!bytestream2_get_le16(gb);
417 frame->pict_type = frame->key_frame ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
419 if (frame->key_frame) {
424 type = bytestream2_get_le16(gb);
425 size = bytestream2_get_le16(gb);
426 if (size > bytestream2_get_bytes_left(gb))
427 return AVERROR_INVALIDDATA;
429 bytestream2_init_writer(pb, s->buffer, s->buffer_size);
431 decode_type1(gb, pb);
432 } else if (type == 2){
433 decode_type2(gb, pb);
435 avpriv_report_missing_feature(avctx, "compression %d", type);
436 return AVERROR_PATCHWELCOME;
440 dst = frame->data[0] + (avctx->height - 1) * frame->linesize[0];
441 for (y = 0; y < avctx->height; y++) {
442 memcpy(dst, src, avctx->width * s->bpp);
443 dst -= frame->linesize[0];
444 src += s->stride * 4;
447 int block, nb_blocks, type, k, l;
448 uint8_t *ssrc, *ddst;
452 for (block = 0; block < s->nb_blocks; block++)
453 s->blocks[block].xor = 0;
455 nb_blocks = bytestream2_get_le16(gb);
456 if (nb_blocks > s->nb_blocks)
457 return AVERROR_INVALIDDATA;
459 bytestream2_init_writer(pb, s->pbuffer, s->pbuffer_size);
461 type = bytestream2_get_le16(gb);
462 for (block = 0; block < nb_blocks; block++) {
463 int size, offset, start = 0;
465 offset = bytestream2_get_le16(gb);
466 if (offset > s->nb_blocks)
467 return AVERROR_INVALIDDATA;
469 size = bytestream2_get_le16(gb);
470 if (size > bytestream2_get_bytes_left(gb))
471 return AVERROR_INVALIDDATA;
473 start = bytestream2_tell_p(pb);
475 decode_type1(gb, pb);
476 } else if (type == 2){
477 decode_type2(gb, pb);
479 avpriv_report_missing_feature(avctx, "compression %d", type);
480 return AVERROR_PATCHWELCOME;
483 if (s->blocks[offset].size * 4 != bytestream2_tell_p(pb) - start)
484 return AVERROR_INVALIDDATA;
486 s->blocks[offset].xor = 1;
489 src = (const uint32_t *)s->pbuffer;
490 dst = (uint32_t *)s->buffer;
492 for (block = 0, y = 0; y < s->yb; y++) {
493 int block_h = s->blocks[block].h;
494 uint32_t *rect = dst;
496 for (x = 0; x < s->xb; x++) {
497 int block_w = s->blocks[block].w;
500 block_h = s->blocks[block].h;
501 if (s->blocks[block].xor) {
502 for (k = 0; k < block_h; k++) {
503 uint32_t *column = dst;
504 for (l = 0; l < block_w; l++) {
507 dst = &column[s->stride];
513 dst = &rect[block_h * s->stride];
517 ddst = frame->data[0] + (avctx->height - 1) * frame->linesize[0];
518 for (y = 0; y < avctx->height; y++) {
519 memcpy(ddst, ssrc, avctx->width * s->bpp);
520 ddst -= frame->linesize[0];
521 ssrc += s->stride * 4;
530 static av_cold int decode_init(AVCodecContext *avctx)
532 FMVCContext *s = avctx->priv_data;
533 int i, j, m, block = 0, h = BLOCK_HEIGHT, w = BLOCK_WIDTH;
535 switch (avctx->bits_per_coded_sample) {
536 case 16: avctx->pix_fmt = AV_PIX_FMT_RGB555; break;
537 case 24: avctx->pix_fmt = AV_PIX_FMT_BGR24; break;
538 case 32: avctx->pix_fmt = AV_PIX_FMT_BGRA; break;
540 av_log(avctx, AV_LOG_ERROR, "Unsupported bitdepth %i\n", avctx->bits_per_coded_sample);
541 return AVERROR_INVALIDDATA;
544 s->stride = (avctx->width * avctx->bits_per_coded_sample + 31) / 32;
545 s->xb = s->stride / BLOCK_WIDTH;
546 m = s->stride % BLOCK_WIDTH;
556 s->yb = avctx->height / BLOCK_HEIGHT;
557 m = avctx->height % BLOCK_HEIGHT;
560 h = m + BLOCK_HEIGHT;
567 s->nb_blocks = s->xb * s->yb;
568 s->blocks = av_calloc(s->nb_blocks, sizeof(*s->blocks));
570 return AVERROR(ENOMEM);
572 for (i = 0; i < s->yb; i++) {
573 for (j = 0; j < s->xb; j++) {
574 if (i != (s->yb - 1) || j != (s->xb - 1)) {
575 if (i == s->yb - 1) {
576 s->blocks[block].w = BLOCK_WIDTH;
577 s->blocks[block].h = h;
578 s->blocks[block].size = BLOCK_WIDTH * h;
579 } else if (j == s->xb - 1) {
580 s->blocks[block].w = w;
581 s->blocks[block].h = BLOCK_HEIGHT;
582 s->blocks[block].size = BLOCK_HEIGHT * w;
584 s->blocks[block].w = BLOCK_WIDTH;
585 s->blocks[block].h = BLOCK_HEIGHT;
586 s->blocks[block].size = BLOCK_WIDTH * BLOCK_HEIGHT;
589 s->blocks[block].w = w;
590 s->blocks[block].h = h;
591 s->blocks[block].size = w * h;
597 s->bpp = avctx->bits_per_coded_sample >> 3;
598 s->buffer_size = avctx->width * avctx->height * 4;
599 s->pbuffer_size = avctx->width * avctx->height * 4;
600 s->buffer = av_malloc(s->buffer_size);
601 s->pbuffer = av_malloc(s->pbuffer_size);
602 if (!s->buffer || !s->pbuffer)
603 return AVERROR(ENOMEM);
608 static av_cold int decode_close(AVCodecContext *avctx)
610 FMVCContext *s = avctx->priv_data;
612 av_freep(&s->buffer);
613 av_freep(&s->pbuffer);
614 av_freep(&s->blocks);
619 AVCodec ff_fmvc_decoder = {
621 .long_name = NULL_IF_CONFIG_SMALL("FM Screen Capture Codec"),
622 .type = AVMEDIA_TYPE_VIDEO,
623 .id = AV_CODEC_ID_FMVC,
624 .priv_data_size = sizeof(FMVCContext),
626 .close = decode_close,
627 .decode = decode_frame,
628 .capabilities = AV_CODEC_CAP_DR1,
629 .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |
630 FF_CODEC_CAP_INIT_CLEANUP,