1 /*
2 * TDSC decoder
3 * Copyright (C) 2015 Vittorio Giovara <vittorio.giovara@gmail.com>
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 /**
23 * @file
24 * TDSC decoder
25 *
26 * Fourcc: TSDC
27 *
28 * TDSC is very simple. It codes picture by tiles, storing them in raw BGR24
29 * format or compressing them in JPEG. Frames can be full pictures or just
30 * updates to the previous frame. Cursor is found in its own frame or at the
31 * bottom of the picture. Every frame is then packed with zlib.
32 *
33 * Supports: BGR24
34 */
35
36 #include <stdint.h>
37 #include <zlib.h>
38
42
47
48 #define BITMAPINFOHEADER_SIZE 0x28
49 #define TDSF_HEADER_SIZE 0x56
50 #define TDSB_HEADER_SIZE 0x08
51
54
57
62
63 /* zlib interaction */
66
67 /* All that is cursor */
73
74 /* 1 byte bits, 1 byte planes, 2 bytes format (probably) */
79 };
80
82 {
84
92
93 return 0;
94 }
95
97 {
100
102
103 /* These needs to be set to estimate buffer and frame size */
107 }
108
109 /* This value should be large enough for a RAW-only frame plus headers */
114
115 /* Allocate reference and JPEG frame */
119 if (!
ctx->refframe || !
ctx->jpgframe || !
ctx->jpkt)
121
122 /* Prepare everything needed for JPEG decoding */
125 if (!
ctx->jpeg_avctx)
133
134 /* Set the output pixel format on the reference frame */
136
137 return 0;
138 }
139
140 #define APPLY_ALPHA(src, new, alpha) \
141 src = (src * (256 - alpha) + new * alpha) >> 8
142
143 /* Paint a region over a buffer, without drawing out of its bounds. */
145 {
147 const uint8_t *cursor =
ctx->cursor;
148 int x =
ctx->cursor_x -
ctx->cursor_hot_x;
149 int y =
ctx->cursor_y -
ctx->cursor_hot_y;
150 int w =
ctx->cursor_w;
151 int h =
ctx->cursor_h;
153
155 return;
156
157 if (x +
w >
ctx->width)
159 if (y +
h >
ctx->height)
161 if (x < 0) {
163 cursor += -x * 4;
164 } else {
166 }
167 if (y < 0) {
169 cursor += -y *
ctx->cursor_stride;
170 } else {
172 }
174 return;
175
176 for (j = 0; j <
h; j++) {
177 for (
i = 0;
i <
w;
i++) {
178 uint8_t
alpha = cursor[
i * 4];
182 }
184 cursor +=
ctx->cursor_stride;
185 }
186 }
187
188 /* Load cursor data and store it in ABGR mode. */
190 {
192 int i, j, k,
ret, cursor_fmt;
194
195 ctx->cursor_hot_x = bytestream2_get_le16(&
ctx->gbc);
196 ctx->cursor_hot_y = bytestream2_get_le16(&
ctx->gbc);
197 ctx->cursor_w = bytestream2_get_le16(&
ctx->gbc);
198 ctx->cursor_h = bytestream2_get_le16(&
ctx->gbc);
199
201 cursor_fmt = bytestream2_get_le32(&
ctx->gbc);
202
205 "Invalid cursor position (%d.%d outside %dx%d).\n",
208 }
209 if (
ctx->cursor_w < 1 ||
ctx->cursor_w > 256 ||
210 ctx->cursor_h < 1 ||
ctx->cursor_h > 256) {
212 "Invalid cursor dimensions %dx%d.\n",
213 ctx->cursor_w,
ctx->cursor_h);
215 }
216 if (
ctx->cursor_hot_x >
ctx->cursor_w ||
217 ctx->cursor_hot_y >
ctx->cursor_h) {
219 ctx->cursor_hot_x,
ctx->cursor_hot_y);
222 }
223
228 }
229
231 /* here data is packed in BE */
232 switch (cursor_fmt) {
234 for (j = 0; j <
ctx->cursor_h; j++) {
235 for (
i = 0;
i <
ctx->cursor_w;
i += 32) {
236 uint32_t
bits = bytestream2_get_be32(&
ctx->gbc);
237 for (k = 0; k < 32; k++) {
238 dst[0] = !!(
bits & 0x80000000);
241 }
242 }
243 dst +=
ctx->cursor_stride -
ctx->cursor_w * 4;
244 }
245
247 for (j = 0; j <
ctx->cursor_h; j++) {
248 for (
i = 0;
i <
ctx->cursor_w;
i += 32) {
249 uint32_t
bits = bytestream2_get_be32(&
ctx->gbc);
250 for (k = 0; k < 32; k++) {
251 int mask_bit = !!(
bits & 0x80000000);
252 switch (
dst[0] * 2 + mask_bit) {
253 case 0:
258 break;
259 case 1:
264 break;
265 default:
270 }
273 }
274 }
275 dst +=
ctx->cursor_stride -
ctx->cursor_w * 4;
276 }
277 break;
280 /* Skip monochrome version of the cursor */
283 if (cursor_fmt & 8) { // RGBA -> ABGR
284 for (j = 0; j <
ctx->cursor_h; j++) {
285 for (
i = 0;
i <
ctx->cursor_w;
i++) {
286 int val = bytestream2_get_be32(&
ctx->gbc);
291 }
292 dst +=
ctx->cursor_stride -
ctx->cursor_w * 4;
293 }
294 } else { // BGRA -> ABGR
295 for (j = 0; j <
ctx->cursor_h; j++) {
296 for (
i = 0;
i <
ctx->cursor_w;
i++) {
297 int val = bytestream2_get_be32(&
ctx->gbc);
302 }
303 dst +=
ctx->cursor_stride -
ctx->cursor_w * 4;
304 }
305 }
306 break;
307 default:
310 }
311
312 return 0;
313 }
314
315 /* Convert a single YUV pixel to RGB. */
317 {
321 }
322
323 /* Convert a YUV420 buffer to a RGB buffer. */
325 const uint8_t *srcy, int srcy_stride,
326 const uint8_t *srcu, const uint8_t *srcv,
328 {
331 for (col = 0; col <
width; col++)
333 srcu[col >> 1] - 128, srcv[col >> 1] - 128);
334
336 srcy += srcy_stride;
337 srcu += srcuv_stride * (
line & 1);
338 srcv += srcuv_stride * (
line & 1);
339 }
340 }
341
342 /* Invoke the MJPEG decoder to decode the tile. */
344 int x,
int y,
int w,
int h)
345 {
348
349 /* Prepare a packet and send to the MJPEG decoder */
351 ctx->jpkt->data =
ctx->tilebuffer;
352 ctx->jpkt->size = tile_size;
353
358 }
359
363 "JPEG decoding error (%d).\n",
ret);
364
365 /* Normally skip, error if explode */
368 else
369 return 0;
370 }
371
372 /* Let's paint onto the buffer */
373 tdsc_blit(
ctx->refframe->data[0] + x * 3 +
ctx->refframe->linesize[0] * y,
374 ctx->refframe->linesize[0],
375 ctx->jpgframe->data[0],
ctx->jpgframe->linesize[0],
376 ctx->jpgframe->data[1],
ctx->jpgframe->data[2],
377 ctx->jpgframe->linesize[1],
w,
h);
378
380
381 return 0;
382 }
383
384 /* Parse frame and either copy data or decode JPEG. */
386 {
389
390 /* Iterate over the number of tiles */
391 for (
i = 0;
i < number_tiles;
i++) {
392 int tile_size;
393 int tile_mode;
394 int x, y, x2, y2,
w,
h;
396
398 bytestream2_get_le32(&
ctx->gbc) !=
MKTAG(
'T',
'D',
'S',
'B') ||
402 }
403
404 tile_size = bytestream2_get_le32(&
ctx->gbc);
407
408 tile_mode = bytestream2_get_le32(&
ctx->gbc);
410 x = bytestream2_get_le32(&
ctx->gbc);
411 y = bytestream2_get_le32(&
ctx->gbc);
412 x2 = bytestream2_get_le32(&
ctx->gbc);
413 y2 = bytestream2_get_le32(&
ctx->gbc);
414
415 if (x < 0 || y < 0 || x2 <= x || y2 <= y ||
416 x2 >
ctx->width || y2 >
ctx->height
417 ) {
419 "Invalid tile position (%d.%d %d.%d outside %dx%d).\n",
420 x, y, x2, y2,
ctx->width,
ctx->height);
422 }
425
427 if (!
ctx->tilebuffer)
429
431
432 if (tile_mode ==
MKTAG(
'G',
'E',
'P',
'J')) {
433 /* Decode JPEG tile and copy it in the reference frame */
437 }
else if (tile_mode ==
MKTAG(
' ',
'W',
'A',
'R')) {
438 /* Just copy the buffer to output */
440 ctx->refframe->linesize[0] * y,
441 ctx->refframe->linesize[0],
ctx->tilebuffer,
443 } else {
446 }
448 }
449
450 return 0;
451 }
452
454 {
456 int ret,
w,
h, init_refframe = !
ctx->refframe->data[0];
457
458 /* BITMAPINFOHEADER
459 * http://msdn.microsoft.com/en-us/library/windows/desktop/dd183376.aspx */
462
463 /* Store size, but wait for context reinit before updating avctx */
464 w = bytestream2_get_le32(&
ctx->gbc);
465 h = -bytestream2_get_le32(&
ctx->gbc);
466
467 if (bytestream2_get_le16(&
ctx->gbc) != 1 ||
// 1 plane
468 bytestream2_get_le16(&
ctx->gbc) != 24)
// BGR24
470
472
473 /* Update sizes */
480 init_refframe = 1;
481 }
482 ctx->refframe->width =
ctx->width =
w;
483 ctx->refframe->height =
ctx->height =
h;
484
485 /* Allocate the reference frame if not already done or on size change */
486 if (init_refframe) {
490 }
491
492 /* Decode all tiles in a frame */
494 }
495
497 {
500 int action = bytestream2_get_le32(&
ctx->gbc);
501
503
504 if (action == 2 || action == 3) {
505 /* Load cursor coordinates */
506 ctx->cursor_x = bytestream2_get_le32(&
ctx->gbc);
507 ctx->cursor_y = bytestream2_get_le32(&
ctx->gbc);
508
509 /* Load a full cursor sprite */
510 if (action == 3) {
512 /* Do not consider cursor errors fatal unless in explode mode */
515 }
516 } else {
518 }
519
520 return 0;
521 }
522
525 {
527 int ret, tag_header, keyframe = 0;
528 uLongf dlen;
529
530 /* Resize deflate buffer on resolution change */
532 int deflatelen = avctx->
width * avctx->
height * (3 + 1);
533 if (deflatelen !=
ctx->deflatelen) {
534 ctx->deflatelen =deflatelen;
539 }
540 }
541 }
542 dlen =
ctx->deflatelen;
543
544 /* Frames are deflated, need to inflate them first */
545 ret = uncompress(
ctx->deflatebuffer, &dlen, avpkt->
data, avpkt->
size);
549 }
550
552
553 /* Check for tag and for size info */
557 }
558
559 /* Read tag */
560 tag_header = bytestream2_get_le32(&
ctx->gbc);
561
562 if (tag_header ==
MKTAG(
'T',
'D',
'S',
'F')) {
563 int number_tiles;
567 }
568 /* First 4 bytes here are the number of GEPJ/WAR tiles in this frame */
569 number_tiles = bytestream2_get_le32(&
ctx->gbc);
570
572 keyframe = bytestream2_get_le32(&
ctx->gbc) == 0x30;
573
577
578 /* Check if there is anything else we are able to parse */
580 tag_header = bytestream2_get_le32(&
ctx->gbc);
581 }
582
583 /* This tag can be after a TDSF block or on its own frame */
584 if (tag_header ==
MKTAG(
'D',
'T',
'S',
'M')) {
585 /* First 4 bytes here are the total size in bytes for this frame */
586 int tag_size = bytestream2_get_le32(&
ctx->gbc);
587
591 }
592
596 }
597
598 /* Get the output frame and copy the reference frame */
602
606
607 /* Paint the cursor on the output frame */
609
610 /* Frame is ready to be output */
611 if (keyframe) {
614 } else {
616 }
617 *got_frame = 1;
618
620 }
621
633 };