LCOV - code coverage report
Current view: top level - libavcodec - eatgv.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 154 181 85.1 %
Date: 2017-12-16 13:57:32 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Electronic Arts TGV Video Decoder
       3             :  * Copyright (c) 2007-2008 Peter Ross
       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 St, Fifth Floor, Boston, MA  02110-1301  USA
      20             :  */
      21             : 
      22             : /**
      23             :  * @file
      24             :  * Electronic Arts TGV Video Decoder
      25             :  * by Peter Ross (pross@xvid.org)
      26             :  *
      27             :  * Technical details here:
      28             :  * http://wiki.multimedia.cx/index.php?title=Electronic_Arts_TGV
      29             :  */
      30             : 
      31             : #include "libavutil/imgutils.h"
      32             : #include "libavutil/mem.h"
      33             : 
      34             : #define BITSTREAM_READER_LE
      35             : #include "avcodec.h"
      36             : #include "get_bits.h"
      37             : #include "internal.h"
      38             : 
      39             : #define EA_PREAMBLE_SIZE    8
      40             : #define kVGT_TAG MKTAG('k', 'V', 'G', 'T')
      41             : 
      42             : typedef struct TgvContext {
      43             :     AVCodecContext *avctx;
      44             :     AVFrame *last_frame;
      45             :     uint8_t *frame_buffer;
      46             :     int width,height;
      47             :     uint32_t palette[AVPALETTE_COUNT];
      48             : 
      49             :     int (*mv_codebook)[2];
      50             :     uint8_t (*block_codebook)[16];
      51             :     int num_mvs;           ///< current length of mv_codebook
      52             :     int num_blocks_packed; ///< current length of block_codebook
      53             : } TgvContext;
      54             : 
      55           6 : static av_cold int tgv_decode_init(AVCodecContext *avctx)
      56             : {
      57           6 :     TgvContext *s = avctx->priv_data;
      58           6 :     s->avctx         = avctx;
      59           6 :     avctx->framerate = (AVRational){ 15, 1 };
      60           6 :     avctx->pix_fmt   = AV_PIX_FMT_PAL8;
      61             : 
      62           6 :     s->last_frame = av_frame_alloc();
      63           6 :     if (!s->last_frame)
      64           0 :         return AVERROR(ENOMEM);
      65             : 
      66           6 :     return 0;
      67             : }
      68             : 
      69             : /**
      70             :  * Unpack buffer
      71             :  * @return 0 on success, -1 on critical buffer underflow
      72             :  */
      73          11 : static int unpack(const uint8_t *src, const uint8_t *src_end,
      74             :                   uint8_t *dst, int width, int height)
      75             : {
      76          11 :     uint8_t *dst_end = dst + width*height;
      77             :     int size, size1, size2, offset, run;
      78          11 :     uint8_t *dst_start = dst;
      79             : 
      80          11 :     if (src[0] & 0x01)
      81           0 :         src += 5;
      82             :     else
      83          11 :         src += 2;
      84             : 
      85          11 :     if (src_end - src < 3)
      86           0 :         return AVERROR_INVALIDDATA;
      87          11 :     size = AV_RB24(src);
      88          11 :     src += 3;
      89             : 
      90      102040 :     while (size > 0 && src < src_end) {
      91             : 
      92             :         /* determine size1 and size2 */
      93      102018 :         size1 = (src[0] & 3);
      94      102018 :         if (src[0] & 0x80) {  // 1
      95       49446 :             if (src[0] & 0x40 ) {  // 11
      96       15234 :                 if (src[0] & 0x20) {  // 111
      97       10712 :                     if (src[0] < 0xFC)  // !(111111)
      98       10704 :                         size1 = (((src[0] & 31) + 1) << 2);
      99       10712 :                     src++;
     100       10712 :                     size2 = 0;
     101             :                 } else {  // 110
     102        4522 :                     offset = ((src[0] & 0x10) << 12) + AV_RB16(&src[1]) + 1;
     103        4522 :                     size2  = ((src[0] & 0xC) << 6) + src[3] + 5;
     104        4522 :                     src   += 4;
     105             :                 }
     106             :             } else {  // 10
     107       34212 :                 size1  = ((src[1] & 0xC0) >> 6);
     108       34212 :                 offset = (AV_RB16(&src[1]) & 0x3FFF) + 1;
     109       34212 :                 size2  = (src[0] & 0x3F) + 4;
     110       34212 :                 src   += 3;
     111             :             }
     112             :         } else {  // 0
     113       52572 :             offset = ((src[0] & 0x60) << 3) + src[1] + 1;
     114       52572 :             size2  = ((src[0] & 0x1C) >> 2) + 3;
     115       52572 :             src   += 2;
     116             :         }
     117             : 
     118             : 
     119             :         /* fetch strip from src */
     120      102018 :         if (size1 > src_end - src)
     121           0 :             break;
     122             : 
     123      102018 :         if (size1 > 0) {
     124       35301 :             size -= size1;
     125       35301 :             run   = FFMIN(size1, dst_end - dst);
     126       35301 :             memcpy(dst, src, run);
     127       35301 :             dst += run;
     128       35301 :             src += run;
     129             :         }
     130             : 
     131      102018 :         if (size2 > 0) {
     132       91306 :             if (dst - dst_start < offset)
     133           0 :                 return 0;
     134       91306 :             size -= size2;
     135       91306 :             run   = FFMIN(size2, dst_end - dst);
     136       91306 :             av_memcpy_backptr(dst, offset, run);
     137       91306 :             dst += run;
     138             :         }
     139             :     }
     140             : 
     141          11 :     return 0;
     142             : }
     143             : 
     144             : /**
     145             :  * Decode inter-frame
     146             :  * @return 0 on success, -1 on critical buffer underflow
     147             :  */
     148          79 : static int tgv_decode_inter(TgvContext *s, AVFrame *frame,
     149             :                             const uint8_t *buf, const uint8_t *buf_end)
     150             : {
     151             :     int num_mvs;
     152             :     int num_blocks_raw;
     153             :     int num_blocks_packed;
     154             :     int vector_bits;
     155             :     int i,j,x,y;
     156             :     GetBitContext gb;
     157             :     int mvbits;
     158             :     const uint8_t *blocks_raw;
     159             : 
     160          79 :     if(buf_end - buf < 12)
     161           0 :         return AVERROR_INVALIDDATA;
     162             : 
     163          79 :     num_mvs           = AV_RL16(&buf[0]);
     164          79 :     num_blocks_raw    = AV_RL16(&buf[2]);
     165          79 :     num_blocks_packed = AV_RL16(&buf[4]);
     166          79 :     vector_bits       = AV_RL16(&buf[6]);
     167          79 :     buf += 12;
     168             : 
     169          79 :     if (vector_bits > MIN_CACHE_BITS || !vector_bits) {
     170           0 :         av_log(s->avctx, AV_LOG_ERROR,
     171             :                "Invalid value for motion vector bits: %d\n", vector_bits);
     172           0 :         return AVERROR_INVALIDDATA;
     173             :     }
     174             : 
     175             :     /* allocate codebook buffers as necessary */
     176          79 :     if (num_mvs > s->num_mvs) {
     177           8 :         int err = av_reallocp_array(&s->mv_codebook, num_mvs, sizeof(*s->mv_codebook));
     178           8 :         if (err < 0) {
     179           0 :             s->num_mvs = 0;
     180           0 :             return err;
     181             :         }
     182           8 :         s->num_mvs = num_mvs;
     183             :     }
     184             : 
     185          79 :     if (num_blocks_packed > s->num_blocks_packed) {
     186             :         int err;
     187           7 :         if ((err = av_reallocp(&s->block_codebook, num_blocks_packed * 16)) < 0) {
     188           0 :             s->num_blocks_packed = 0;
     189           0 :             return err;
     190             :         }
     191           7 :         s->num_blocks_packed = num_blocks_packed;
     192             :     }
     193             : 
     194             :     /* read motion vectors */
     195          79 :     mvbits = (num_mvs * 2 * 10 + 31) & ~31;
     196             : 
     197          79 :     if (buf_end - buf < (mvbits>>3) + 16*num_blocks_raw + 8*num_blocks_packed)
     198           0 :         return AVERROR_INVALIDDATA;
     199             : 
     200          79 :     init_get_bits(&gb, buf, mvbits);
     201       13453 :     for (i = 0; i < num_mvs; i++) {
     202       13374 :         s->mv_codebook[i][0] = get_sbits(&gb, 10);
     203       13374 :         s->mv_codebook[i][1] = get_sbits(&gb, 10);
     204             :     }
     205          79 :     buf += mvbits >> 3;
     206             : 
     207             :     /* note ptr to uncompressed blocks */
     208          79 :     blocks_raw = buf;
     209          79 :     buf       += num_blocks_raw * 16;
     210             : 
     211             :     /* read compressed blocks */
     212          79 :     init_get_bits(&gb, buf, (buf_end - buf) << 3);
     213       31502 :     for (i = 0; i < num_blocks_packed; i++) {
     214             :         int tmp[4];
     215      157115 :         for (j = 0; j < 4; j++)
     216      125692 :             tmp[j] = get_bits(&gb, 8);
     217      534191 :         for (j = 0; j < 16; j++)
     218      502768 :             s->block_codebook[i][15-j] = tmp[get_bits(&gb, 2)];
     219             :     }
     220             : 
     221         237 :     if (get_bits_left(&gb) < vector_bits *
     222         158 :         (s->avctx->height / 4) * (s->avctx->width / 4))
     223           1 :         return AVERROR_INVALIDDATA;
     224             : 
     225             :     /* read vectors and build frame */
     226        4418 :     for (y = 0; y < s->avctx->height / 4; y++)
     227      351540 :         for (x = 0; x < s->avctx->width / 4; x++) {
     228      347200 :             unsigned int vector = get_bits(&gb, vector_bits);
     229             :             const uint8_t *src;
     230             :             ptrdiff_t src_stride;
     231             : 
     232      347200 :             if (vector < num_mvs) {
     233      293708 :                 int mx = x * 4 + s->mv_codebook[vector][0];
     234      293708 :                 int my = y * 4 + s->mv_codebook[vector][1];
     235             : 
     236      293708 :                 if (mx < 0 || mx + 4 > s->avctx->width ||
     237      293708 :                     my < 0 || my + 4 > s->avctx->height) {
     238           0 :                     av_log(s->avctx, AV_LOG_ERROR, "MV %d %d out of picture\n", mx, my);
     239           0 :                     continue;
     240             :                 }
     241             : 
     242      293708 :                 src = s->last_frame->data[0] + mx + my * s->last_frame->linesize[0];
     243      293708 :                 src_stride = s->last_frame->linesize[0];
     244             :             } else {
     245       53492 :                 int offset = vector - num_mvs;
     246       53492 :                 if (offset < num_blocks_raw)
     247        5411 :                     src = blocks_raw + 16*offset;
     248       48081 :                 else if (offset - num_blocks_raw < num_blocks_packed)
     249       48081 :                     src = s->block_codebook[offset - num_blocks_raw];
     250             :                 else
     251           0 :                     continue;
     252       53492 :                 src_stride = 4;
     253             :             }
     254             : 
     255     1736000 :             for (j = 0; j < 4; j++)
     256     6944000 :                 for (i = 0; i < 4; i++)
     257    11110400 :                     frame->data[0][(y * 4 + j) * frame->linesize[0] + (x * 4 + i)] =
     258    11110400 :                         src[j * src_stride + i];
     259             :     }
     260             : 
     261          78 :     return 0;
     262             : }
     263             : 
     264          90 : static int tgv_decode_frame(AVCodecContext *avctx,
     265             :                             void *data, int *got_frame,
     266             :                             AVPacket *avpkt)
     267             : {
     268          90 :     const uint8_t *buf     = avpkt->data;
     269          90 :     int buf_size           = avpkt->size;
     270          90 :     TgvContext *s          = avctx->priv_data;
     271          90 :     const uint8_t *buf_end = buf + buf_size;
     272          90 :     AVFrame *frame         = data;
     273             :     int chunk_type, ret;
     274             : 
     275          90 :     if (buf_end - buf < EA_PREAMBLE_SIZE)
     276           0 :         return AVERROR_INVALIDDATA;
     277             : 
     278          90 :     chunk_type = AV_RL32(&buf[0]);
     279          90 :     buf       += EA_PREAMBLE_SIZE;
     280             : 
     281          90 :     if (chunk_type == kVGT_TAG) {
     282             :         int pal_count, i;
     283          11 :         if(buf_end - buf < 12) {
     284           0 :             av_log(avctx, AV_LOG_WARNING, "truncated header\n");
     285           0 :             return AVERROR_INVALIDDATA;
     286             :         }
     287             : 
     288          11 :         s->width  = AV_RL16(&buf[0]);
     289          11 :         s->height = AV_RL16(&buf[2]);
     290          11 :         if (s->avctx->width != s->width || s->avctx->height != s->height) {
     291           4 :             av_freep(&s->frame_buffer);
     292           4 :             av_frame_unref(s->last_frame);
     293           4 :             if ((ret = ff_set_dimensions(s->avctx, s->width, s->height)) < 0)
     294           0 :                 return ret;
     295             :         }
     296             : 
     297          11 :         pal_count = AV_RL16(&buf[6]);
     298          11 :         buf += 12;
     299        2827 :         for(i = 0; i < pal_count && i < AVPALETTE_COUNT && buf_end - buf >= 3; i++) {
     300        2816 :             s->palette[i] = 0xFFU << 24 | AV_RB24(buf);
     301        2816 :             buf += 3;
     302             :         }
     303             :     }
     304             : 
     305          90 :     if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
     306           0 :         return ret;
     307             : 
     308          90 :     memcpy(frame->data[1], s->palette, AVPALETTE_SIZE);
     309             : 
     310          90 :     if (chunk_type == kVGT_TAG) {
     311             :         int y;
     312          11 :         frame->key_frame = 1;
     313          11 :         frame->pict_type = AV_PICTURE_TYPE_I;
     314             : 
     315          17 :         if (!s->frame_buffer &&
     316           6 :             !(s->frame_buffer = av_mallocz(s->width * s->height)))
     317           0 :             return AVERROR(ENOMEM);
     318             : 
     319          11 :         if (unpack(buf, buf_end, s->frame_buffer, s->avctx->width, s->avctx->height) < 0) {
     320           0 :             av_log(avctx, AV_LOG_WARNING, "truncated intra frame\n");
     321           0 :             return AVERROR_INVALIDDATA;
     322             :         }
     323        2411 :         for (y = 0; y < s->height; y++)
     324        4800 :             memcpy(frame->data[0]  + y * frame->linesize[0],
     325        2400 :                    s->frame_buffer + y * s->width,
     326        2400 :                    s->width);
     327             :     } else {
     328          79 :         if (!s->last_frame->data[0]) {
     329           0 :             av_log(avctx, AV_LOG_WARNING, "inter frame without corresponding intra frame\n");
     330           0 :             return buf_size;
     331             :         }
     332          79 :         frame->key_frame = 0;
     333          79 :         frame->pict_type = AV_PICTURE_TYPE_P;
     334          79 :         if (tgv_decode_inter(s, frame, buf, buf_end) < 0) {
     335           1 :             av_log(avctx, AV_LOG_WARNING, "truncated inter frame\n");
     336           1 :             return AVERROR_INVALIDDATA;
     337             :         }
     338             :     }
     339             : 
     340          89 :     av_frame_unref(s->last_frame);
     341          89 :     if ((ret = av_frame_ref(s->last_frame, frame)) < 0)
     342           0 :         return ret;
     343             : 
     344          89 :     *got_frame = 1;
     345             : 
     346          89 :     return buf_size;
     347             : }
     348             : 
     349           6 : static av_cold int tgv_decode_end(AVCodecContext *avctx)
     350             : {
     351           6 :     TgvContext *s = avctx->priv_data;
     352           6 :     av_frame_free(&s->last_frame);
     353           6 :     av_freep(&s->frame_buffer);
     354           6 :     av_freep(&s->mv_codebook);
     355           6 :     av_freep(&s->block_codebook);
     356           6 :     return 0;
     357             : }
     358             : 
     359             : AVCodec ff_eatgv_decoder = {
     360             :     .name           = "eatgv",
     361             :     .long_name      = NULL_IF_CONFIG_SMALL("Electronic Arts TGV video"),
     362             :     .type           = AVMEDIA_TYPE_VIDEO,
     363             :     .id             = AV_CODEC_ID_TGV,
     364             :     .priv_data_size = sizeof(TgvContext),
     365             :     .init           = tgv_decode_init,
     366             :     .close          = tgv_decode_end,
     367             :     .decode         = tgv_decode_frame,
     368             :     .capabilities   = AV_CODEC_CAP_DR1,
     369             : };

Generated by: LCOV version 1.13