00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034
00035 #include "libavutil/intreadwrite.h"
00036 #include "avcodec.h"
00037 #include "bytestream.h"
00038 #define BITSTREAM_READER_LE
00039 #include "get_bits.h"
00040
00041 #include "libavutil/lzo.h"
00042
00043 #define RUNTIME_GAMMA 0
00044
00045 #define VGA__TAG MKTAG('V', 'G', 'A', ' ')
00046 #define PALT_TAG MKTAG('P', 'A', 'L', 'T')
00047 #define SHOT_TAG MKTAG('S', 'H', 'O', 'T')
00048 #define PALETTE_COUNT 256
00049 #define PALETTE_SIZE (PALETTE_COUNT * 3)
00050 #define PALETTES_MAX 256
00051
00052 typedef struct XanContext {
00053
00054 AVCodecContext *avctx;
00055 AVFrame last_frame;
00056 AVFrame current_frame;
00057
00058 const unsigned char *buf;
00059 int size;
00060
00061
00062 unsigned char *buffer1;
00063 int buffer1_size;
00064 unsigned char *buffer2;
00065 int buffer2_size;
00066
00067 unsigned *palettes;
00068 int palettes_count;
00069 int cur_palette;
00070
00071 int frame_size;
00072
00073 } XanContext;
00074
00075 static av_cold int xan_decode_init(AVCodecContext *avctx)
00076 {
00077 XanContext *s = avctx->priv_data;
00078
00079 s->avctx = avctx;
00080 s->frame_size = 0;
00081
00082 avctx->pix_fmt = PIX_FMT_PAL8;
00083
00084 s->buffer1_size = avctx->width * avctx->height;
00085 s->buffer1 = av_malloc(s->buffer1_size);
00086 if (!s->buffer1)
00087 return AVERROR(ENOMEM);
00088 s->buffer2_size = avctx->width * avctx->height;
00089 s->buffer2 = av_malloc(s->buffer2_size + 130);
00090 if (!s->buffer2) {
00091 av_freep(&s->buffer1);
00092 return AVERROR(ENOMEM);
00093 }
00094 avcodec_get_frame_defaults(&s->last_frame);
00095 avcodec_get_frame_defaults(&s->current_frame);
00096
00097 return 0;
00098 }
00099
00100 static int xan_huffman_decode(unsigned char *dest, int dest_len,
00101 const unsigned char *src, int src_len)
00102 {
00103 unsigned char byte = *src++;
00104 unsigned char ival = byte + 0x16;
00105 const unsigned char * ptr = src + byte*2;
00106 int ptr_len = src_len - 1 - byte*2;
00107 unsigned char val = ival;
00108 unsigned char *dest_end = dest + dest_len;
00109 GetBitContext gb;
00110
00111 if (ptr_len < 0)
00112 return AVERROR_INVALIDDATA;
00113
00114 init_get_bits(&gb, ptr, ptr_len * 8);
00115
00116 while (val != 0x16) {
00117 unsigned idx = val - 0x17 + get_bits1(&gb) * byte;
00118 if (idx >= 2 * byte)
00119 return -1;
00120 val = src[idx];
00121
00122 if (val < 0x16) {
00123 if (dest >= dest_end)
00124 return 0;
00125 *dest++ = val;
00126 val = ival;
00127 }
00128 }
00129
00130 return 0;
00131 }
00132
00138 static void xan_unpack(unsigned char *dest, int dest_len,
00139 const unsigned char *src, int src_len)
00140 {
00141 unsigned char opcode;
00142 int size;
00143 unsigned char *dest_org = dest;
00144 unsigned char *dest_end = dest + dest_len;
00145 const unsigned char *src_end = src + src_len;
00146
00147 while (dest < dest_end && src < src_end) {
00148 opcode = *src++;
00149
00150 if (opcode < 0xe0) {
00151 int size2, back;
00152 if ((opcode & 0x80) == 0) {
00153 size = opcode & 3;
00154
00155 back = ((opcode & 0x60) << 3) + *src++ + 1;
00156 size2 = ((opcode & 0x1c) >> 2) + 3;
00157 } else if ((opcode & 0x40) == 0) {
00158 size = *src >> 6;
00159
00160 back = (bytestream_get_be16(&src) & 0x3fff) + 1;
00161 size2 = (opcode & 0x3f) + 4;
00162 } else {
00163 size = opcode & 3;
00164
00165 back = ((opcode & 0x10) << 12) + bytestream_get_be16(&src) + 1;
00166 size2 = ((opcode & 0x0c) << 6) + *src++ + 5;
00167 }
00168
00169 if (dest_end - dest < size + size2 ||
00170 dest + size - dest_org < back ||
00171 src_end - src < size)
00172 return;
00173 memcpy(dest, src, size); dest += size; src += size;
00174 av_memcpy_backptr(dest, back, size2);
00175 dest += size2;
00176 } else {
00177 int finish = opcode >= 0xfc;
00178 size = finish ? opcode & 3 : ((opcode & 0x1f) << 2) + 4;
00179
00180 if (dest_end - dest < size || src_end - src < size)
00181 return;
00182 memcpy(dest, src, size); dest += size; src += size;
00183 if (finish)
00184 return;
00185 }
00186 }
00187 }
00188
00189 static inline void xan_wc3_output_pixel_run(XanContext *s,
00190 const unsigned char *pixel_buffer, int x, int y, int pixel_count)
00191 {
00192 int stride;
00193 int line_inc;
00194 int index;
00195 int current_x;
00196 int width = s->avctx->width;
00197 unsigned char *palette_plane;
00198
00199 palette_plane = s->current_frame.data[0];
00200 stride = s->current_frame.linesize[0];
00201 line_inc = stride - width;
00202 index = y * stride + x;
00203 current_x = x;
00204 while (pixel_count && index < s->frame_size) {
00205 int count = FFMIN(pixel_count, width - current_x);
00206 memcpy(palette_plane + index, pixel_buffer, count);
00207 pixel_count -= count;
00208 index += count;
00209 pixel_buffer += count;
00210 current_x += count;
00211
00212 if (current_x >= width) {
00213 index += line_inc;
00214 current_x = 0;
00215 }
00216 }
00217 }
00218
00219 static inline void xan_wc3_copy_pixel_run(XanContext *s, int x, int y,
00220 int pixel_count, int motion_x,
00221 int motion_y)
00222 {
00223 int stride;
00224 int line_inc;
00225 int curframe_index, prevframe_index;
00226 int curframe_x, prevframe_x;
00227 int width = s->avctx->width;
00228 unsigned char *palette_plane, *prev_palette_plane;
00229
00230 if (y + motion_y < 0 || y + motion_y >= s->avctx->height ||
00231 x + motion_x < 0 || x + motion_x >= s->avctx->width)
00232 return;
00233
00234 palette_plane = s->current_frame.data[0];
00235 prev_palette_plane = s->last_frame.data[0];
00236 if (!prev_palette_plane)
00237 prev_palette_plane = palette_plane;
00238 stride = s->current_frame.linesize[0];
00239 line_inc = stride - width;
00240 curframe_index = y * stride + x;
00241 curframe_x = x;
00242 prevframe_index = (y + motion_y) * stride + x + motion_x;
00243 prevframe_x = x + motion_x;
00244 while (pixel_count &&
00245 curframe_index < s->frame_size &&
00246 prevframe_index < s->frame_size) {
00247 int count = FFMIN3(pixel_count, width - curframe_x,
00248 width - prevframe_x);
00249
00250 memcpy(palette_plane + curframe_index,
00251 prev_palette_plane + prevframe_index, count);
00252 pixel_count -= count;
00253 curframe_index += count;
00254 prevframe_index += count;
00255 curframe_x += count;
00256 prevframe_x += count;
00257
00258 if (curframe_x >= width) {
00259 curframe_index += line_inc;
00260 curframe_x = 0;
00261 }
00262
00263 if (prevframe_x >= width) {
00264 prevframe_index += line_inc;
00265 prevframe_x = 0;
00266 }
00267 }
00268 }
00269
00270 static int xan_wc3_decode_frame(XanContext *s) {
00271
00272 int width = s->avctx->width;
00273 int height = s->avctx->height;
00274 int total_pixels = width * height;
00275 unsigned char opcode;
00276 unsigned char flag = 0;
00277 int size = 0;
00278 int motion_x, motion_y;
00279 int x, y;
00280
00281 unsigned char *opcode_buffer = s->buffer1;
00282 unsigned char *opcode_buffer_end = s->buffer1 + s->buffer1_size;
00283 int opcode_buffer_size = s->buffer1_size;
00284 const unsigned char *imagedata_buffer = s->buffer2;
00285
00286
00287 const unsigned char *huffman_segment;
00288 const unsigned char *size_segment;
00289 const unsigned char *vector_segment;
00290 const unsigned char *imagedata_segment;
00291 const unsigned char *buf_end = s->buf + s->size;
00292 int huffman_offset, size_offset, vector_offset, imagedata_offset,
00293 imagedata_size;
00294
00295 if (s->size < 8)
00296 return AVERROR_INVALIDDATA;
00297
00298 huffman_offset = AV_RL16(&s->buf[0]);
00299 size_offset = AV_RL16(&s->buf[2]);
00300 vector_offset = AV_RL16(&s->buf[4]);
00301 imagedata_offset = AV_RL16(&s->buf[6]);
00302
00303 if (huffman_offset >= s->size ||
00304 size_offset >= s->size ||
00305 vector_offset >= s->size ||
00306 imagedata_offset >= s->size)
00307 return AVERROR_INVALIDDATA;
00308
00309 huffman_segment = s->buf + huffman_offset;
00310 size_segment = s->buf + size_offset;
00311 vector_segment = s->buf + vector_offset;
00312 imagedata_segment = s->buf + imagedata_offset;
00313
00314 if (xan_huffman_decode(opcode_buffer, opcode_buffer_size,
00315 huffman_segment, s->size - huffman_offset) < 0)
00316 return AVERROR_INVALIDDATA;
00317
00318 if (imagedata_segment[0] == 2) {
00319 xan_unpack(s->buffer2, s->buffer2_size,
00320 &imagedata_segment[1], s->size - imagedata_offset - 1);
00321 imagedata_size = s->buffer2_size;
00322 } else {
00323 imagedata_size = s->size - imagedata_offset - 1;
00324 imagedata_buffer = &imagedata_segment[1];
00325 }
00326
00327
00328 x = y = 0;
00329 while (total_pixels && opcode_buffer < opcode_buffer_end) {
00330
00331 opcode = *opcode_buffer++;
00332 size = 0;
00333
00334 switch (opcode) {
00335
00336 case 0:
00337 flag ^= 1;
00338 continue;
00339
00340 case 1:
00341 case 2:
00342 case 3:
00343 case 4:
00344 case 5:
00345 case 6:
00346 case 7:
00347 case 8:
00348 size = opcode;
00349 break;
00350
00351 case 12:
00352 case 13:
00353 case 14:
00354 case 15:
00355 case 16:
00356 case 17:
00357 case 18:
00358 size += (opcode - 10);
00359 break;
00360
00361 case 9:
00362 case 19:
00363 size = *size_segment++;
00364 break;
00365
00366 case 10:
00367 case 20:
00368 size = AV_RB16(&size_segment[0]);
00369 size_segment += 2;
00370 break;
00371
00372 case 11:
00373 case 21:
00374 size = AV_RB24(size_segment);
00375 size_segment += 3;
00376 break;
00377 }
00378
00379 if (size > total_pixels)
00380 break;
00381
00382 if (opcode < 12) {
00383 flag ^= 1;
00384 if (flag) {
00385
00386 xan_wc3_copy_pixel_run(s, x, y, size, 0, 0);
00387 } else {
00388
00389 if (imagedata_size < size)
00390 break;
00391 xan_wc3_output_pixel_run(s, imagedata_buffer, x, y, size);
00392 imagedata_buffer += size;
00393 imagedata_size -= size;
00394 }
00395 } else {
00396 if (vector_segment >= buf_end) {
00397 av_log(s->avctx, AV_LOG_ERROR, "vector_segment overread\n");
00398 return AVERROR_INVALIDDATA;
00399 }
00400
00401 motion_x = sign_extend(*vector_segment >> 4, 4);
00402 motion_y = sign_extend(*vector_segment & 0xF, 4);
00403 vector_segment++;
00404
00405
00406 xan_wc3_copy_pixel_run(s, x, y, size, motion_x, motion_y);
00407
00408 flag = 0;
00409 }
00410
00411
00412 total_pixels -= size;
00413 y += (x + size) / width;
00414 x = (x + size) % width;
00415 }
00416 return 0;
00417 }
00418
00419 #if RUNTIME_GAMMA
00420 static inline unsigned mul(unsigned a, unsigned b)
00421 {
00422 return (a * b) >> 16;
00423 }
00424
00425 static inline unsigned pow4(unsigned a)
00426 {
00427 unsigned square = mul(a, a);
00428 return mul(square, square);
00429 }
00430
00431 static inline unsigned pow5(unsigned a)
00432 {
00433 return mul(pow4(a), a);
00434 }
00435
00436 static uint8_t gamma_corr(uint8_t in) {
00437 unsigned lo, hi = 0xff40, target;
00438 int i = 15;
00439 in = (in << 2) | (in >> 6);
00440
00441
00442
00443
00444
00445 lo = target = in << 8;
00446 do {
00447 unsigned mid = (lo + hi) >> 1;
00448 unsigned pow = pow5(mid);
00449 if (pow > target) hi = mid;
00450 else lo = mid;
00451 } while (--i);
00452 return (pow4((lo + hi) >> 1) + 0x80) >> 8;
00453 }
00454 #else
00455
00466 static const uint8_t gamma_lookup[256] = {
00467 0x00, 0x09, 0x10, 0x16, 0x1C, 0x21, 0x27, 0x2C,
00468 0x31, 0x35, 0x3A, 0x3F, 0x43, 0x48, 0x4C, 0x50,
00469 0x54, 0x59, 0x5D, 0x61, 0x65, 0x69, 0x6D, 0x71,
00470 0x75, 0x79, 0x7D, 0x80, 0x84, 0x88, 0x8C, 0x8F,
00471 0x93, 0x97, 0x9A, 0x9E, 0xA2, 0xA5, 0xA9, 0xAC,
00472 0xB0, 0xB3, 0xB7, 0xBA, 0xBE, 0xC1, 0xC5, 0xC8,
00473 0xCB, 0xCF, 0xD2, 0xD5, 0xD9, 0xDC, 0xDF, 0xE3,
00474 0xE6, 0xE9, 0xED, 0xF0, 0xF3, 0xF6, 0xFA, 0xFD,
00475 0x03, 0x0B, 0x12, 0x18, 0x1D, 0x23, 0x28, 0x2D,
00476 0x32, 0x36, 0x3B, 0x40, 0x44, 0x49, 0x4D, 0x51,
00477 0x56, 0x5A, 0x5E, 0x62, 0x66, 0x6A, 0x6E, 0x72,
00478 0x76, 0x7A, 0x7D, 0x81, 0x85, 0x89, 0x8D, 0x90,
00479 0x94, 0x98, 0x9B, 0x9F, 0xA2, 0xA6, 0xAA, 0xAD,
00480 0xB1, 0xB4, 0xB8, 0xBB, 0xBF, 0xC2, 0xC5, 0xC9,
00481 0xCC, 0xD0, 0xD3, 0xD6, 0xDA, 0xDD, 0xE0, 0xE4,
00482 0xE7, 0xEA, 0xED, 0xF1, 0xF4, 0xF7, 0xFA, 0xFD,
00483 0x05, 0x0D, 0x13, 0x19, 0x1F, 0x24, 0x29, 0x2E,
00484 0x33, 0x38, 0x3C, 0x41, 0x45, 0x4A, 0x4E, 0x52,
00485 0x57, 0x5B, 0x5F, 0x63, 0x67, 0x6B, 0x6F, 0x73,
00486 0x77, 0x7B, 0x7E, 0x82, 0x86, 0x8A, 0x8D, 0x91,
00487 0x95, 0x99, 0x9C, 0xA0, 0xA3, 0xA7, 0xAA, 0xAE,
00488 0xB2, 0xB5, 0xB9, 0xBC, 0xBF, 0xC3, 0xC6, 0xCA,
00489 0xCD, 0xD0, 0xD4, 0xD7, 0xDA, 0xDE, 0xE1, 0xE4,
00490 0xE8, 0xEB, 0xEE, 0xF1, 0xF5, 0xF8, 0xFB, 0xFD,
00491 0x07, 0x0E, 0x15, 0x1A, 0x20, 0x25, 0x2A, 0x2F,
00492 0x34, 0x39, 0x3D, 0x42, 0x46, 0x4B, 0x4F, 0x53,
00493 0x58, 0x5C, 0x60, 0x64, 0x68, 0x6C, 0x70, 0x74,
00494 0x78, 0x7C, 0x7F, 0x83, 0x87, 0x8B, 0x8E, 0x92,
00495 0x96, 0x99, 0x9D, 0xA1, 0xA4, 0xA8, 0xAB, 0xAF,
00496 0xB2, 0xB6, 0xB9, 0xBD, 0xC0, 0xC4, 0xC7, 0xCB,
00497 0xCE, 0xD1, 0xD5, 0xD8, 0xDB, 0xDF, 0xE2, 0xE5,
00498 0xE9, 0xEC, 0xEF, 0xF2, 0xF6, 0xF9, 0xFC, 0xFD
00499 };
00500 #endif
00501
00502 static int xan_decode_frame(AVCodecContext *avctx,
00503 void *data, int *data_size,
00504 AVPacket *avpkt)
00505 {
00506 const uint8_t *buf = avpkt->data;
00507 int ret, buf_size = avpkt->size;
00508 XanContext *s = avctx->priv_data;
00509
00510 if (avctx->codec->id == CODEC_ID_XAN_WC3) {
00511 const uint8_t *buf_end = buf + buf_size;
00512 int tag = 0;
00513 while (buf_end - buf > 8 && tag != VGA__TAG) {
00514 unsigned *tmpptr;
00515 uint32_t new_pal;
00516 int size;
00517 int i;
00518 tag = bytestream_get_le32(&buf);
00519 size = bytestream_get_be32(&buf);
00520 if(size < 0) {
00521 av_log(avctx, AV_LOG_ERROR, "Invalid tag size %d\n", size);
00522 return AVERROR_INVALIDDATA;
00523 }
00524 size = FFMIN(size, buf_end - buf);
00525 switch (tag) {
00526 case PALT_TAG:
00527 if (size < PALETTE_SIZE)
00528 return AVERROR_INVALIDDATA;
00529 if (s->palettes_count >= PALETTES_MAX)
00530 return AVERROR_INVALIDDATA;
00531 tmpptr = av_realloc(s->palettes,
00532 (s->palettes_count + 1) * AVPALETTE_SIZE);
00533 if (!tmpptr)
00534 return AVERROR(ENOMEM);
00535 s->palettes = tmpptr;
00536 tmpptr += s->palettes_count * AVPALETTE_COUNT;
00537 for (i = 0; i < PALETTE_COUNT; i++) {
00538 #if RUNTIME_GAMMA
00539 int r = gamma_corr(*buf++);
00540 int g = gamma_corr(*buf++);
00541 int b = gamma_corr(*buf++);
00542 #else
00543 int r = gamma_lookup[*buf++];
00544 int g = gamma_lookup[*buf++];
00545 int b = gamma_lookup[*buf++];
00546 #endif
00547 *tmpptr++ = (0xFFU << 24) | (r << 16) | (g << 8) | b;
00548 }
00549 s->palettes_count++;
00550 break;
00551 case SHOT_TAG:
00552 if (size < 4)
00553 return AVERROR_INVALIDDATA;
00554 new_pal = bytestream_get_le32(&buf);
00555 if (new_pal < s->palettes_count) {
00556 s->cur_palette = new_pal;
00557 } else
00558 av_log(avctx, AV_LOG_ERROR, "Invalid palette selected\n");
00559 break;
00560 case VGA__TAG:
00561 break;
00562 default:
00563 buf += size;
00564 break;
00565 }
00566 }
00567 buf_size = buf_end - buf;
00568 }
00569 if (s->palettes_count <= 0) {
00570 av_log(s->avctx, AV_LOG_ERROR, "No palette found\n");
00571 return AVERROR_INVALIDDATA;
00572 }
00573
00574 if ((ret = avctx->get_buffer(avctx, &s->current_frame))) {
00575 av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00576 return ret;
00577 }
00578 s->current_frame.reference = 3;
00579
00580 if (!s->frame_size)
00581 s->frame_size = s->current_frame.linesize[0] * s->avctx->height;
00582
00583 memcpy(s->current_frame.data[1],
00584 s->palettes + s->cur_palette * AVPALETTE_COUNT, AVPALETTE_SIZE);
00585
00586 s->buf = buf;
00587 s->size = buf_size;
00588
00589 if (xan_wc3_decode_frame(s) < 0)
00590 return AVERROR_INVALIDDATA;
00591
00592
00593 if (s->last_frame.data[0])
00594 avctx->release_buffer(avctx, &s->last_frame);
00595
00596 *data_size = sizeof(AVFrame);
00597 *(AVFrame*)data = s->current_frame;
00598
00599
00600 FFSWAP(AVFrame, s->current_frame, s->last_frame);
00601
00602
00603 return buf_size;
00604 }
00605
00606 static av_cold int xan_decode_end(AVCodecContext *avctx)
00607 {
00608 XanContext *s = avctx->priv_data;
00609
00610
00611 if (s->last_frame.data[0])
00612 avctx->release_buffer(avctx, &s->last_frame);
00613 if (s->current_frame.data[0])
00614 avctx->release_buffer(avctx, &s->current_frame);
00615
00616 av_freep(&s->buffer1);
00617 av_freep(&s->buffer2);
00618 av_freep(&s->palettes);
00619
00620 return 0;
00621 }
00622
00623 AVCodec ff_xan_wc3_decoder = {
00624 .name = "xan_wc3",
00625 .type = AVMEDIA_TYPE_VIDEO,
00626 .id = CODEC_ID_XAN_WC3,
00627 .priv_data_size = sizeof(XanContext),
00628 .init = xan_decode_init,
00629 .close = xan_decode_end,
00630 .decode = xan_decode_frame,
00631 .capabilities = CODEC_CAP_DR1,
00632 .long_name = NULL_IF_CONFIG_SMALL("Wing Commander III / Xan"),
00633 };