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
40
44
45 #define BITMAPINFOHEADER_SIZE 0x28
46 #define TDSF_HEADER_SIZE 0x56
47 #define TDSB_HEADER_SIZE 0x08
48
51
54
58
59 /* zlib interation */
62
63 /* All that is cursor */
69
70 /* 1 byte bits, 1 byte planes, 2 bytes format (probably) */
75 };
76
78 {
80
87
88 return 0;
89 }
90
92 {
95 int ret;
96
98
99 /* These needs to be set to estimate buffer and frame size */
103 }
104
105 /* This value should be large enough for a RAW-only frame plus headers */
108 if (ret < 0)
109 return ret;
110
111 /* Allocate reference and JPEG frame */
116
117 /* Prepare everything needed for JPEG decoding */
119 if (!codec)
129 if (ret < 0)
130 return ret;
131
132 /* Set the output pixel format on the reference frame */
134
135 return 0;
136 }
137
138 #define APPLY_ALPHA(src, new, alpha) \
139 src = (src * (256 - alpha) + new * alpha) >> 8
140
141 /* Paint a region over a buffer, without drawing out of its bounds. */
143 {
150 int i, j;
151
153 return;
154
155 if (x + w > ctx->
width)
159 if (x < 0) {
160 w += x;
161 cursor += -x * 4;
162 } else {
163 dst += x * 3;
164 }
165 if (y < 0) {
166 h += y;
168 } else {
170 }
171 if (w < 0 || h < 0)
172 return;
173
174 for (j = 0; j <
h; j++) {
175 for (i = 0; i < w; i++) {
177 APPLY_ALPHA(dst[i * 3 + 0], cursor[i * 4 + 1], alpha);
178 APPLY_ALPHA(dst[i * 3 + 1], cursor[i * 4 + 2], alpha);
179 APPLY_ALPHA(dst[i * 3 + 2], cursor[i * 4 + 3], alpha);
180 }
183 }
184 }
185
186 /* Load cursor data and store it in ABGR mode. */
188 {
190 int i, j, k, ret,
bits, cursor_fmt;
192
197
199 cursor_fmt = bytestream2_get_le32(&ctx->
gbc);
200
203 "Invalid cursor position (%d.%d outside %dx%d).\n",
206 }
210 "Invalid cursor dimensions %dx%d.\n",
213 }
220 }
221
223 if (ret < 0) {
225 return ret;
226 }
227
229 /* here data is packed in BE */
230 switch (cursor_fmt) {
232 for (j = 0; j < ctx->
cursor_h; j++) {
233 for (i = 0; i < ctx->
cursor_w; i += 32) {
234 bits = bytestream2_get_be32(&ctx->
gbc);
235 for (k = 0; k < 32; k++) {
236 dst[0] = !!(bits & 0x80000000);
237 dst += 4;
238 bits <<= 1;
239 }
240 }
242 }
243
245 for (j = 0; j < ctx->
cursor_h; j++) {
246 for (i = 0; i < ctx->
cursor_w; i += 32) {
247 bits = bytestream2_get_be32(&ctx->
gbc);
248 for (k = 0; k < 32; k++) {
249 int mask_bit = !!(bits & 0x80000000);
250 switch (dst[0] * 2 + mask_bit) {
251 case 0:
252 dst[0] = 0xFF;
253 dst[1] = 0x00;
254 dst[2] = 0x00;
255 dst[3] = 0x00;
256 break;
257 case 1:
258 dst[0] = 0xFF;
259 dst[1] = 0xFF;
260 dst[2] = 0xFF;
261 dst[3] = 0xFF;
262 break;
263 default:
264 dst[0] = 0x00;
265 dst[1] = 0x00;
266 dst[2] = 0x00;
267 dst[3] = 0x00;
268 }
269 dst += 4;
270 bits <<= 1;
271 }
272 }
274 }
275 break;
278 /* Skip monochrome version of the cursor */
281 if (cursor_fmt & 8) { // RGBA -> ABGR
282 for (j = 0; j < ctx->
cursor_h; j++) {
283 for (i = 0; i < ctx->
cursor_w; i++) {
284 int val = bytestream2_get_be32(&ctx->
gbc);
285 *dst++ = val >> 24;
286 *dst++ = val >> 16;
287 *dst++ = val >> 8;
288 *dst++ = val >> 0;
289 }
291 }
292 } else { // BGRA -> ABGR
293 for (j = 0; j < ctx->
cursor_h; j++) {
294 for (i = 0; i < ctx->
cursor_w; i++) {
295 int val = bytestream2_get_be32(&ctx->
gbc);
296 *dst++ = val >> 0;
297 *dst++ = val >> 24;
298 *dst++ = val >> 16;
299 *dst++ = val >> 8;
300 }
302 }
303 }
304 break;
305 default:
308 }
309
310 return 0;
311 }
312
313 /* Convert a single YUV pixel to RGB. */
315 {
316 out[0] = av_clip_uint8(Y + ( 91881 * V + 32768 >> 16));
317 out[1] = av_clip_uint8(Y + (-22554 * U - 46802 * V + 32768 >> 16));
318 out[2] = av_clip_uint8(Y + (116130 * U + 32768 >> 16));
319 }
320
321 /* Convert a YUV420 buffer to a RGB buffer. */
323 const uint8_t *srcy,
int srcy_stride,
326 {
328 for (line = 0; line <
height; line++) {
329 for (col = 0; col <
width; col++)
331 srcu[col >> 1] - 128, srcv[col >> 1] - 128);
332
333 dst += dst_stride;
334 srcy += srcy_stride;
335 srcu += srcuv_stride * (line & 1);
336 srcv += srcuv_stride * (line & 1);
337 }
338 }
339
340 /* Invoke the MJPEG decoder to decode the tile. */
342 int x,
int y,
int w,
int h)
343 {
346 int got_frame = 0;
347 int ret;
348
349 /* Prepare a packet and send to the MJPEG decoder */
352 jpkt.
size = tile_size;
353
355 &got_frame, &jpkt);
358 "JPEG decoding error (%d) for (%d) frame.\n",
359 ret, got_frame);
360
361 /* Normally skip, error if explode */
364 else
365 return 0;
366 }
367
368 /* Let's paint ont the buffer */
374
376
377 return 0;
378 }
379
380 /* Parse frame and either copy data or decode JPEG. */
382 {
384 int i;
385
386 /* Iterate over the number of tiles */
387 for (i = 0; i < number_tiles; i++) {
388 int tile_size;
389 int tile_mode;
391 int ret;
392
394 bytestream2_get_le32(&ctx->
gbc) !=
MKTAG(
'T',
'D',
'S',
'B') ||
398 }
399
400 tile_size = bytestream2_get_le32(&ctx->
gbc);
403
404 tile_mode = bytestream2_get_le32(&ctx->
gbc);
406 x = bytestream2_get_le32(&ctx->
gbc);
407 y = bytestream2_get_le32(&ctx->
gbc);
408 w = bytestream2_get_le32(&ctx->
gbc) - x;
409 h = bytestream2_get_le32(&ctx->
gbc) - y;
410
413 "Invalid tile position (%d.%d outside %dx%d).\n",
416 }
419 "Invalid tile size %dx%d\n", w, h);
421 }
422
425 return ret;
426
428
429 if (tile_mode ==
MKTAG(
'G',
'E',
'P',
'J')) {
430 /* Decode JPEG tile and copy it in the reference frame */
432 if (ret < 0)
433 return ret;
434 }
else if (tile_mode ==
MKTAG(
' ',
'W',
'A',
'R')) {
435 /* Just copy the buffer to output */
439 w * 3, w * 3, h);
440 } else {
443 }
445 }
446
447 return 0;
448 }
449
451 {
454
455 /* BITMAPINFOHEADER
456 * http://msdn.microsoft.com/en-us/library/windows/desktop/dd183376.aspx */
459
460 /* Store size, but wait for context reinit before updating avctx */
461 w = bytestream2_get_le32(&ctx->
gbc);
462 h = -bytestream2_get_le32(&ctx->
gbc);
463
464 if (bytestream2_get_le16(&ctx->
gbc) != 1 ||
// 1 plane
465 bytestream2_get_le16(&ctx->
gbc) != 24)
// BGR24
467
469
470 /* Update sizes */
475 if (ret < 0)
476 return ret;
477 init_refframe = 1;
478 }
481
482 /* Allocate the reference frame if not already done or on size change */
483 if (init_refframe) {
485 if (ret < 0)
486 return ret;
487 }
488
489 /* Decode all tiles in a frame */
491 }
492
494 {
496 int ret;
497 int action = bytestream2_get_le32(&ctx->
gbc);
498
500
501 if (action == 2 || action == 3) {
502 /* Load cursor coordinates */
505
506 /* Load a full cursor sprite */
507 if (action == 3) {
509 /* Do not consider cursor errors fatal unless in explode mode */
511 return ret;
512 }
513 } else {
515 }
516
517 return 0;
518 }
519
522 {
525 int ret, tag_header, keyframe = 0;
526 uLongf dlen;
527
528 /* Resize deflate buffer on resolution change */
532 if (ret < 0)
533 return ret;
534 }
536
537 /* Frames are deflated, need to inflate them first */
539 if (ret) {
542 }
543
545
546 /* Check for tag and for size info */
550 }
551
552 /* Read tag */
553 tag_header = bytestream2_get_le32(&ctx->
gbc);
554
555 if (tag_header ==
MKTAG(
'T',
'D',
'S',
'F')) {
556 int number_tiles;
560 }
561 /* First 4 bytes here are the number of GEPJ/WAR tiles in this frame */
562 number_tiles = bytestream2_get_le32(&ctx->
gbc);
563
565 keyframe = bytestream2_get_le32(&ctx->
gbc) == 0x30;
566
568 if (ret < 0)
569 return ret;
570
571 /* Check if there is anything else we are able to parse */
573 tag_header = bytestream2_get_le32(&ctx->
gbc);
574 }
575
576 /* This tag can be after a TDSF block or on its own frame */
577 if (tag_header ==
MKTAG(
'D',
'T',
'S',
'M')) {
578 /* First 4 bytes here are the total size in bytes for this frame */
579 int tag_size = bytestream2_get_le32(&ctx->
gbc);
580
584 }
585
587 if (ret < 0)
588 return ret;
589 }
590
591 /* Get the output frame and copy the reference frame */
593 if (ret < 0)
594 return ret;
595
597 if (ret < 0)
598 return ret;
599
600 /* Paint the cursor on the output frame */
602
603 /* Frame is ready to be output */
604 if (keyframe) {
607 } else {
609 }
610 *got_frame = 1;
611
612 return 0;
613 }
614
627 };
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
const char const char void * val
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
static int tdsc_decode_tiles(AVCodecContext *avctx, int number_tiles)
This structure describes decoded (raw) audio or video data.
int dct_algo
DCT algorithm, see FF_DCT_* below.
ptrdiff_t const GLvoid * data
#define AV_LOG_WARNING
Something somehow does not look correct.
int ff_set_dimensions(AVCodecContext *s, int width, int height)
Check that the provided frame dimensions are valid and set them on the codec context.
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
static av_cold int tdsc_init(AVCodecContext *avctx)
AVCodecContext * jpeg_avctx
void void avpriv_request_sample(void *avc, const char *msg,...) av_printf_format(2
Log a generic warning message about a missing feature.
#define FF_CODEC_CAP_INIT_THREADSAFE
The codec does not modify any global variables in the init function, allowing to call the init functi...
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
#define BITMAPINFOHEADER_SIZE
static int tdsc_parse_dtsm(AVCodecContext *avctx)
static av_always_inline void tdsc_blit(uint8_t *dst, int dst_stride, const uint8_t *srcy, int srcy_stride, const uint8_t *srcu, const uint8_t *srcv, int srcuv_stride, int width, int height)
static av_cold int tdsc_close(AVCodecContext *avctx)
static double alpha(void *priv, double x, double y)
int width
width and height of the video frame
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, const AVPacket *avpkt)
Decode the video frame of size avpkt->size from avpkt->data into picture.
int ff_codec_open2_recursive(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
Call avcodec_open2 recursively by decrementing counter, unlocking mutex, calling the function and the...
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
static int tdsc_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
static av_always_inline unsigned int bytestream2_get_bytes_left(GetByteContext *g)
int flags
AV_CODEC_FLAG_*.
const char * name
Name of the codec implementation.
static int tdsc_parse_tdsf(AVCodecContext *avctx, int number_tiles)
int av_frame_copy(AVFrame *dst, const AVFrame *src)
Copy the frame data from src to dst.
enum AVPictureType pict_type
Picture type of the frame.
int err_recognition
Error recognition; may misdetect some more or less valid parts as errors.
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting col...
AVCodecContext * avcodec_alloc_context3(const AVCodec *codec)
Allocate an AVCodecContext and set its fields to default values.
int width
picture width / height.
int idct_algo
IDCT algorithm, see FF_IDCT_* below.
static int tdsc_decode_jpeg_tile(AVCodecContext *avctx, int tile_size, int x, int y, int w, int h)
#define AV_EF_EXPLODE
abort decoding on minor error detection
packed RGB 8:8:8, 24bpp, BGRBGR...
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
static void tdsc_paint_cursor(AVCodecContext *avctx, uint8_t *dst, int stride)
Libavcodec external API header.
void avcodec_free_context(AVCodecContext **avctx)
Free the codec context and everything associated with it and write NULL to the provided pointer...
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
main external API structure.
AVCodec * avcodec_find_decoder(enum AVCodecID id)
Find a registered decoder with a matching codec ID.
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
BYTE int const BYTE int int int height
int av_frame_get_buffer(AVFrame *frame, int align)
Allocate new buffer(s) for audio or video data.
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
GLint GLenum GLboolean GLsizei stride
common internal api header.
int av_reallocp(void *ptr, size_t size)
Allocate or reallocate a block of memory.
void av_init_packet(AVPacket *pkt)
Initialize optional fields of a packet with default values.
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
int key_frame
1 -> keyframe, 0-> not
#define APPLY_ALPHA(src, new, alpha)
static void tdsc_yuv2rgb(uint8_t *out, int Y, int U, int V)
int flags2
AV_CODEC_FLAG2_*.
static int tdsc_load_cursor(AVCodecContext *avctx)
void av_image_copy_plane(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int bytewidth, int height)
Copy image plane from src to dst.
#define MKTAG(a, b, c, d)
This structure stores compressed data.
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.