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