annotate ffmpeg/libavcodec/eatgv.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * Electronic Arts TGV Video Decoder
yading@10 3 * Copyright (c) 2007-2008 Peter Ross
yading@10 4 *
yading@10 5 * This file is part of FFmpeg.
yading@10 6 *
yading@10 7 * FFmpeg is free software; you can redistribute it and/or
yading@10 8 * modify it under the terms of the GNU Lesser General Public
yading@10 9 * License as published by the Free Software Foundation; either
yading@10 10 * version 2.1 of the License, or (at your option) any later version.
yading@10 11 *
yading@10 12 * FFmpeg is distributed in the hope that it will be useful,
yading@10 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 15 * Lesser General Public License for more details.
yading@10 16 *
yading@10 17 * You should have received a copy of the GNU Lesser General Public
yading@10 18 * License along with FFmpeg; if not, write to the Free Software
yading@10 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 20 */
yading@10 21
yading@10 22 /**
yading@10 23 * @file
yading@10 24 * Electronic Arts TGV Video Decoder
yading@10 25 * by Peter Ross (pross@xvid.org)
yading@10 26 *
yading@10 27 * Technical details here:
yading@10 28 * http://wiki.multimedia.cx/index.php?title=Electronic_Arts_TGV
yading@10 29 */
yading@10 30
yading@10 31 #include "avcodec.h"
yading@10 32 #define BITSTREAM_READER_LE
yading@10 33 #include "get_bits.h"
yading@10 34 #include "internal.h"
yading@10 35 #include "libavutil/imgutils.h"
yading@10 36 #include "libavutil/mem.h"
yading@10 37
yading@10 38 #define EA_PREAMBLE_SIZE 8
yading@10 39 #define kVGT_TAG MKTAG('k', 'V', 'G', 'T')
yading@10 40
yading@10 41 typedef struct TgvContext {
yading@10 42 AVCodecContext *avctx;
yading@10 43 AVFrame last_frame;
yading@10 44 uint8_t *frame_buffer;
yading@10 45 int width,height;
yading@10 46 uint32_t palette[AVPALETTE_COUNT];
yading@10 47
yading@10 48 int (*mv_codebook)[2];
yading@10 49 uint8_t (*block_codebook)[16];
yading@10 50 int num_mvs; ///< current length of mv_codebook
yading@10 51 int num_blocks_packed; ///< current length of block_codebook
yading@10 52 } TgvContext;
yading@10 53
yading@10 54 static av_cold int tgv_decode_init(AVCodecContext *avctx)
yading@10 55 {
yading@10 56 TgvContext *s = avctx->priv_data;
yading@10 57 s->avctx = avctx;
yading@10 58 avctx->time_base = (AVRational){1, 15};
yading@10 59 avctx->pix_fmt = AV_PIX_FMT_PAL8;
yading@10 60 avcodec_get_frame_defaults(&s->last_frame);
yading@10 61 return 0;
yading@10 62 }
yading@10 63
yading@10 64 /**
yading@10 65 * Unpack buffer
yading@10 66 * @return 0 on success, -1 on critical buffer underflow
yading@10 67 */
yading@10 68 static int unpack(const uint8_t *src, const uint8_t *src_end,
yading@10 69 uint8_t *dst, int width, int height)
yading@10 70 {
yading@10 71 uint8_t *dst_end = dst + width*height;
yading@10 72 int size, size1, size2, offset, run;
yading@10 73 uint8_t *dst_start = dst;
yading@10 74
yading@10 75 if (src[0] & 0x01)
yading@10 76 src += 5;
yading@10 77 else
yading@10 78 src += 2;
yading@10 79
yading@10 80 if (src_end - src < 3)
yading@10 81 return AVERROR_INVALIDDATA;
yading@10 82 size = AV_RB24(src);
yading@10 83 src += 3;
yading@10 84
yading@10 85 while (size > 0 && src < src_end) {
yading@10 86
yading@10 87 /* determine size1 and size2 */
yading@10 88 size1 = (src[0] & 3);
yading@10 89 if (src[0] & 0x80) { // 1
yading@10 90 if (src[0] & 0x40 ) { // 11
yading@10 91 if (src[0] & 0x20) { // 111
yading@10 92 if (src[0] < 0xFC) // !(111111)
yading@10 93 size1 = (((src[0] & 31) + 1) << 2);
yading@10 94 src++;
yading@10 95 size2 = 0;
yading@10 96 } else { // 110
yading@10 97 offset = ((src[0] & 0x10) << 12) + AV_RB16(&src[1]) + 1;
yading@10 98 size2 = ((src[0] & 0xC) << 6) + src[3] + 5;
yading@10 99 src += 4;
yading@10 100 }
yading@10 101 } else { // 10
yading@10 102 size1 = ((src[1] & 0xC0) >> 6);
yading@10 103 offset = (AV_RB16(&src[1]) & 0x3FFF) + 1;
yading@10 104 size2 = (src[0] & 0x3F) + 4;
yading@10 105 src += 3;
yading@10 106 }
yading@10 107 } else { // 0
yading@10 108 offset = ((src[0] & 0x60) << 3) + src[1] + 1;
yading@10 109 size2 = ((src[0] & 0x1C) >> 2) + 3;
yading@10 110 src += 2;
yading@10 111 }
yading@10 112
yading@10 113
yading@10 114 /* fetch strip from src */
yading@10 115 if (size1 > src_end - src)
yading@10 116 break;
yading@10 117
yading@10 118 if (size1 > 0) {
yading@10 119 size -= size1;
yading@10 120 run = FFMIN(size1, dst_end - dst);
yading@10 121 memcpy(dst, src, run);
yading@10 122 dst += run;
yading@10 123 src += run;
yading@10 124 }
yading@10 125
yading@10 126 if (size2 > 0) {
yading@10 127 if (dst - dst_start < offset)
yading@10 128 return 0;
yading@10 129 size -= size2;
yading@10 130 run = FFMIN(size2, dst_end - dst);
yading@10 131 av_memcpy_backptr(dst, offset, run);
yading@10 132 dst += run;
yading@10 133 }
yading@10 134 }
yading@10 135
yading@10 136 return 0;
yading@10 137 }
yading@10 138
yading@10 139 /**
yading@10 140 * Decode inter-frame
yading@10 141 * @return 0 on success, -1 on critical buffer underflow
yading@10 142 */
yading@10 143 static int tgv_decode_inter(TgvContext *s, AVFrame *frame,
yading@10 144 const uint8_t *buf, const uint8_t *buf_end)
yading@10 145 {
yading@10 146 int num_mvs;
yading@10 147 int num_blocks_raw;
yading@10 148 int num_blocks_packed;
yading@10 149 int vector_bits;
yading@10 150 int i,j,x,y;
yading@10 151 GetBitContext gb;
yading@10 152 int mvbits;
yading@10 153 const uint8_t *blocks_raw;
yading@10 154
yading@10 155 if(buf_end - buf < 12)
yading@10 156 return AVERROR_INVALIDDATA;
yading@10 157
yading@10 158 num_mvs = AV_RL16(&buf[0]);
yading@10 159 num_blocks_raw = AV_RL16(&buf[2]);
yading@10 160 num_blocks_packed = AV_RL16(&buf[4]);
yading@10 161 vector_bits = AV_RL16(&buf[6]);
yading@10 162 buf += 12;
yading@10 163
yading@10 164 if (vector_bits > MIN_CACHE_BITS || !vector_bits) {
yading@10 165 av_log(s->avctx, AV_LOG_ERROR,
yading@10 166 "Invalid value for motion vector bits: %d\n", vector_bits);
yading@10 167 return AVERROR_INVALIDDATA;
yading@10 168 }
yading@10 169
yading@10 170 /* allocate codebook buffers as necessary */
yading@10 171 if (num_mvs > s->num_mvs) {
yading@10 172 s->mv_codebook = av_realloc(s->mv_codebook, num_mvs*2*sizeof(int));
yading@10 173 s->num_mvs = num_mvs;
yading@10 174 }
yading@10 175
yading@10 176 if (num_blocks_packed > s->num_blocks_packed) {
yading@10 177 s->block_codebook = av_realloc(s->block_codebook, num_blocks_packed*16);
yading@10 178 s->num_blocks_packed = num_blocks_packed;
yading@10 179 }
yading@10 180
yading@10 181 /* read motion vectors */
yading@10 182 mvbits = (num_mvs * 2 * 10 + 31) & ~31;
yading@10 183
yading@10 184 if (buf_end - buf < (mvbits>>3) + 16*num_blocks_raw + 8*num_blocks_packed)
yading@10 185 return AVERROR_INVALIDDATA;
yading@10 186
yading@10 187 init_get_bits(&gb, buf, mvbits);
yading@10 188 for (i = 0; i < num_mvs; i++) {
yading@10 189 s->mv_codebook[i][0] = get_sbits(&gb, 10);
yading@10 190 s->mv_codebook[i][1] = get_sbits(&gb, 10);
yading@10 191 }
yading@10 192 buf += mvbits >> 3;
yading@10 193
yading@10 194 /* note ptr to uncompressed blocks */
yading@10 195 blocks_raw = buf;
yading@10 196 buf += num_blocks_raw * 16;
yading@10 197
yading@10 198 /* read compressed blocks */
yading@10 199 init_get_bits(&gb, buf, (buf_end - buf) << 3);
yading@10 200 for (i = 0; i < num_blocks_packed; i++) {
yading@10 201 int tmp[4];
yading@10 202 for (j = 0; j < 4; j++)
yading@10 203 tmp[j] = get_bits(&gb, 8);
yading@10 204 for (j = 0; j < 16; j++)
yading@10 205 s->block_codebook[i][15-j] = tmp[get_bits(&gb, 2)];
yading@10 206 }
yading@10 207
yading@10 208 if (get_bits_left(&gb) < vector_bits *
yading@10 209 (s->avctx->height / 4) * (s->avctx->width / 4))
yading@10 210 return AVERROR_INVALIDDATA;
yading@10 211
yading@10 212 /* read vectors and build frame */
yading@10 213 for (y = 0; y < s->avctx->height / 4; y++)
yading@10 214 for (x = 0; x < s->avctx->width / 4; x++) {
yading@10 215 unsigned int vector = get_bits(&gb, vector_bits);
yading@10 216 const uint8_t *src;
yading@10 217 int src_stride;
yading@10 218
yading@10 219 if (vector < num_mvs) {
yading@10 220 int mx = x * 4 + s->mv_codebook[vector][0];
yading@10 221 int my = y * 4 + s->mv_codebook[vector][1];
yading@10 222
yading@10 223 if (mx < 0 || mx + 4 > s->avctx->width ||
yading@10 224 my < 0 || my + 4 > s->avctx->height) {
yading@10 225 av_log(s->avctx, AV_LOG_ERROR, "MV %d %d out of picture\n", mx, my);
yading@10 226 continue;
yading@10 227 }
yading@10 228
yading@10 229 src = s->last_frame.data[0] + mx + my * s->last_frame.linesize[0];
yading@10 230 src_stride = s->last_frame.linesize[0];
yading@10 231 } else {
yading@10 232 int offset = vector - num_mvs;
yading@10 233 if (offset < num_blocks_raw)
yading@10 234 src = blocks_raw + 16*offset;
yading@10 235 else if (offset - num_blocks_raw < num_blocks_packed)
yading@10 236 src = s->block_codebook[offset - num_blocks_raw];
yading@10 237 else
yading@10 238 continue;
yading@10 239 src_stride = 4;
yading@10 240 }
yading@10 241
yading@10 242 for (j = 0; j < 4; j++)
yading@10 243 for (i = 0; i < 4; i++)
yading@10 244 frame->data[0][(y * 4 + j) * frame->linesize[0] + (x * 4 + i)] =
yading@10 245 src[j * src_stride + i];
yading@10 246 }
yading@10 247
yading@10 248 return 0;
yading@10 249 }
yading@10 250
yading@10 251 static int tgv_decode_frame(AVCodecContext *avctx,
yading@10 252 void *data, int *got_frame,
yading@10 253 AVPacket *avpkt)
yading@10 254 {
yading@10 255 const uint8_t *buf = avpkt->data;
yading@10 256 int buf_size = avpkt->size;
yading@10 257 TgvContext *s = avctx->priv_data;
yading@10 258 const uint8_t *buf_end = buf + buf_size;
yading@10 259 AVFrame *frame = data;
yading@10 260 int chunk_type, ret;
yading@10 261
yading@10 262 if (buf_end - buf < EA_PREAMBLE_SIZE)
yading@10 263 return AVERROR_INVALIDDATA;
yading@10 264
yading@10 265 chunk_type = AV_RL32(&buf[0]);
yading@10 266 buf += EA_PREAMBLE_SIZE;
yading@10 267
yading@10 268 if (chunk_type == kVGT_TAG) {
yading@10 269 int pal_count, i;
yading@10 270 if(buf_end - buf < 12) {
yading@10 271 av_log(avctx, AV_LOG_WARNING, "truncated header\n");
yading@10 272 return AVERROR_INVALIDDATA;
yading@10 273 }
yading@10 274
yading@10 275 s->width = AV_RL16(&buf[0]);
yading@10 276 s->height = AV_RL16(&buf[2]);
yading@10 277 if (s->avctx->width != s->width || s->avctx->height != s->height) {
yading@10 278 avcodec_set_dimensions(s->avctx, s->width, s->height);
yading@10 279 av_freep(&s->frame_buffer);
yading@10 280 av_frame_unref(&s->last_frame);
yading@10 281 }
yading@10 282
yading@10 283 pal_count = AV_RL16(&buf[6]);
yading@10 284 buf += 12;
yading@10 285 for(i = 0; i < pal_count && i < AVPALETTE_COUNT && buf_end - buf >= 3; i++) {
yading@10 286 s->palette[i] = 0xFFU << 24 | AV_RB24(buf);
yading@10 287 buf += 3;
yading@10 288 }
yading@10 289 }
yading@10 290
yading@10 291 if ((ret = av_image_check_size(s->width, s->height, 0, avctx)) < 0)
yading@10 292 return ret;
yading@10 293
yading@10 294 if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
yading@10 295 return ret;
yading@10 296
yading@10 297 memcpy(frame->data[1], s->palette, AVPALETTE_SIZE);
yading@10 298
yading@10 299 if (chunk_type == kVGT_TAG) {
yading@10 300 int y;
yading@10 301 frame->key_frame = 1;
yading@10 302 frame->pict_type = AV_PICTURE_TYPE_I;
yading@10 303
yading@10 304 if (!s->frame_buffer &&
yading@10 305 !(s->frame_buffer = av_malloc(s->width * s->height)))
yading@10 306 return AVERROR(ENOMEM);
yading@10 307
yading@10 308 if (unpack(buf, buf_end, s->frame_buffer, s->avctx->width, s->avctx->height) < 0) {
yading@10 309 av_log(avctx, AV_LOG_WARNING, "truncated intra frame\n");
yading@10 310 return AVERROR_INVALIDDATA;
yading@10 311 }
yading@10 312 for (y = 0; y < s->height; y++)
yading@10 313 memcpy(frame->data[0] + y * frame->linesize[0],
yading@10 314 s->frame_buffer + y * s->width,
yading@10 315 s->width);
yading@10 316 } else {
yading@10 317 if (!s->last_frame.data[0]) {
yading@10 318 av_log(avctx, AV_LOG_WARNING, "inter frame without corresponding intra frame\n");
yading@10 319 return buf_size;
yading@10 320 }
yading@10 321 frame->key_frame = 0;
yading@10 322 frame->pict_type = AV_PICTURE_TYPE_P;
yading@10 323 if (tgv_decode_inter(s, frame, buf, buf_end) < 0) {
yading@10 324 av_log(avctx, AV_LOG_WARNING, "truncated inter frame\n");
yading@10 325 return AVERROR_INVALIDDATA;
yading@10 326 }
yading@10 327 }
yading@10 328
yading@10 329 av_frame_unref(&s->last_frame);
yading@10 330 if ((ret = av_frame_ref(&s->last_frame, frame)) < 0)
yading@10 331 return ret;
yading@10 332
yading@10 333 *got_frame = 1;
yading@10 334
yading@10 335 return buf_size;
yading@10 336 }
yading@10 337
yading@10 338 static av_cold int tgv_decode_end(AVCodecContext *avctx)
yading@10 339 {
yading@10 340 TgvContext *s = avctx->priv_data;
yading@10 341 av_frame_unref(&s->last_frame);
yading@10 342 av_freep(&s->frame_buffer);
yading@10 343 av_free(s->mv_codebook);
yading@10 344 av_free(s->block_codebook);
yading@10 345 return 0;
yading@10 346 }
yading@10 347
yading@10 348 AVCodec ff_eatgv_decoder = {
yading@10 349 .name = "eatgv",
yading@10 350 .type = AVMEDIA_TYPE_VIDEO,
yading@10 351 .id = AV_CODEC_ID_TGV,
yading@10 352 .priv_data_size = sizeof(TgvContext),
yading@10 353 .init = tgv_decode_init,
yading@10 354 .close = tgv_decode_end,
yading@10 355 .decode = tgv_decode_frame,
yading@10 356 .long_name = NULL_IF_CONFIG_SMALL("Electronic Arts TGV video"),
yading@10 357 .capabilities = CODEC_CAP_DR1,
yading@10 358 };