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 35typedef struct InterBlock { 36 int w, h; 37 int size; 38 int xor; 39} InterBlock; 40 41typedef 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 55static 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 290static 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 397static 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 540static 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 627static 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 638const 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