LCOV - code coverage report
Current view: top level - libavcodec - tdsc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 250 322 77.6 %
Date: 2017-12-11 20:48:03 Functions: 11 11 100.0 %

          Line data    Source code
       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             : 
      39             : #include "libavutil/imgutils.h"
      40             : 
      41             : #include "avcodec.h"
      42             : #include "bytestream.h"
      43             : #include "internal.h"
      44             : 
      45             : #define BITMAPINFOHEADER_SIZE 0x28
      46             : #define TDSF_HEADER_SIZE      0x56
      47             : #define TDSB_HEADER_SIZE      0x08
      48             : 
      49             : typedef struct TDSCContext {
      50             :     AVCodecContext *jpeg_avctx;   // wrapper context for MJPEG
      51             : 
      52             :     int width, height;
      53             :     GetByteContext gbc;
      54             : 
      55             :     AVFrame *refframe;          // full decoded frame (without cursor)
      56             :     AVFrame *jpgframe;          // decoded JPEG tile
      57             :     uint8_t *tilebuffer;        // buffer containing tile data
      58             : 
      59             :     /* zlib interaction */
      60             :     uint8_t *deflatebuffer;
      61             :     uLongf deflatelen;
      62             : 
      63             :     /* All that is cursor */
      64             :     uint8_t    *cursor;
      65             :     int        cursor_stride;
      66             :     int        cursor_w, cursor_h, cursor_x, cursor_y;
      67             :     int        cursor_hot_x, cursor_hot_y;
      68             : } TDSCContext;
      69             : 
      70             : /* 1 byte bits, 1 byte planes, 2 bytes format (probably) */
      71             : enum TDSCCursorFormat {
      72             :     CUR_FMT_MONO = 0x01010004,
      73             :     CUR_FMT_BGRA = 0x20010004,
      74             :     CUR_FMT_RGBA = 0x20010008,
      75             : };
      76             : 
      77           2 : static av_cold int tdsc_close(AVCodecContext *avctx)
      78             : {
      79           2 :     TDSCContext *ctx = avctx->priv_data;
      80             : 
      81           2 :     av_frame_free(&ctx->refframe);
      82           2 :     av_frame_free(&ctx->jpgframe);
      83           2 :     av_freep(&ctx->deflatebuffer);
      84           2 :     av_freep(&ctx->tilebuffer);
      85           2 :     av_freep(&ctx->cursor);
      86           2 :     avcodec_free_context(&ctx->jpeg_avctx);
      87             : 
      88           2 :     return 0;
      89             : }
      90             : 
      91           2 : static av_cold int tdsc_init(AVCodecContext *avctx)
      92             : {
      93           2 :     TDSCContext *ctx = avctx->priv_data;
      94             :     const AVCodec *codec;
      95             :     int ret;
      96             : 
      97           2 :     avctx->pix_fmt = AV_PIX_FMT_BGR24;
      98             : 
      99             :     /* These needs to be set to estimate buffer and frame size */
     100           2 :     if (!(avctx->width && avctx->height)) {
     101           0 :         av_log(avctx, AV_LOG_ERROR, "Video size not set.\n");
     102           0 :         return AVERROR_INVALIDDATA;
     103             :     }
     104             : 
     105             :     /* This value should be large enough for a RAW-only frame plus headers */
     106           2 :     ctx->deflatelen = avctx->width * avctx->height * (3 + 1);
     107           2 :     ret = av_reallocp(&ctx->deflatebuffer, ctx->deflatelen);
     108           2 :     if (ret < 0)
     109           0 :         return ret;
     110             : 
     111             :     /* Allocate reference and JPEG frame */
     112           2 :     ctx->refframe = av_frame_alloc();
     113           2 :     ctx->jpgframe = av_frame_alloc();
     114           2 :     if (!ctx->refframe || !ctx->jpgframe)
     115           0 :         return AVERROR(ENOMEM);
     116             : 
     117             :     /* Prepare everything needed for JPEG decoding */
     118           2 :     codec = avcodec_find_decoder(AV_CODEC_ID_MJPEG);
     119           2 :     if (!codec)
     120           0 :         return AVERROR_BUG;
     121           2 :     ctx->jpeg_avctx = avcodec_alloc_context3(codec);
     122           2 :     if (!ctx->jpeg_avctx)
     123           0 :         return AVERROR(ENOMEM);
     124           2 :     ctx->jpeg_avctx->flags = avctx->flags;
     125           2 :     ctx->jpeg_avctx->flags2 = avctx->flags2;
     126           2 :     ctx->jpeg_avctx->dct_algo = avctx->dct_algo;
     127           2 :     ctx->jpeg_avctx->idct_algo = avctx->idct_algo;
     128           2 :     ret = ff_codec_open2_recursive(ctx->jpeg_avctx, codec, NULL);
     129           2 :     if (ret < 0)
     130           0 :         return ret;
     131             : 
     132             :     /* Set the output pixel format on the reference frame */
     133           2 :     ctx->refframe->format = avctx->pix_fmt;
     134             : 
     135           2 :     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. */
     142          41 : static void tdsc_paint_cursor(AVCodecContext *avctx, uint8_t *dst, int stride)
     143             : {
     144          41 :     TDSCContext *ctx = avctx->priv_data;
     145          41 :     const uint8_t *cursor = ctx->cursor;
     146          41 :     int x = ctx->cursor_x - ctx->cursor_hot_x;
     147          41 :     int y = ctx->cursor_y - ctx->cursor_hot_y;
     148          41 :     int w = ctx->cursor_w;
     149          41 :     int h = ctx->cursor_h;
     150             :     int i, j;
     151             : 
     152          41 :     if (!ctx->cursor)
     153          17 :         return;
     154             : 
     155          24 :     if (x + w > ctx->width)
     156           0 :         w = ctx->width - x;
     157          24 :     if (y + h > ctx->height)
     158           0 :         h = ctx->height - y;
     159          24 :     if (x < 0) {
     160           0 :         w      +=  x;
     161           0 :         cursor += -x * 4;
     162             :     } else {
     163          24 :         dst    +=  x * 3;
     164             :     }
     165          24 :     if (y < 0) {
     166           0 :         h      +=  y;
     167           0 :         cursor += -y * ctx->cursor_stride;
     168             :     } else {
     169          24 :         dst    +=  y * stride;
     170             :     }
     171          24 :     if (w < 0 || h < 0)
     172           0 :         return;
     173             : 
     174         799 :     for (j = 0; j < h; j++) {
     175       25926 :         for (i = 0; i < w; i++) {
     176       25151 :             uint8_t alpha = cursor[i * 4];
     177       25151 :             APPLY_ALPHA(dst[i * 3 + 0], cursor[i * 4 + 1], alpha);
     178       25151 :             APPLY_ALPHA(dst[i * 3 + 1], cursor[i * 4 + 2], alpha);
     179       25151 :             APPLY_ALPHA(dst[i * 3 + 2], cursor[i * 4 + 3], alpha);
     180             :         }
     181         775 :         dst    += stride;
     182         775 :         cursor += ctx->cursor_stride;
     183             :     }
     184             : }
     185             : 
     186             : /* Load cursor data and store it in ABGR mode. */
     187           3 : static int tdsc_load_cursor(AVCodecContext *avctx)
     188             : {
     189           3 :     TDSCContext *ctx  = avctx->priv_data;
     190             :     int i, j, k, ret, bits, cursor_fmt;
     191             :     uint8_t *dst;
     192             : 
     193           3 :     ctx->cursor_hot_x = bytestream2_get_le16(&ctx->gbc);
     194           3 :     ctx->cursor_hot_y = bytestream2_get_le16(&ctx->gbc);
     195           3 :     ctx->cursor_w     = bytestream2_get_le16(&ctx->gbc);
     196           3 :     ctx->cursor_h     = bytestream2_get_le16(&ctx->gbc);
     197             : 
     198           3 :     ctx->cursor_stride = FFALIGN(ctx->cursor_w, 32) * 4;
     199           3 :     cursor_fmt = bytestream2_get_le32(&ctx->gbc);
     200             : 
     201           3 :     if (ctx->cursor_x >= avctx->width || ctx->cursor_y >= avctx->height) {
     202           0 :         av_log(avctx, AV_LOG_ERROR,
     203             :                "Invalid cursor position (%d.%d outside %dx%d).\n",
     204             :                ctx->cursor_x, ctx->cursor_y, avctx->width, avctx->height);
     205           0 :         return AVERROR_INVALIDDATA;
     206             :     }
     207           6 :     if (ctx->cursor_w < 1 || ctx->cursor_w > 256 ||
     208           6 :         ctx->cursor_h < 1 || ctx->cursor_h > 256) {
     209           0 :         av_log(avctx, AV_LOG_ERROR,
     210             :                "Invalid cursor dimensions %dx%d.\n",
     211             :                ctx->cursor_w, ctx->cursor_h);
     212           0 :         return AVERROR_INVALIDDATA;
     213             :     }
     214           6 :     if (ctx->cursor_hot_x > ctx->cursor_w ||
     215           3 :         ctx->cursor_hot_y > ctx->cursor_h) {
     216           0 :         av_log(avctx, AV_LOG_WARNING, "Invalid hotspot position %d.%d.\n",
     217             :                ctx->cursor_hot_x, ctx->cursor_hot_y);
     218           0 :         ctx->cursor_hot_x = FFMIN(ctx->cursor_hot_x, ctx->cursor_w - 1);
     219           0 :         ctx->cursor_hot_y = FFMIN(ctx->cursor_hot_y, ctx->cursor_h - 1);
     220             :     }
     221             : 
     222           3 :     ret = av_reallocp(&ctx->cursor, ctx->cursor_stride * ctx->cursor_h);
     223           3 :     if (ret < 0) {
     224           0 :         av_log(avctx, AV_LOG_ERROR, "Cannot allocate cursor buffer.\n");
     225           0 :         return ret;
     226             :     }
     227             : 
     228           3 :     dst = ctx->cursor;
     229             :     /* here data is packed in BE */
     230           3 :     switch (cursor_fmt) {
     231           2 :     case CUR_FMT_MONO:
     232          66 :         for (j = 0; j < ctx->cursor_h; j++) {
     233         128 :             for (i = 0; i < ctx->cursor_w; i += 32) {
     234          64 :                 bits = bytestream2_get_be32(&ctx->gbc);
     235        2112 :                 for (k = 0; k < 32; k++) {
     236        2048 :                     dst[0] = !!(bits & 0x80000000);
     237        2048 :                     dst   += 4;
     238        2048 :                     bits <<= 1;
     239             :                 }
     240             :             }
     241          64 :             dst += ctx->cursor_stride - ctx->cursor_w * 4;
     242             :         }
     243             : 
     244           2 :         dst = ctx->cursor;
     245          66 :         for (j = 0; j < ctx->cursor_h; j++) {
     246         128 :             for (i = 0; i < ctx->cursor_w; i += 32) {
     247          64 :                 bits = bytestream2_get_be32(&ctx->gbc);
     248        2112 :                 for (k = 0; k < 32; k++) {
     249        2048 :                     int mask_bit = !!(bits & 0x80000000);
     250        2048 :                     switch (dst[0] * 2 + mask_bit) {
     251         104 :                     case 0:
     252         104 :                         dst[0] = 0xFF;
     253         104 :                         dst[1] = 0x00;
     254         104 :                         dst[2] = 0x00;
     255         104 :                         dst[3] = 0x00;
     256         104 :                         break;
     257         178 :                     case 1:
     258         178 :                         dst[0] = 0xFF;
     259         178 :                         dst[1] = 0xFF;
     260         178 :                         dst[2] = 0xFF;
     261         178 :                         dst[3] = 0xFF;
     262         178 :                         break;
     263        1766 :                     default:
     264        1766 :                         dst[0] = 0x00;
     265        1766 :                         dst[1] = 0x00;
     266        1766 :                         dst[2] = 0x00;
     267        1766 :                         dst[3] = 0x00;
     268             :                     }
     269        2048 :                     dst   += 4;
     270        2048 :                     bits <<= 1;
     271             :                 }
     272             :             }
     273          64 :             dst += ctx->cursor_stride - ctx->cursor_w * 4;
     274             :         }
     275           2 :         break;
     276           1 :     case CUR_FMT_BGRA:
     277             :     case CUR_FMT_RGBA:
     278             :         /* Skip monochrome version of the cursor */
     279           1 :         bytestream2_skip(&ctx->gbc,
     280           1 :                          ctx->cursor_h * (FFALIGN(ctx->cursor_w, 32) >> 3));
     281           1 :         if (cursor_fmt & 8) { // RGBA -> ABGR
     282          40 :             for (j = 0; j < ctx->cursor_h; j++) {
     283        1638 :                 for (i = 0; i < ctx->cursor_w; i++) {
     284        1599 :                     int val = bytestream2_get_be32(&ctx->gbc);
     285        1599 :                     *dst++ = val >> 24;
     286        1599 :                     *dst++ = val >> 16;
     287        1599 :                     *dst++ = val >>  8;
     288        1599 :                     *dst++ = val >>  0;
     289             :                 }
     290          39 :                 dst += ctx->cursor_stride - ctx->cursor_w * 4;
     291             :             }
     292             :         } else { // BGRA -> ABGR
     293           0 :             for (j = 0; j < ctx->cursor_h; j++) {
     294           0 :                 for (i = 0; i < ctx->cursor_w; i++) {
     295           0 :                     int val = bytestream2_get_be32(&ctx->gbc);
     296           0 :                     *dst++ = val >>  0;
     297           0 :                     *dst++ = val >> 24;
     298           0 :                     *dst++ = val >> 16;
     299           0 :                     *dst++ = val >>  8;
     300             :                 }
     301           0 :                 dst += ctx->cursor_stride - ctx->cursor_w * 4;
     302             :             }
     303             :         }
     304           1 :         break;
     305           0 :     default:
     306           0 :         avpriv_request_sample(avctx, "Cursor format %08x", cursor_fmt);
     307           0 :         return AVERROR_PATCHWELCOME;
     308             :     }
     309             : 
     310           3 :     return 0;
     311             : }
     312             : 
     313             : /* Convert a single YUV pixel to RGB. */
     314     1231360 : static inline void tdsc_yuv2rgb(uint8_t *out, int Y, int U, int V)
     315             : {
     316     1231360 :     out[0] = av_clip_uint8(Y + (             91881 * V + 32768 >> 16));
     317     1231360 :     out[1] = av_clip_uint8(Y + (-22554 * U - 46802 * V + 32768 >> 16));
     318     1231360 :     out[2] = av_clip_uint8(Y + (116130 * U             + 32768 >> 16));
     319     1231360 : }
     320             : 
     321             : /* Convert a YUV420 buffer to a RGB buffer. */
     322         273 : static av_always_inline void tdsc_blit(uint8_t *dst, int dst_stride,
     323             :                                        const uint8_t *srcy, int srcy_stride,
     324             :                                        const uint8_t *srcu, const uint8_t *srcv,
     325             :                                        int srcuv_stride, int width, int height)
     326             : {
     327             :     int col, line;
     328        8305 :     for (line = 0; line < height; line++) {
     329     1239392 :         for (col = 0; col < width; col++)
     330     2462720 :             tdsc_yuv2rgb(dst + col * 3, srcy[col],
     331     2462720 :                          srcu[col >> 1] - 128, srcv[col >> 1] - 128);
     332             : 
     333        8032 :         dst  +=   dst_stride;
     334        8032 :         srcy +=  srcy_stride;
     335        8032 :         srcu += srcuv_stride * (line & 1);
     336        8032 :         srcv += srcuv_stride * (line & 1);
     337             :     }
     338         273 : }
     339             : 
     340             : /* Invoke the MJPEG decoder to decode the tile. */
     341         273 : static int tdsc_decode_jpeg_tile(AVCodecContext *avctx, int tile_size,
     342             :                                  int x, int y, int w, int h)
     343             : {
     344         273 :     TDSCContext *ctx = avctx->priv_data;
     345             :     AVPacket jpkt;
     346             :     int ret;
     347             : 
     348             :     /* Prepare a packet and send to the MJPEG decoder */
     349         273 :     av_init_packet(&jpkt);
     350         273 :     jpkt.data = ctx->tilebuffer;
     351         273 :     jpkt.size = tile_size;
     352             : 
     353         273 :     ret = avcodec_send_packet(ctx->jpeg_avctx, &jpkt);
     354         273 :     if (ret < 0) {
     355           0 :         av_log(avctx, AV_LOG_ERROR, "Error submitting a packet for decoding\n");
     356           0 :         return ret;
     357             :     }
     358             : 
     359         273 :     ret = avcodec_receive_frame(ctx->jpeg_avctx, ctx->jpgframe);
     360         273 :     if (ret < 0 || ctx->jpgframe->format != AV_PIX_FMT_YUVJ420P) {
     361           0 :         av_log(avctx, AV_LOG_ERROR,
     362             :                "JPEG decoding error (%d).\n", ret);
     363             : 
     364             :         /* Normally skip, error if explode */
     365           0 :         if (avctx->err_recognition & AV_EF_EXPLODE)
     366           0 :             return AVERROR_INVALIDDATA;
     367             :         else
     368           0 :             return 0;
     369             :     }
     370             : 
     371             :     /* Let's paint onto the buffer */
     372         819 :     tdsc_blit(ctx->refframe->data[0] + x * 3 + ctx->refframe->linesize[0] * y,
     373         273 :               ctx->refframe->linesize[0],
     374         546 :               ctx->jpgframe->data[0], ctx->jpgframe->linesize[0],
     375         273 :               ctx->jpgframe->data[1], ctx->jpgframe->data[2],
     376         273 :               ctx->jpgframe->linesize[1], w, h);
     377             : 
     378         273 :     av_frame_unref(ctx->jpgframe);
     379             : 
     380         273 :     return 0;
     381             : }
     382             : 
     383             : /* Parse frame and either copy data or decode JPEG. */
     384          36 : static int tdsc_decode_tiles(AVCodecContext *avctx, int number_tiles)
     385             : {
     386          36 :     TDSCContext *ctx = avctx->priv_data;
     387             :     int i;
     388             : 
     389             :     /* Iterate over the number of tiles */
     390         598 :     for (i = 0; i < number_tiles; i++) {
     391             :         int tile_size;
     392             :         int tile_mode;
     393             :         int x, y, w, h;
     394             :         int ret;
     395             : 
     396        1124 :         if (bytestream2_get_bytes_left(&ctx->gbc) < 4 ||
     397        1124 :             bytestream2_get_le32(&ctx->gbc) != MKTAG('T','D','S','B') ||
     398         562 :             bytestream2_get_bytes_left(&ctx->gbc) < TDSB_HEADER_SIZE - 4) {
     399           0 :             av_log(avctx, AV_LOG_ERROR, "TDSB tag is too small.\n");
     400           0 :             return AVERROR_INVALIDDATA;
     401             :         }
     402             : 
     403         562 :         tile_size = bytestream2_get_le32(&ctx->gbc);
     404         562 :         if (bytestream2_get_bytes_left(&ctx->gbc) < tile_size)
     405           0 :             return AVERROR_INVALIDDATA;
     406             : 
     407         562 :         tile_mode = bytestream2_get_le32(&ctx->gbc);
     408         562 :         bytestream2_skip(&ctx->gbc, 4); // unknown
     409         562 :         x = bytestream2_get_le32(&ctx->gbc);
     410         562 :         y = bytestream2_get_le32(&ctx->gbc);
     411         562 :         w = bytestream2_get_le32(&ctx->gbc) - x;
     412         562 :         h = bytestream2_get_le32(&ctx->gbc) - y;
     413             : 
     414         562 :         if (x >= ctx->width || y >= ctx->height) {
     415           0 :             av_log(avctx, AV_LOG_ERROR,
     416             :                    "Invalid tile position (%d.%d outside %dx%d).\n",
     417             :                    x, y, ctx->width, ctx->height);
     418           0 :             return AVERROR_INVALIDDATA;
     419             :         }
     420         562 :         if (x + w > ctx->width || y + h > ctx->height) {
     421           0 :             av_log(avctx, AV_LOG_ERROR,
     422             :                    "Invalid tile size %dx%d\n", w, h);
     423           0 :             return AVERROR_INVALIDDATA;
     424             :         }
     425             : 
     426         562 :         ret = av_reallocp(&ctx->tilebuffer, tile_size);
     427         562 :         if (!ctx->tilebuffer)
     428           0 :             return ret;
     429             : 
     430         562 :         bytestream2_get_buffer(&ctx->gbc, ctx->tilebuffer, tile_size);
     431             : 
     432         562 :         if (tile_mode == MKTAG('G','E','P','J')) {
     433             :             /* Decode JPEG tile and copy it in the reference frame */
     434         273 :             ret = tdsc_decode_jpeg_tile(avctx, tile_size, x, y, w, h);
     435         273 :             if (ret < 0)
     436           0 :                 return ret;
     437         289 :         } else if (tile_mode == MKTAG(' ','W','A','R')) {
     438             :             /* Just copy the buffer to output */
     439         867 :             av_image_copy_plane(ctx->refframe->data[0] + x * 3 +
     440         289 :                                 ctx->refframe->linesize[0] * y,
     441         289 :                                 ctx->refframe->linesize[0], ctx->tilebuffer,
     442             :                                 w * 3, w * 3, h);
     443             :         } else {
     444           0 :             av_log(avctx, AV_LOG_ERROR, "Unknown tile type %08x.\n", tile_mode);
     445           0 :             return AVERROR_INVALIDDATA;
     446             :         }
     447         562 :         av_log(avctx, AV_LOG_DEBUG, "Tile %d, %dx%d (%d.%d)\n", i, w, h, x, y);
     448             :     }
     449             : 
     450          36 :     return 0;
     451             : }
     452             : 
     453          36 : static int tdsc_parse_tdsf(AVCodecContext *avctx, int number_tiles)
     454             : {
     455          36 :     TDSCContext *ctx = avctx->priv_data;
     456          36 :     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 */
     460          36 :     if (bytestream2_get_le32(&ctx->gbc) != BITMAPINFOHEADER_SIZE)
     461           0 :         return AVERROR_INVALIDDATA;
     462             : 
     463             :     /* Store size, but wait for context reinit before updating avctx */
     464          36 :     w =  bytestream2_get_le32(&ctx->gbc);
     465          36 :     h = -bytestream2_get_le32(&ctx->gbc);
     466             : 
     467          72 :     if (bytestream2_get_le16(&ctx->gbc) != 1 ||  // 1 plane
     468          36 :         bytestream2_get_le16(&ctx->gbc) != 24)   // BGR24
     469           0 :         return AVERROR_INVALIDDATA;
     470             : 
     471          36 :     bytestream2_skip(&ctx->gbc, 24); // unused fields
     472             : 
     473             :     /* Update sizes */
     474          36 :     if (avctx->width != w || avctx->height != h) {
     475           0 :         av_log(avctx, AV_LOG_DEBUG, "Size update %dx%d -> %d%d.\n",
     476             :                avctx->width, avctx->height, ctx->width, ctx->height);
     477           0 :         ret = ff_set_dimensions(avctx, w, h);
     478           0 :         if (ret < 0)
     479           0 :             return ret;
     480           0 :         init_refframe = 1;
     481             :     }
     482          36 :     ctx->refframe->width  = ctx->width  = w;
     483          36 :     ctx->refframe->height = ctx->height = h;
     484             : 
     485             :     /* Allocate the reference frame if not already done or on size change */
     486          36 :     if (init_refframe) {
     487           1 :         ret = av_frame_get_buffer(ctx->refframe, 32);
     488           1 :         if (ret < 0)
     489           0 :             return ret;
     490             :     }
     491             : 
     492             :     /* Decode all tiles in a frame */
     493          36 :     return tdsc_decode_tiles(avctx, number_tiles);
     494             : }
     495             : 
     496          34 : static int tdsc_parse_dtsm(AVCodecContext *avctx)
     497             : {
     498          34 :     TDSCContext *ctx = avctx->priv_data;
     499             :     int ret;
     500          34 :     int action = bytestream2_get_le32(&ctx->gbc);
     501             : 
     502          34 :     bytestream2_skip(&ctx->gbc, 4); // some kind of ID or version maybe?
     503             : 
     504          34 :     if (action == 2 || action == 3) {
     505             :         /* Load cursor coordinates */
     506          34 :         ctx->cursor_x = bytestream2_get_le32(&ctx->gbc);
     507          34 :         ctx->cursor_y = bytestream2_get_le32(&ctx->gbc);
     508             : 
     509             :         /* Load a full cursor sprite */
     510          68 :         if (action == 3) {
     511           3 :             ret = tdsc_load_cursor(avctx);
     512             :             /* Do not consider cursor errors fatal unless in explode mode */
     513           3 :             if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE))
     514           0 :                 return ret;
     515             :         }
     516             :     } else {
     517           0 :         avpriv_request_sample(avctx, "Cursor action %d", action);
     518             :     }
     519             : 
     520          34 :     return 0;
     521             : }
     522             : 
     523          42 : static int tdsc_decode_frame(AVCodecContext *avctx, void *data,
     524             :                              int *got_frame, AVPacket *avpkt)
     525             : {
     526          42 :     TDSCContext *ctx = avctx->priv_data;
     527          42 :     AVFrame *frame = data;
     528          42 :     int ret, tag_header, keyframe = 0;
     529             :     uLongf dlen;
     530             : 
     531             :     /* Resize deflate buffer on resolution change */
     532          42 :     if (ctx->width != avctx->width || ctx->height != avctx->height) {
     533           1 :         ctx->deflatelen = avctx->width * avctx->height * (3 + 1);
     534           1 :         ret = av_reallocp(&ctx->deflatebuffer, ctx->deflatelen);
     535           1 :         if (ret < 0)
     536           0 :             return ret;
     537             :     }
     538          42 :     dlen = ctx->deflatelen;
     539             : 
     540             :     /* Frames are deflated, need to inflate them first */
     541          42 :     ret = uncompress(ctx->deflatebuffer, &dlen, avpkt->data, avpkt->size);
     542          42 :     if (ret) {
     543           1 :         av_log(avctx, AV_LOG_ERROR, "Deflate error %d.\n", ret);
     544           1 :         return AVERROR_UNKNOWN;
     545             :     }
     546             : 
     547          41 :     bytestream2_init(&ctx->gbc, ctx->deflatebuffer, dlen);
     548             : 
     549             :     /* Check for tag and for size info */
     550          41 :     if (bytestream2_get_bytes_left(&ctx->gbc) < 4 + 4) {
     551           0 :         av_log(avctx, AV_LOG_ERROR, "Frame is too small.\n");
     552           0 :         return AVERROR_INVALIDDATA;
     553             :     }
     554             : 
     555             :     /* Read tag */
     556          41 :     tag_header = bytestream2_get_le32(&ctx->gbc);
     557             : 
     558          41 :     if (tag_header == MKTAG('T','D','S','F')) {
     559             :         int number_tiles;
     560          36 :         if (bytestream2_get_bytes_left(&ctx->gbc) < TDSF_HEADER_SIZE) {
     561           0 :             av_log(avctx, AV_LOG_ERROR, "TDSF tag is too small.\n");
     562           0 :             return AVERROR_INVALIDDATA;
     563             :         }
     564             :         /* First 4 bytes here are the number of GEPJ/WAR tiles in this frame */
     565          36 :         number_tiles = bytestream2_get_le32(&ctx->gbc);
     566             : 
     567          36 :         bytestream2_skip(&ctx->gbc, 4); // internal timestamp maybe?
     568          36 :         keyframe = bytestream2_get_le32(&ctx->gbc) == 0x30;
     569             : 
     570          36 :         ret = tdsc_parse_tdsf(avctx, number_tiles);
     571          36 :         if (ret < 0)
     572           0 :             return ret;
     573             : 
     574             :         /* Check if there is anything else we are able to parse */
     575          36 :         if (bytestream2_get_bytes_left(&ctx->gbc) >= 4 + 4)
     576          31 :             tag_header = bytestream2_get_le32(&ctx->gbc);
     577             :     }
     578             : 
     579             :     /* This tag can be after a TDSF block or on its own frame */
     580          41 :     if (tag_header == MKTAG('D','T','S','M')) {
     581             :         /* First 4 bytes here are the total size in bytes for this frame */
     582          34 :         int tag_size = bytestream2_get_le32(&ctx->gbc);
     583             : 
     584          34 :         if (bytestream2_get_bytes_left(&ctx->gbc) < tag_size) {
     585           0 :             av_log(avctx, AV_LOG_ERROR, "DTSM tag is too small.\n");
     586           0 :             return AVERROR_INVALIDDATA;
     587             :         }
     588             : 
     589          34 :         ret = tdsc_parse_dtsm(avctx);
     590          34 :         if (ret < 0)
     591           0 :             return ret;
     592             :     }
     593             : 
     594             :     /* Get the output frame and copy the reference frame */
     595          41 :     ret = ff_get_buffer(avctx, frame, 0);
     596          41 :     if (ret < 0)
     597           0 :         return ret;
     598             : 
     599          41 :     ret = av_frame_copy(frame, ctx->refframe);
     600          41 :     if (ret < 0)
     601           0 :         return ret;
     602             : 
     603             :     /* Paint the cursor on the output frame */
     604          41 :     tdsc_paint_cursor(avctx, frame->data[0], frame->linesize[0]);
     605             : 
     606             :     /* Frame is ready to be output */
     607          41 :     if (keyframe) {
     608           2 :         frame->pict_type = AV_PICTURE_TYPE_I;
     609           2 :         frame->key_frame = 1;
     610             :     } else {
     611          39 :         frame->pict_type = AV_PICTURE_TYPE_P;
     612             :     }
     613          41 :     *got_frame = 1;
     614             : 
     615          41 :     return avpkt->size;
     616             : }
     617             : 
     618             : AVCodec ff_tdsc_decoder = {
     619             :     .name           = "tdsc",
     620             :     .long_name      = NULL_IF_CONFIG_SMALL("TDSC"),
     621             :     .type           = AVMEDIA_TYPE_VIDEO,
     622             :     .id             = AV_CODEC_ID_TDSC,
     623             :     .init           = tdsc_init,
     624             :     .decode         = tdsc_decode_frame,
     625             :     .close          = tdsc_close,
     626             :     .priv_data_size = sizeof(TDSCContext),
     627             :     .capabilities   = AV_CODEC_CAP_DR1,
     628             :     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE |
     629             :                       FF_CODEC_CAP_INIT_CLEANUP,
     630             : };

Generated by: LCOV version 1.13