1/* 2 * Electronic Arts TGV Video Decoder 3 * Copyright (c) 2007-2008 Peter Ross 4 * 5 * This file is part of Libav. 6 * 7 * Libav 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 * Libav 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 Libav; 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 "avcodec.h" 32#define BITSTREAM_READER_LE 33#include "get_bits.h" 34#include "libavutil/lzo.h" 35#include "libavutil/imgutils.h" 36 37#define EA_PREAMBLE_SIZE 8 38#define kVGT_TAG MKTAG('k', 'V', 'G', 'T') 39 40typedef struct TgvContext { 41 AVCodecContext *avctx; 42 AVFrame frame; 43 AVFrame last_frame; 44 int width,height; 45 unsigned int palette[AVPALETTE_COUNT]; 46 47 int (*mv_codebook)[2]; 48 unsigned char (*block_codebook)[16]; 49 int num_mvs; ///< current length of mv_codebook 50 int num_blocks_packed; ///< current length of block_codebook 51} TgvContext; 52 53static av_cold int tgv_decode_init(AVCodecContext *avctx){ 54 TgvContext *s = avctx->priv_data; 55 s->avctx = avctx; 56 avctx->time_base = (AVRational){1, 15}; 57 avctx->pix_fmt = PIX_FMT_PAL8; 58 return 0; 59} 60 61/** 62 * Unpack buffer 63 * @return 0 on success, -1 on critical buffer underflow 64 */ 65static int unpack(const uint8_t *src, const uint8_t *src_end, unsigned char *dst, int width, int height) { 66 unsigned char *dst_end = dst + width*height; 67 int size, size1, size2, av_uninit(offset), run; 68 unsigned char *dst_start = dst; 69 70 if (src[0] & 0x01) 71 src += 5; 72 else 73 src += 2; 74 75 if (src+3>src_end) 76 return -1; 77 size = AV_RB24(src); 78 src += 3; 79 80 while(size>0 && src<src_end) { 81 82 /* determine size1 and size2 */ 83 size1 = (src[0] & 3); 84 if ( src[0] & 0x80 ) { // 1 85 if (src[0] & 0x40 ) { // 11 86 if ( src[0] & 0x20 ) { // 111 87 if ( src[0] < 0xFC ) // !(111111) 88 size1 = (((src[0] & 31) + 1) << 2); 89 src++; 90 size2 = 0; 91 } else { // 110 92 offset = ((src[0] & 0x10) << 12) + AV_RB16(&src[1]) + 1; 93 size2 = ((src[0] & 0xC) << 6) + src[3] + 5; 94 src += 4; 95 } 96 } else { // 10 97 size1 = ( ( src[1] & 0xC0) >> 6 ); 98 offset = (AV_RB16(&src[1]) & 0x3FFF) + 1; 99 size2 = (src[0] & 0x3F) + 4; 100 src += 3; 101 } 102 } else { // 0 103 offset = ((src[0] & 0x60) << 3) + src[1] + 1; 104 size2 = ((src[0] & 0x1C) >> 2) + 3; 105 src += 2; 106 } 107 108 109 /* fetch strip from src */ 110 if (size1>src_end-src) 111 break; 112 113 if (size1>0) { 114 size -= size1; 115 run = FFMIN(size1, dst_end-dst); 116 memcpy(dst, src, run); 117 dst += run; 118 src += run; 119 } 120 121 if (size2>0) { 122 if (dst-dst_start<offset) 123 return 0; 124 size -= size2; 125 run = FFMIN(size2, dst_end-dst); 126 av_memcpy_backptr(dst, offset, run); 127 dst += run; 128 } 129 } 130 131 return 0; 132} 133 134/** 135 * Decode inter-frame 136 * @return 0 on success, -1 on critical buffer underflow 137 */ 138static int tgv_decode_inter(TgvContext * s, const uint8_t *buf, const uint8_t *buf_end){ 139 unsigned char *frame0_end = s->last_frame.data[0] + s->avctx->width*s->last_frame.linesize[0]; 140 int num_mvs; 141 int num_blocks_raw; 142 int num_blocks_packed; 143 int vector_bits; 144 int i,j,x,y; 145 GetBitContext gb; 146 int mvbits; 147 const unsigned char *blocks_raw; 148 149 if(buf+12>buf_end) 150 return -1; 151 152 num_mvs = AV_RL16(&buf[0]); 153 num_blocks_raw = AV_RL16(&buf[2]); 154 num_blocks_packed = AV_RL16(&buf[4]); 155 vector_bits = AV_RL16(&buf[6]); 156 buf += 12; 157 158 /* allocate codebook buffers as necessary */ 159 if (num_mvs > s->num_mvs) { 160 s->mv_codebook = av_realloc(s->mv_codebook, num_mvs*2*sizeof(int)); 161 s->num_mvs = num_mvs; 162 } 163 164 if (num_blocks_packed > s->num_blocks_packed) { 165 s->block_codebook = av_realloc(s->block_codebook, num_blocks_packed*16*sizeof(unsigned char)); 166 s->num_blocks_packed = num_blocks_packed; 167 } 168 169 /* read motion vectors */ 170 mvbits = (num_mvs*2*10+31) & ~31; 171 172 if (buf+(mvbits>>3)+16*num_blocks_raw+8*num_blocks_packed>buf_end) 173 return -1; 174 175 init_get_bits(&gb, buf, mvbits); 176 for (i=0; i<num_mvs; i++) { 177 s->mv_codebook[i][0] = get_sbits(&gb, 10); 178 s->mv_codebook[i][1] = get_sbits(&gb, 10); 179 } 180 buf += mvbits>>3; 181 182 /* note ptr to uncompressed blocks */ 183 blocks_raw = buf; 184 buf += num_blocks_raw*16; 185 186 /* read compressed blocks */ 187 init_get_bits(&gb, buf, (buf_end-buf)<<3); 188 for (i=0; i<num_blocks_packed; i++) { 189 int tmp[4]; 190 for(j=0; j<4; j++) 191 tmp[j] = get_bits(&gb, 8); 192 for(j=0; j<16; j++) 193 s->block_codebook[i][15-j] = tmp[get_bits(&gb, 2)]; 194 } 195 196 if (get_bits_left(&gb) < vector_bits * 197 (s->avctx->height/4) * (s->avctx->width/4)) 198 return -1; 199 200 /* read vectors and build frame */ 201 for(y=0; y<s->avctx->height/4; y++) 202 for(x=0; x<s->avctx->width/4; x++) { 203 unsigned int vector = get_bits(&gb, vector_bits); 204 const unsigned char *src; 205 int src_stride; 206 207 if (vector < num_mvs) { 208 src = s->last_frame.data[0] + 209 (y*4 + s->mv_codebook[vector][1])*s->last_frame.linesize[0] + 210 x*4 + s->mv_codebook[vector][0]; 211 src_stride = s->last_frame.linesize[0]; 212 if (src+3*src_stride+3>=frame0_end) 213 continue; 214 }else{ 215 int offset = vector - num_mvs; 216 if (offset<num_blocks_raw) 217 src = blocks_raw + 16*offset; 218 else if (offset-num_blocks_raw<num_blocks_packed) 219 src = s->block_codebook[offset-num_blocks_raw]; 220 else 221 continue; 222 src_stride = 4; 223 } 224 225 for(j=0; j<4; j++) 226 for(i=0; i<4; i++) 227 s->frame.data[0][ (y*4+j)*s->frame.linesize[0] + (x*4+i) ] = 228 src[j*src_stride + i]; 229 } 230 231 return 0; 232} 233 234/** release AVFrame buffers if allocated */ 235static void cond_release_buffer(AVFrame *pic) 236{ 237 if (pic->data[0]) { 238 av_freep(&pic->data[0]); 239 av_free(pic->data[1]); 240 } 241} 242 243static int tgv_decode_frame(AVCodecContext *avctx, 244 void *data, int *data_size, 245 AVPacket *avpkt) 246{ 247 const uint8_t *buf = avpkt->data; 248 int buf_size = avpkt->size; 249 TgvContext *s = avctx->priv_data; 250 const uint8_t *buf_end = buf + buf_size; 251 int chunk_type; 252 253 chunk_type = AV_RL32(&buf[0]); 254 buf += EA_PREAMBLE_SIZE; 255 256 if (chunk_type==kVGT_TAG) { 257 int pal_count, i; 258 if(buf+12>buf_end) { 259 av_log(avctx, AV_LOG_WARNING, "truncated header\n"); 260 return -1; 261 } 262 263 s->width = AV_RL16(&buf[0]); 264 s->height = AV_RL16(&buf[2]); 265 if (s->avctx->width!=s->width || s->avctx->height!=s->height) { 266 avcodec_set_dimensions(s->avctx, s->width, s->height); 267 cond_release_buffer(&s->frame); 268 cond_release_buffer(&s->last_frame); 269 } 270 271 pal_count = AV_RL16(&buf[6]); 272 buf += 12; 273 for(i=0; i<pal_count && i<AVPALETTE_COUNT && buf+2<buf_end; i++) { 274 s->palette[i] = AV_RB24(buf); 275 buf += 3; 276 } 277 } 278 279 if (av_image_check_size(s->width, s->height, 0, avctx)) 280 return -1; 281 282 /* shuffle */ 283 FFSWAP(AVFrame, s->frame, s->last_frame); 284 if (!s->frame.data[0]) { 285 s->frame.reference = 1; 286 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID; 287 s->frame.linesize[0] = s->width; 288 289 /* allocate additional 12 bytes to accommodate av_memcpy_backptr() OUTBUF_PADDED optimisation */ 290 s->frame.data[0] = av_malloc(s->width*s->height + 12); 291 if (!s->frame.data[0]) 292 return AVERROR(ENOMEM); 293 s->frame.data[1] = av_malloc(AVPALETTE_SIZE); 294 if (!s->frame.data[1]) { 295 av_freep(&s->frame.data[0]); 296 return AVERROR(ENOMEM); 297 } 298 } 299 memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE); 300 301 if(chunk_type==kVGT_TAG) { 302 s->frame.key_frame = 1; 303 s->frame.pict_type = AV_PICTURE_TYPE_I; 304 if (unpack(buf, buf_end, s->frame.data[0], s->avctx->width, s->avctx->height)<0) { 305 av_log(avctx, AV_LOG_WARNING, "truncated intra frame\n"); 306 return -1; 307 } 308 }else{ 309 if (!s->last_frame.data[0]) { 310 av_log(avctx, AV_LOG_WARNING, "inter frame without corresponding intra frame\n"); 311 return buf_size; 312 } 313 s->frame.key_frame = 0; 314 s->frame.pict_type = AV_PICTURE_TYPE_P; 315 if (tgv_decode_inter(s, buf, buf_end)<0) { 316 av_log(avctx, AV_LOG_WARNING, "truncated inter frame\n"); 317 return -1; 318 } 319 } 320 321 *data_size = sizeof(AVFrame); 322 *(AVFrame*)data = s->frame; 323 324 return buf_size; 325} 326 327static av_cold int tgv_decode_end(AVCodecContext *avctx) 328{ 329 TgvContext *s = avctx->priv_data; 330 cond_release_buffer(&s->frame); 331 cond_release_buffer(&s->last_frame); 332 av_free(s->mv_codebook); 333 av_free(s->block_codebook); 334 return 0; 335} 336 337AVCodec ff_eatgv_decoder = { 338 .name = "eatgv", 339 .type = AVMEDIA_TYPE_VIDEO, 340 .id = CODEC_ID_TGV, 341 .priv_data_size = sizeof(TgvContext), 342 .init = tgv_decode_init, 343 .close = tgv_decode_end, 344 .decode = tgv_decode_frame, 345 .long_name = NULL_IF_CONFIG_SMALL("Electronic Arts TGV video"), 346}; 347