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