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