annotate ffmpeg/libavcodec/xxan.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 * Wing Commander/Xan Video Decoder
yading@10 3 * Copyright (C) 2011 Konstantin Shishkov
yading@10 4 * based on work by Mike Melanson
yading@10 5 *
yading@10 6 * This file is part of FFmpeg.
yading@10 7 *
yading@10 8 * FFmpeg is free software; you can redistribute it and/or
yading@10 9 * modify it under the terms of the GNU Lesser General Public
yading@10 10 * License as published by the Free Software Foundation; either
yading@10 11 * version 2.1 of the License, or (at your option) any later version.
yading@10 12 *
yading@10 13 * FFmpeg is distributed in the hope that it will be useful,
yading@10 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 16 * Lesser General Public License for more details.
yading@10 17 *
yading@10 18 * You should have received a copy of the GNU Lesser General Public
yading@10 19 * License along with FFmpeg; if not, write to the Free Software
yading@10 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 21 */
yading@10 22
yading@10 23 #include "avcodec.h"
yading@10 24 #include "libavutil/intreadwrite.h"
yading@10 25 #include "libavutil/mem.h"
yading@10 26 #include "bytestream.h"
yading@10 27 #define BITSTREAM_READER_LE
yading@10 28 #include "get_bits.h"
yading@10 29 #include "internal.h"
yading@10 30
yading@10 31 typedef struct XanContext {
yading@10 32 AVCodecContext *avctx;
yading@10 33 AVFrame *pic;
yading@10 34
yading@10 35 uint8_t *y_buffer;
yading@10 36 uint8_t *scratch_buffer;
yading@10 37 int buffer_size;
yading@10 38 GetByteContext gb;
yading@10 39 } XanContext;
yading@10 40
yading@10 41 static av_cold int xan_decode_end(AVCodecContext *avctx);
yading@10 42
yading@10 43 static av_cold int xan_decode_init(AVCodecContext *avctx)
yading@10 44 {
yading@10 45 XanContext *s = avctx->priv_data;
yading@10 46
yading@10 47 s->avctx = avctx;
yading@10 48
yading@10 49 avctx->pix_fmt = AV_PIX_FMT_YUV420P;
yading@10 50
yading@10 51 if (avctx->height < 8) {
yading@10 52 av_log(avctx, AV_LOG_ERROR, "Invalid frame height: %d.\n", avctx->height);
yading@10 53 return AVERROR(EINVAL);
yading@10 54 }
yading@10 55
yading@10 56 s->buffer_size = avctx->width * avctx->height;
yading@10 57 s->y_buffer = av_malloc(s->buffer_size);
yading@10 58 if (!s->y_buffer)
yading@10 59 return AVERROR(ENOMEM);
yading@10 60 s->scratch_buffer = av_malloc(s->buffer_size + 130);
yading@10 61 if (!s->scratch_buffer) {
yading@10 62 xan_decode_end(avctx);
yading@10 63 return AVERROR(ENOMEM);
yading@10 64 }
yading@10 65
yading@10 66 s->pic = av_frame_alloc();
yading@10 67 if (!s->pic) {
yading@10 68 xan_decode_end(avctx);
yading@10 69 return AVERROR(ENOMEM);
yading@10 70 }
yading@10 71
yading@10 72 return 0;
yading@10 73 }
yading@10 74
yading@10 75 static int xan_unpack_luma(XanContext *s,
yading@10 76 uint8_t *dst, const int dst_size)
yading@10 77 {
yading@10 78 int tree_size, eof;
yading@10 79 int bits, mask;
yading@10 80 int tree_root, node;
yading@10 81 const uint8_t *dst_end = dst + dst_size;
yading@10 82 GetByteContext tree = s->gb;
yading@10 83 int start_off = bytestream2_tell(&tree);
yading@10 84
yading@10 85 tree_size = bytestream2_get_byte(&s->gb);
yading@10 86 eof = bytestream2_get_byte(&s->gb);
yading@10 87 tree_root = eof + tree_size;
yading@10 88 bytestream2_skip(&s->gb, tree_size * 2);
yading@10 89
yading@10 90 node = tree_root;
yading@10 91 bits = bytestream2_get_byte(&s->gb);
yading@10 92 mask = 0x80;
yading@10 93 for (;;) {
yading@10 94 int bit = !!(bits & mask);
yading@10 95 mask >>= 1;
yading@10 96 bytestream2_seek(&tree, start_off + node*2 + bit - eof * 2, SEEK_SET);
yading@10 97 node = bytestream2_get_byte(&tree);
yading@10 98 if (node == eof)
yading@10 99 break;
yading@10 100 if (node < eof) {
yading@10 101 *dst++ = node;
yading@10 102 if (dst > dst_end)
yading@10 103 break;
yading@10 104 node = tree_root;
yading@10 105 }
yading@10 106 if (!mask) {
yading@10 107 if (bytestream2_get_bytes_left(&s->gb) <= 0)
yading@10 108 break;
yading@10 109 bits = bytestream2_get_byteu(&s->gb);
yading@10 110 mask = 0x80;
yading@10 111 }
yading@10 112 }
yading@10 113 return dst != dst_end ? AVERROR_INVALIDDATA : 0;
yading@10 114 }
yading@10 115
yading@10 116 /* almost the same as in xan_wc3 decoder */
yading@10 117 static int xan_unpack(XanContext *s,
yading@10 118 uint8_t *dest, const int dest_len)
yading@10 119 {
yading@10 120 uint8_t opcode;
yading@10 121 int size;
yading@10 122 uint8_t *orig_dest = dest;
yading@10 123 const uint8_t *dest_end = dest + dest_len;
yading@10 124
yading@10 125 while (dest < dest_end) {
yading@10 126 if (bytestream2_get_bytes_left(&s->gb) <= 0)
yading@10 127 return AVERROR_INVALIDDATA;
yading@10 128
yading@10 129 opcode = bytestream2_get_byteu(&s->gb);
yading@10 130
yading@10 131 if (opcode < 0xe0) {
yading@10 132 int size2, back;
yading@10 133 if ((opcode & 0x80) == 0) {
yading@10 134 size = opcode & 3;
yading@10 135 back = ((opcode & 0x60) << 3) + bytestream2_get_byte(&s->gb) + 1;
yading@10 136 size2 = ((opcode & 0x1c) >> 2) + 3;
yading@10 137 } else if ((opcode & 0x40) == 0) {
yading@10 138 size = bytestream2_peek_byte(&s->gb) >> 6;
yading@10 139 back = (bytestream2_get_be16(&s->gb) & 0x3fff) + 1;
yading@10 140 size2 = (opcode & 0x3f) + 4;
yading@10 141 } else {
yading@10 142 size = opcode & 3;
yading@10 143 back = ((opcode & 0x10) << 12) + bytestream2_get_be16(&s->gb) + 1;
yading@10 144 size2 = ((opcode & 0x0c) << 6) + bytestream2_get_byte(&s->gb) + 5;
yading@10 145 if (size + size2 > dest_end - dest)
yading@10 146 break;
yading@10 147 }
yading@10 148 if (dest + size + size2 > dest_end ||
yading@10 149 dest - orig_dest + size < back)
yading@10 150 return AVERROR_INVALIDDATA;
yading@10 151 bytestream2_get_buffer(&s->gb, dest, size);
yading@10 152 dest += size;
yading@10 153 av_memcpy_backptr(dest, back, size2);
yading@10 154 dest += size2;
yading@10 155 } else {
yading@10 156 int finish = opcode >= 0xfc;
yading@10 157
yading@10 158 size = finish ? opcode & 3 : ((opcode & 0x1f) << 2) + 4;
yading@10 159 if (dest_end - dest < size)
yading@10 160 return AVERROR_INVALIDDATA;
yading@10 161 bytestream2_get_buffer(&s->gb, dest, size);
yading@10 162 dest += size;
yading@10 163 if (finish)
yading@10 164 break;
yading@10 165 }
yading@10 166 }
yading@10 167 return dest - orig_dest;
yading@10 168 }
yading@10 169
yading@10 170 static int xan_decode_chroma(AVCodecContext *avctx, unsigned chroma_off)
yading@10 171 {
yading@10 172 XanContext *s = avctx->priv_data;
yading@10 173 uint8_t *U, *V;
yading@10 174 int val, uval, vval;
yading@10 175 int i, j;
yading@10 176 const uint8_t *src, *src_end;
yading@10 177 const uint8_t *table;
yading@10 178 int mode, offset, dec_size, table_size;
yading@10 179
yading@10 180 if (!chroma_off)
yading@10 181 return 0;
yading@10 182 if (chroma_off + 4 >= bytestream2_get_bytes_left(&s->gb)) {
yading@10 183 av_log(avctx, AV_LOG_ERROR, "Invalid chroma block position\n");
yading@10 184 return AVERROR_INVALIDDATA;
yading@10 185 }
yading@10 186 bytestream2_seek(&s->gb, chroma_off + 4, SEEK_SET);
yading@10 187 mode = bytestream2_get_le16(&s->gb);
yading@10 188 table = s->gb.buffer;
yading@10 189 table_size = bytestream2_get_le16(&s->gb);
yading@10 190 offset = table_size * 2;
yading@10 191 table_size += 1;
yading@10 192
yading@10 193 if (offset >= bytestream2_get_bytes_left(&s->gb)) {
yading@10 194 av_log(avctx, AV_LOG_ERROR, "Invalid chroma block offset\n");
yading@10 195 return AVERROR_INVALIDDATA;
yading@10 196 }
yading@10 197
yading@10 198 bytestream2_skip(&s->gb, offset);
yading@10 199 memset(s->scratch_buffer, 0, s->buffer_size);
yading@10 200 dec_size = xan_unpack(s, s->scratch_buffer, s->buffer_size);
yading@10 201 if (dec_size < 0) {
yading@10 202 av_log(avctx, AV_LOG_ERROR, "Chroma unpacking failed\n");
yading@10 203 return dec_size;
yading@10 204 }
yading@10 205
yading@10 206 U = s->pic->data[1];
yading@10 207 V = s->pic->data[2];
yading@10 208 src = s->scratch_buffer;
yading@10 209 src_end = src + dec_size;
yading@10 210 if (mode) {
yading@10 211 for (j = 0; j < avctx->height >> 1; j++) {
yading@10 212 for (i = 0; i < avctx->width >> 1; i++) {
yading@10 213 if (src_end - src < 1)
yading@10 214 return 0;
yading@10 215 val = *src++;
yading@10 216 if (val) {
yading@10 217 if (val >= table_size)
yading@10 218 return AVERROR_INVALIDDATA;
yading@10 219 val = AV_RL16(table + (val << 1));
yading@10 220 uval = (val >> 3) & 0xF8;
yading@10 221 vval = (val >> 8) & 0xF8;
yading@10 222 U[i] = uval | (uval >> 5);
yading@10 223 V[i] = vval | (vval >> 5);
yading@10 224 }
yading@10 225 }
yading@10 226 U += s->pic->linesize[1];
yading@10 227 V += s->pic->linesize[2];
yading@10 228 }
yading@10 229 if (avctx->height & 1) {
yading@10 230 memcpy(U, U - s->pic->linesize[1], avctx->width >> 1);
yading@10 231 memcpy(V, V - s->pic->linesize[2], avctx->width >> 1);
yading@10 232 }
yading@10 233 } else {
yading@10 234 uint8_t *U2 = U + s->pic->linesize[1];
yading@10 235 uint8_t *V2 = V + s->pic->linesize[2];
yading@10 236
yading@10 237 for (j = 0; j < avctx->height >> 2; j++) {
yading@10 238 for (i = 0; i < avctx->width >> 1; i += 2) {
yading@10 239 if (src_end - src < 1)
yading@10 240 return 0;
yading@10 241 val = *src++;
yading@10 242 if (val) {
yading@10 243 if (val >= table_size)
yading@10 244 return AVERROR_INVALIDDATA;
yading@10 245 val = AV_RL16(table + (val << 1));
yading@10 246 uval = (val >> 3) & 0xF8;
yading@10 247 vval = (val >> 8) & 0xF8;
yading@10 248 U[i] = U[i+1] = U2[i] = U2[i+1] = uval | (uval >> 5);
yading@10 249 V[i] = V[i+1] = V2[i] = V2[i+1] = vval | (vval >> 5);
yading@10 250 }
yading@10 251 }
yading@10 252 U += s->pic->linesize[1] * 2;
yading@10 253 V += s->pic->linesize[2] * 2;
yading@10 254 U2 += s->pic->linesize[1] * 2;
yading@10 255 V2 += s->pic->linesize[2] * 2;
yading@10 256 }
yading@10 257 if (avctx->height & 3) {
yading@10 258 int lines = ((avctx->height + 1) >> 1) - (avctx->height >> 2) * 2;
yading@10 259
yading@10 260 memcpy(U, U - lines * s->pic->linesize[1], lines * s->pic->linesize[1]);
yading@10 261 memcpy(V, V - lines * s->pic->linesize[2], lines * s->pic->linesize[2]);
yading@10 262 }
yading@10 263 }
yading@10 264
yading@10 265 return 0;
yading@10 266 }
yading@10 267
yading@10 268 static int xan_decode_frame_type0(AVCodecContext *avctx)
yading@10 269 {
yading@10 270 XanContext *s = avctx->priv_data;
yading@10 271 uint8_t *ybuf, *prev_buf, *src = s->scratch_buffer;
yading@10 272 unsigned chroma_off, corr_off;
yading@10 273 int cur, last;
yading@10 274 int i, j;
yading@10 275 int ret;
yading@10 276
yading@10 277 chroma_off = bytestream2_get_le32(&s->gb);
yading@10 278 corr_off = bytestream2_get_le32(&s->gb);
yading@10 279
yading@10 280 if ((ret = xan_decode_chroma(avctx, chroma_off)) != 0)
yading@10 281 return ret;
yading@10 282
yading@10 283 if (corr_off >= bytestream2_size(&s->gb)) {
yading@10 284 av_log(avctx, AV_LOG_WARNING, "Ignoring invalid correction block position\n");
yading@10 285 corr_off = 0;
yading@10 286 }
yading@10 287 bytestream2_seek(&s->gb, 12, SEEK_SET);
yading@10 288 ret = xan_unpack_luma(s, src, s->buffer_size >> 1);
yading@10 289 if (ret) {
yading@10 290 av_log(avctx, AV_LOG_ERROR, "Luma decoding failed\n");
yading@10 291 return ret;
yading@10 292 }
yading@10 293
yading@10 294 ybuf = s->y_buffer;
yading@10 295 last = *src++;
yading@10 296 ybuf[0] = last << 1;
yading@10 297 for (j = 1; j < avctx->width - 1; j += 2) {
yading@10 298 cur = (last + *src++) & 0x1F;
yading@10 299 ybuf[j] = last + cur;
yading@10 300 ybuf[j+1] = cur << 1;
yading@10 301 last = cur;
yading@10 302 }
yading@10 303 if(j < avctx->width)
yading@10 304 ybuf[j] = last << 1;
yading@10 305 prev_buf = ybuf;
yading@10 306 ybuf += avctx->width;
yading@10 307
yading@10 308 for (i = 1; i < avctx->height; i++) {
yading@10 309 last = ((prev_buf[0] >> 1) + *src++) & 0x1F;
yading@10 310 ybuf[0] = last << 1;
yading@10 311 for (j = 1; j < avctx->width - 1; j += 2) {
yading@10 312 cur = ((prev_buf[j + 1] >> 1) + *src++) & 0x1F;
yading@10 313 ybuf[j] = last + cur;
yading@10 314 ybuf[j+1] = cur << 1;
yading@10 315 last = cur;
yading@10 316 }
yading@10 317 if(j < avctx->width)
yading@10 318 ybuf[j] = last << 1;
yading@10 319 prev_buf = ybuf;
yading@10 320 ybuf += avctx->width;
yading@10 321 }
yading@10 322
yading@10 323 if (corr_off) {
yading@10 324 int dec_size;
yading@10 325
yading@10 326 bytestream2_seek(&s->gb, 8 + corr_off, SEEK_SET);
yading@10 327 dec_size = xan_unpack(s, s->scratch_buffer, s->buffer_size / 2);
yading@10 328 if (dec_size < 0)
yading@10 329 dec_size = 0;
yading@10 330 else
yading@10 331 dec_size = FFMIN(dec_size, s->buffer_size/2 - 1);
yading@10 332
yading@10 333 for (i = 0; i < dec_size; i++)
yading@10 334 s->y_buffer[i*2+1] = (s->y_buffer[i*2+1] + (s->scratch_buffer[i] << 1)) & 0x3F;
yading@10 335 }
yading@10 336
yading@10 337 src = s->y_buffer;
yading@10 338 ybuf = s->pic->data[0];
yading@10 339 for (j = 0; j < avctx->height; j++) {
yading@10 340 for (i = 0; i < avctx->width; i++)
yading@10 341 ybuf[i] = (src[i] << 2) | (src[i] >> 3);
yading@10 342 src += avctx->width;
yading@10 343 ybuf += s->pic->linesize[0];
yading@10 344 }
yading@10 345
yading@10 346 return 0;
yading@10 347 }
yading@10 348
yading@10 349 static int xan_decode_frame_type1(AVCodecContext *avctx)
yading@10 350 {
yading@10 351 XanContext *s = avctx->priv_data;
yading@10 352 uint8_t *ybuf, *src = s->scratch_buffer;
yading@10 353 int cur, last;
yading@10 354 int i, j;
yading@10 355 int ret;
yading@10 356
yading@10 357 if ((ret = xan_decode_chroma(avctx, bytestream2_get_le32(&s->gb))) != 0)
yading@10 358 return ret;
yading@10 359
yading@10 360 bytestream2_seek(&s->gb, 16, SEEK_SET);
yading@10 361 ret = xan_unpack_luma(s, src,
yading@10 362 s->buffer_size >> 1);
yading@10 363 if (ret) {
yading@10 364 av_log(avctx, AV_LOG_ERROR, "Luma decoding failed\n");
yading@10 365 return ret;
yading@10 366 }
yading@10 367
yading@10 368 ybuf = s->y_buffer;
yading@10 369 for (i = 0; i < avctx->height; i++) {
yading@10 370 last = (ybuf[0] + (*src++ << 1)) & 0x3F;
yading@10 371 ybuf[0] = last;
yading@10 372 for (j = 1; j < avctx->width - 1; j += 2) {
yading@10 373 cur = (ybuf[j + 1] + (*src++ << 1)) & 0x3F;
yading@10 374 ybuf[j] = (last + cur) >> 1;
yading@10 375 ybuf[j+1] = cur;
yading@10 376 last = cur;
yading@10 377 }
yading@10 378 if(j < avctx->width)
yading@10 379 ybuf[j] = last;
yading@10 380 ybuf += avctx->width;
yading@10 381 }
yading@10 382
yading@10 383 src = s->y_buffer;
yading@10 384 ybuf = s->pic->data[0];
yading@10 385 for (j = 0; j < avctx->height; j++) {
yading@10 386 for (i = 0; i < avctx->width; i++)
yading@10 387 ybuf[i] = (src[i] << 2) | (src[i] >> 3);
yading@10 388 src += avctx->width;
yading@10 389 ybuf += s->pic->linesize[0];
yading@10 390 }
yading@10 391
yading@10 392 return 0;
yading@10 393 }
yading@10 394
yading@10 395 static int xan_decode_frame(AVCodecContext *avctx,
yading@10 396 void *data, int *got_frame,
yading@10 397 AVPacket *avpkt)
yading@10 398 {
yading@10 399 XanContext *s = avctx->priv_data;
yading@10 400 int ftype;
yading@10 401 int ret;
yading@10 402
yading@10 403 if ((ret = ff_reget_buffer(avctx, s->pic)) < 0)
yading@10 404 return ret;
yading@10 405
yading@10 406 bytestream2_init(&s->gb, avpkt->data, avpkt->size);
yading@10 407 ftype = bytestream2_get_le32(&s->gb);
yading@10 408 switch (ftype) {
yading@10 409 case 0:
yading@10 410 ret = xan_decode_frame_type0(avctx);
yading@10 411 break;
yading@10 412 case 1:
yading@10 413 ret = xan_decode_frame_type1(avctx);
yading@10 414 break;
yading@10 415 default:
yading@10 416 av_log(avctx, AV_LOG_ERROR, "Unknown frame type %d\n", ftype);
yading@10 417 return AVERROR_INVALIDDATA;
yading@10 418 }
yading@10 419 if (ret)
yading@10 420 return ret;
yading@10 421
yading@10 422 if ((ret = av_frame_ref(data, s->pic)) < 0)
yading@10 423 return ret;
yading@10 424
yading@10 425 *got_frame = 1;
yading@10 426
yading@10 427 return avpkt->size;
yading@10 428 }
yading@10 429
yading@10 430 static av_cold int xan_decode_end(AVCodecContext *avctx)
yading@10 431 {
yading@10 432 XanContext *s = avctx->priv_data;
yading@10 433
yading@10 434 av_frame_free(&s->pic);
yading@10 435
yading@10 436 av_freep(&s->y_buffer);
yading@10 437 av_freep(&s->scratch_buffer);
yading@10 438
yading@10 439 return 0;
yading@10 440 }
yading@10 441
yading@10 442 AVCodec ff_xan_wc4_decoder = {
yading@10 443 .name = "xan_wc4",
yading@10 444 .type = AVMEDIA_TYPE_VIDEO,
yading@10 445 .id = AV_CODEC_ID_XAN_WC4,
yading@10 446 .priv_data_size = sizeof(XanContext),
yading@10 447 .init = xan_decode_init,
yading@10 448 .close = xan_decode_end,
yading@10 449 .decode = xan_decode_frame,
yading@10 450 .capabilities = CODEC_CAP_DR1,
yading@10 451 .long_name = NULL_IF_CONFIG_SMALL("Wing Commander IV / Xxan"),
yading@10 452 };