3 * Copyright (C) 2015 Vittorio Giovara <vittorio.giovara@gmail.com>
5 * This file is part of FFmpeg.
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.
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.
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
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.
39 #include "libavutil/imgutils.h"
40 #include "libavutil/mem.h"
43 #include "bytestream.h"
44 #include "codec_internal.h"
47 #define BITMAPINFOHEADER_SIZE 0x28
48 #define TDSF_HEADER_SIZE 0x56
49 #define TDSB_HEADER_SIZE 0x08
51 typedef struct TDSCContext
{
52 AVCodecContext
*jpeg_avctx
; // wrapper context for MJPEG
57 AVFrame
*refframe
; // full decoded frame (without cursor)
58 AVPacket
*jpkt
; // encoded JPEG tile
59 AVFrame
*jpgframe
; // decoded JPEG tile
60 uint8_t *tilebuffer
; // buffer containing tile data
62 /* zlib interaction */
63 uint8_t *deflatebuffer
;
66 /* All that is cursor */
69 int cursor_w
, cursor_h
, cursor_x
, cursor_y
;
70 int cursor_hot_x
, cursor_hot_y
;
73 /* 1 byte bits, 1 byte planes, 2 bytes format (probably) */
74 enum TDSCCursorFormat
{
75 CUR_FMT_MONO
= 0x01010004,
76 CUR_FMT_BGRA
= 0x20010004,
77 CUR_FMT_RGBA
= 0x20010008,
80 static av_cold
int tdsc_close(AVCodecContext
*avctx
)
82 TDSCContext
*ctx
= avctx
->priv_data
;
84 av_frame_free(&ctx
->refframe
);
85 av_frame_free(&ctx
->jpgframe
);
86 av_packet_free(&ctx
->jpkt
);
87 av_freep(&ctx
->deflatebuffer
);
88 av_freep(&ctx
->tilebuffer
);
89 av_freep(&ctx
->cursor
);
90 avcodec_free_context(&ctx
->jpeg_avctx
);
95 static av_cold
int tdsc_init(AVCodecContext
*avctx
)
97 TDSCContext
*ctx
= avctx
->priv_data
;
101 avctx
->pix_fmt
= AV_PIX_FMT_BGR24
;
103 /* These needs to be set to estimate buffer and frame size */
104 if (!(avctx
->width
&& avctx
->height
)) {
105 av_log(avctx
, AV_LOG_ERROR
, "Video size not set.\n");
106 return AVERROR_INVALIDDATA
;
109 /* This value should be large enough for a RAW-only frame plus headers */
110 ctx
->deflatelen
= avctx
->width
* avctx
->height
* (3 + 1);
111 ret
= av_reallocp(&ctx
->deflatebuffer
, ctx
->deflatelen
);
115 /* Allocate reference and JPEG frame */
116 ctx
->refframe
= av_frame_alloc();
117 ctx
->jpgframe
= av_frame_alloc();
118 ctx
->jpkt
= av_packet_alloc();
119 if (!ctx
->refframe
|| !ctx
->jpgframe
|| !ctx
->jpkt
)
120 return AVERROR(ENOMEM
);
122 /* Prepare everything needed for JPEG decoding */
123 codec
= avcodec_find_decoder(AV_CODEC_ID_MJPEG
);
126 ctx
->jpeg_avctx
= avcodec_alloc_context3(codec
);
127 if (!ctx
->jpeg_avctx
)
128 return AVERROR(ENOMEM
);
129 ctx
->jpeg_avctx
->flags
= avctx
->flags
;
130 ctx
->jpeg_avctx
->flags2
= avctx
->flags2
;
131 ctx
->jpeg_avctx
->idct_algo
= avctx
->idct_algo
;
132 ret
= avcodec_open2(ctx
->jpeg_avctx
, codec
, NULL
);
136 /* Set the output pixel format on the reference frame */
137 ctx
->refframe
->format
= avctx
->pix_fmt
;
142 #define APPLY_ALPHA(src, new, alpha) \
143 src = (src * (256 - alpha) + new * alpha) >> 8
145 /* Paint a region over a buffer, without drawing out of its bounds. */
146 static void tdsc_paint_cursor(AVCodecContext
*avctx
, uint8_t *dst
, int stride
)
148 TDSCContext
*ctx
= avctx
->priv_data
;
149 const uint8_t *cursor
= ctx
->cursor
;
150 int x
= ctx
->cursor_x
- ctx
->cursor_hot_x
;
151 int y
= ctx
->cursor_y
- ctx
->cursor_hot_y
;
152 int w
= ctx
->cursor_w
;
153 int h
= ctx
->cursor_h
;
159 if (x
+ w
> ctx
->width
)
161 if (y
+ h
> ctx
->height
)
171 cursor
+= -y
* ctx
->cursor_stride
;
178 for (j
= 0; j
< h
; j
++) {
179 for (i
= 0; i
< w
; i
++) {
180 uint8_t alpha
= cursor
[i
* 4];
181 APPLY_ALPHA(dst
[i
* 3 + 0], cursor
[i
* 4 + 1], alpha
);
182 APPLY_ALPHA(dst
[i
* 3 + 1], cursor
[i
* 4 + 2], alpha
);
183 APPLY_ALPHA(dst
[i
* 3 + 2], cursor
[i
* 4 + 3], alpha
);
186 cursor
+= ctx
->cursor_stride
;
190 /* Load cursor data and store it in ABGR mode. */
191 static int tdsc_load_cursor(AVCodecContext
*avctx
)
193 TDSCContext
*ctx
= avctx
->priv_data
;
194 int i
, j
, k
, ret
, cursor_fmt
;
197 ctx
->cursor_hot_x
= bytestream2_get_le16(&ctx
->gbc
);
198 ctx
->cursor_hot_y
= bytestream2_get_le16(&ctx
->gbc
);
199 ctx
->cursor_w
= bytestream2_get_le16(&ctx
->gbc
);
200 ctx
->cursor_h
= bytestream2_get_le16(&ctx
->gbc
);
202 ctx
->cursor_stride
= FFALIGN(ctx
->cursor_w
, 32) * 4;
203 cursor_fmt
= bytestream2_get_le32(&ctx
->gbc
);
205 if (ctx
->cursor_x
>= avctx
->width
|| ctx
->cursor_y
>= avctx
->height
) {
206 av_log(avctx
, AV_LOG_ERROR
,
207 "Invalid cursor position (%d.%d outside %dx%d).\n",
208 ctx
->cursor_x
, ctx
->cursor_y
, avctx
->width
, avctx
->height
);
209 return AVERROR_INVALIDDATA
;
211 if (ctx
->cursor_w
< 1 || ctx
->cursor_w
> 256 ||
212 ctx
->cursor_h
< 1 || ctx
->cursor_h
> 256) {
213 av_log(avctx
, AV_LOG_ERROR
,
214 "Invalid cursor dimensions %dx%d.\n",
215 ctx
->cursor_w
, ctx
->cursor_h
);
216 return AVERROR_INVALIDDATA
;
218 if (ctx
->cursor_hot_x
> ctx
->cursor_w
||
219 ctx
->cursor_hot_y
> ctx
->cursor_h
) {
220 av_log(avctx
, AV_LOG_WARNING
, "Invalid hotspot position %d.%d.\n",
221 ctx
->cursor_hot_x
, ctx
->cursor_hot_y
);
222 ctx
->cursor_hot_x
= FFMIN(ctx
->cursor_hot_x
, ctx
->cursor_w
- 1);
223 ctx
->cursor_hot_y
= FFMIN(ctx
->cursor_hot_y
, ctx
->cursor_h
- 1);
226 ret
= av_reallocp(&ctx
->cursor
, ctx
->cursor_stride
* ctx
->cursor_h
);
228 av_log(avctx
, AV_LOG_ERROR
, "Cannot allocate cursor buffer.\n");
233 /* here data is packed in BE */
234 switch (cursor_fmt
) {
236 for (j
= 0; j
< ctx
->cursor_h
; j
++) {
237 for (i
= 0; i
< ctx
->cursor_w
; i
+= 32) {
238 uint32_t bits
= bytestream2_get_be32(&ctx
->gbc
);
239 for (k
= 0; k
< 32; k
++) {
240 dst
[0] = !!(bits
& 0x80000000);
245 dst
+= ctx
->cursor_stride
- ctx
->cursor_w
* 4;
249 for (j
= 0; j
< ctx
->cursor_h
; j
++) {
250 for (i
= 0; i
< ctx
->cursor_w
; i
+= 32) {
251 uint32_t bits
= bytestream2_get_be32(&ctx
->gbc
);
252 for (k
= 0; k
< 32; k
++) {
253 int mask_bit
= !!(bits
& 0x80000000);
254 switch (dst
[0] * 2 + mask_bit
) {
277 dst
+= ctx
->cursor_stride
- ctx
->cursor_w
* 4;
282 /* Skip monochrome version of the cursor */
283 bytestream2_skip(&ctx
->gbc
,
284 ctx
->cursor_h
* (FFALIGN(ctx
->cursor_w
, 32) >> 3));
285 if (cursor_fmt
& 8) { // RGBA -> ABGR
286 for (j
= 0; j
< ctx
->cursor_h
; j
++) {
287 for (i
= 0; i
< ctx
->cursor_w
; i
++) {
288 int val
= bytestream2_get_be32(&ctx
->gbc
);
294 dst
+= ctx
->cursor_stride
- ctx
->cursor_w
* 4;
296 } else { // BGRA -> ABGR
297 for (j
= 0; j
< ctx
->cursor_h
; j
++) {
298 for (i
= 0; i
< ctx
->cursor_w
; i
++) {
299 int val
= bytestream2_get_be32(&ctx
->gbc
);
305 dst
+= ctx
->cursor_stride
- ctx
->cursor_w
* 4;
310 avpriv_request_sample(avctx
, "Cursor format %08x", cursor_fmt
);
311 return AVERROR_PATCHWELCOME
;
317 /* Convert a single YUV pixel to RGB. */
318 static inline void tdsc_yuv2rgb(uint8_t *out
, int Y
, int U
, int V
)
320 out
[0] = av_clip_uint8(Y
+ ( 91881 * V
+ 32768 >> 16));
321 out
[1] = av_clip_uint8(Y
+ (-22554 * U
- 46802 * V
+ 32768 >> 16));
322 out
[2] = av_clip_uint8(Y
+ (116130 * U
+ 32768 >> 16));
325 /* Convert a YUV420 buffer to a RGB buffer. */
326 static av_always_inline
void tdsc_blit(uint8_t *dst
, int dst_stride
,
327 const uint8_t *srcy
, int srcy_stride
,
328 const uint8_t *srcu
, const uint8_t *srcv
,
329 int srcuv_stride
, int width
, int height
)
332 for (line
= 0; line
< height
; line
++) {
333 for (col
= 0; col
< width
; col
++)
334 tdsc_yuv2rgb(dst
+ col
* 3, srcy
[col
],
335 srcu
[col
>> 1] - 128, srcv
[col
>> 1] - 128);
339 srcu
+= srcuv_stride
* (line
& 1);
340 srcv
+= srcuv_stride
* (line
& 1);
344 /* Invoke the MJPEG decoder to decode the tile. */
345 static int tdsc_decode_jpeg_tile(AVCodecContext
*avctx
, int tile_size
,
346 int x
, int y
, int w
, int h
)
348 TDSCContext
*ctx
= avctx
->priv_data
;
351 /* Prepare a packet and send to the MJPEG decoder */
352 av_packet_unref(ctx
->jpkt
);
353 ctx
->jpkt
->data
= ctx
->tilebuffer
;
354 ctx
->jpkt
->size
= tile_size
;
356 ret
= avcodec_send_packet(ctx
->jpeg_avctx
, ctx
->jpkt
);
358 av_log(avctx
, AV_LOG_ERROR
, "Error submitting a packet for decoding\n");
362 ret
= avcodec_receive_frame(ctx
->jpeg_avctx
, ctx
->jpgframe
);
363 if (ret
< 0 || ctx
->jpgframe
->format
!= AV_PIX_FMT_YUVJ420P
) {
364 av_log(avctx
, AV_LOG_ERROR
,
365 "JPEG decoding error (%d).\n", ret
);
367 /* Normally skip, error if explode */
368 if (avctx
->err_recognition
& AV_EF_EXPLODE
)
369 return AVERROR_INVALIDDATA
;
374 /* Let's paint onto the buffer */
375 tdsc_blit(ctx
->refframe
->data
[0] + x
* 3 + ctx
->refframe
->linesize
[0] * y
,
376 ctx
->refframe
->linesize
[0],
377 ctx
->jpgframe
->data
[0], ctx
->jpgframe
->linesize
[0],
378 ctx
->jpgframe
->data
[1], ctx
->jpgframe
->data
[2],
379 ctx
->jpgframe
->linesize
[1], w
, h
);
381 av_frame_unref(ctx
->jpgframe
);
386 /* Parse frame and either copy data or decode JPEG. */
387 static int tdsc_decode_tiles(AVCodecContext
*avctx
, int number_tiles
)
389 TDSCContext
*ctx
= avctx
->priv_data
;
392 /* Iterate over the number of tiles */
393 for (i
= 0; i
< number_tiles
; i
++) {
396 int x
, y
, x2
, y2
, w
, h
;
399 if (bytestream2_get_bytes_left(&ctx
->gbc
) < 4 ||
400 bytestream2_get_le32(&ctx
->gbc
) != MKTAG('T','D','S','B') ||
401 bytestream2_get_bytes_left(&ctx
->gbc
) < TDSB_HEADER_SIZE
- 4) {
402 av_log(avctx
, AV_LOG_ERROR
, "TDSB tag is too small.\n");
403 return AVERROR_INVALIDDATA
;
406 tile_size
= bytestream2_get_le32(&ctx
->gbc
);
407 if (bytestream2_get_bytes_left(&ctx
->gbc
) < tile_size
)
408 return AVERROR_INVALIDDATA
;
410 tile_mode
= bytestream2_get_le32(&ctx
->gbc
);
411 bytestream2_skip(&ctx
->gbc
, 4); // unknown
412 x
= bytestream2_get_le32(&ctx
->gbc
);
413 y
= bytestream2_get_le32(&ctx
->gbc
);
414 x2
= bytestream2_get_le32(&ctx
->gbc
);
415 y2
= bytestream2_get_le32(&ctx
->gbc
);
417 if (x
< 0 || y
< 0 || x2
<= x
|| y2
<= y
||
418 x2
> ctx
->width
|| y2
> ctx
->height
420 av_log(avctx
, AV_LOG_ERROR
,
421 "Invalid tile position (%d.%d %d.%d outside %dx%d).\n",
422 x
, y
, x2
, y2
, ctx
->width
, ctx
->height
);
423 return AVERROR_INVALIDDATA
;
428 ret
= av_reallocp(&ctx
->tilebuffer
, tile_size
);
429 if (!ctx
->tilebuffer
)
432 bytestream2_get_buffer(&ctx
->gbc
, ctx
->tilebuffer
, tile_size
);
434 if (tile_mode
== MKTAG('G','E','P','J')) {
435 /* Decode JPEG tile and copy it in the reference frame */
436 ret
= tdsc_decode_jpeg_tile(avctx
, tile_size
, x
, y
, w
, h
);
439 } else if (tile_mode
== MKTAG(' ','W','A','R')) {
440 /* Just copy the buffer to output */
441 av_image_copy_plane(ctx
->refframe
->data
[0] + x
* 3 +
442 ctx
->refframe
->linesize
[0] * y
,
443 ctx
->refframe
->linesize
[0], ctx
->tilebuffer
,
446 av_log(avctx
, AV_LOG_ERROR
, "Unknown tile type %08x.\n", tile_mode
);
447 return AVERROR_INVALIDDATA
;
449 av_log(avctx
, AV_LOG_DEBUG
, "Tile %d, %dx%d (%d.%d)\n", i
, w
, h
, x
, y
);
455 static int tdsc_parse_tdsf(AVCodecContext
*avctx
, int number_tiles
)
457 TDSCContext
*ctx
= avctx
->priv_data
;
458 int ret
, w
, h
, init_refframe
= !ctx
->refframe
->data
[0];
461 * http://msdn.microsoft.com/en-us/library/windows/desktop/dd183376.aspx */
462 if (bytestream2_get_le32(&ctx
->gbc
) != BITMAPINFOHEADER_SIZE
)
463 return AVERROR_INVALIDDATA
;
465 /* Store size, but wait for context reinit before updating avctx */
466 w
= bytestream2_get_le32(&ctx
->gbc
);
467 h
= -bytestream2_get_le32(&ctx
->gbc
);
469 if (bytestream2_get_le16(&ctx
->gbc
) != 1 || // 1 plane
470 bytestream2_get_le16(&ctx
->gbc
) != 24) // BGR24
471 return AVERROR_INVALIDDATA
;
473 bytestream2_skip(&ctx
->gbc
, 24); // unused fields
476 if (avctx
->width
!= w
|| avctx
->height
!= h
) {
477 av_log(avctx
, AV_LOG_DEBUG
, "Size update %dx%d -> %d%d.\n",
478 avctx
->width
, avctx
->height
, ctx
->width
, ctx
->height
);
479 ret
= ff_set_dimensions(avctx
, w
, h
);
484 ctx
->refframe
->width
= ctx
->width
= w
;
485 ctx
->refframe
->height
= ctx
->height
= h
;
487 /* Allocate the reference frame if not already done or on size change */
489 ret
= av_frame_get_buffer(ctx
->refframe
, 0);
494 /* Decode all tiles in a frame */
495 return tdsc_decode_tiles(avctx
, number_tiles
);
498 static int tdsc_parse_dtsm(AVCodecContext
*avctx
)
500 TDSCContext
*ctx
= avctx
->priv_data
;
502 int action
= bytestream2_get_le32(&ctx
->gbc
);
504 bytestream2_skip(&ctx
->gbc
, 4); // some kind of ID or version maybe?
506 if (action
== 2 || action
== 3) {
507 /* Load cursor coordinates */
508 ctx
->cursor_x
= bytestream2_get_le32(&ctx
->gbc
);
509 ctx
->cursor_y
= bytestream2_get_le32(&ctx
->gbc
);
511 /* Load a full cursor sprite */
513 ret
= tdsc_load_cursor(avctx
);
514 /* Do not consider cursor errors fatal unless in explode mode */
515 if (ret
< 0 && (avctx
->err_recognition
& AV_EF_EXPLODE
))
519 avpriv_request_sample(avctx
, "Cursor action %d", action
);
525 static int tdsc_decode_frame(AVCodecContext
*avctx
, AVFrame
*frame
,
526 int *got_frame
, AVPacket
*avpkt
)
528 TDSCContext
*ctx
= avctx
->priv_data
;
529 int ret
, tag_header
, keyframe
= 0;
532 /* Resize deflate buffer on resolution change */
533 if (ctx
->width
!= avctx
->width
|| ctx
->height
!= avctx
->height
) {
534 int deflatelen
= avctx
->width
* avctx
->height
* (3 + 1);
535 if (deflatelen
!= ctx
->deflatelen
) {
536 ctx
->deflatelen
=deflatelen
;
537 ret
= av_reallocp(&ctx
->deflatebuffer
, ctx
->deflatelen
);
544 dlen
= ctx
->deflatelen
;
546 /* Frames are deflated, need to inflate them first */
547 ret
= uncompress(ctx
->deflatebuffer
, &dlen
, avpkt
->data
, avpkt
->size
);
549 av_log(avctx
, AV_LOG_ERROR
, "Deflate error %d.\n", ret
);
550 return AVERROR_UNKNOWN
;
553 bytestream2_init(&ctx
->gbc
, ctx
->deflatebuffer
, dlen
);
555 /* Check for tag and for size info */
556 if (bytestream2_get_bytes_left(&ctx
->gbc
) < 4 + 4) {
557 av_log(avctx
, AV_LOG_ERROR
, "Frame is too small.\n");
558 return AVERROR_INVALIDDATA
;
562 tag_header
= bytestream2_get_le32(&ctx
->gbc
);
564 if (tag_header
== MKTAG('T','D','S','F')) {
566 if (bytestream2_get_bytes_left(&ctx
->gbc
) < TDSF_HEADER_SIZE
) {
567 av_log(avctx
, AV_LOG_ERROR
, "TDSF tag is too small.\n");
568 return AVERROR_INVALIDDATA
;
570 /* First 4 bytes here are the number of GEPJ/WAR tiles in this frame */
571 number_tiles
= bytestream2_get_le32(&ctx
->gbc
);
573 bytestream2_skip(&ctx
->gbc
, 4); // internal timestamp maybe?
574 keyframe
= bytestream2_get_le32(&ctx
->gbc
) == 0x30;
576 ret
= tdsc_parse_tdsf(avctx
, number_tiles
);
580 /* Check if there is anything else we are able to parse */
581 if (bytestream2_get_bytes_left(&ctx
->gbc
) >= 4 + 4)
582 tag_header
= bytestream2_get_le32(&ctx
->gbc
);
585 /* This tag can be after a TDSF block or on its own frame */
586 if (tag_header
== MKTAG('D','T','S','M')) {
587 /* First 4 bytes here are the total size in bytes for this frame */
588 int tag_size
= bytestream2_get_le32(&ctx
->gbc
);
590 if (bytestream2_get_bytes_left(&ctx
->gbc
) < tag_size
) {
591 av_log(avctx
, AV_LOG_ERROR
, "DTSM tag is too small.\n");
592 return AVERROR_INVALIDDATA
;
595 ret
= tdsc_parse_dtsm(avctx
);
600 /* Get the output frame and copy the reference frame */
601 ret
= ff_get_buffer(avctx
, frame
, 0);
605 ret
= av_frame_copy(frame
, ctx
->refframe
);
609 /* Paint the cursor on the output frame */
610 tdsc_paint_cursor(avctx
, frame
->data
[0], frame
->linesize
[0]);
612 /* Frame is ready to be output */
614 frame
->pict_type
= AV_PICTURE_TYPE_I
;
615 frame
->flags
|= AV_FRAME_FLAG_KEY
;
617 frame
->pict_type
= AV_PICTURE_TYPE_P
;
624 const FFCodec ff_tdsc_decoder
= {
626 CODEC_LONG_NAME("TDSC"),
627 .p
.type
= AVMEDIA_TYPE_VIDEO
,
628 .p
.id
= AV_CODEC_ID_TDSC
,
630 FF_CODEC_DECODE_CB(tdsc_decode_frame
),
632 .priv_data_size
= sizeof(TDSCContext
),
633 .p
.capabilities
= AV_CODEC_CAP_DR1
,
634 .caps_internal
= FF_CODEC_CAP_INIT_CLEANUP
,