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 #if RUNTIME_GAMMA
00362 static inline unsigned mul(unsigned a, unsigned b)
00363 {
00364 return (a * b) >> 16;
00365 }
00366
00367 static inline unsigned pow4(unsigned a)
00368 {
00369 unsigned square = mul(a, a);
00370 return mul(square, square);
00371 }
00372
00373 static inline unsigned pow5(unsigned a)
00374 {
00375 return mul(pow4(a), a);
00376 }
00377
00378 static uint8_t gamma_corr(uint8_t in) {
00379 unsigned lo, hi = 0xff40, target;
00380 int i = 15;
00381 in = (in << 2) | (in >> 6);
00382
00383
00384
00385
00386
00387 lo = target = in << 8;
00388 do {
00389 unsigned mid = (lo + hi) >> 1;
00390 unsigned pow = pow5(mid);
00391 if (pow > target) hi = mid;
00392 else lo = mid;
00393 } while (--i);
00394 return (pow4((lo + hi) >> 1) + 0x80) >> 8;
00395 }
00396 #else
00397
00408 static const uint8_t gamma_lookup[256] = {
00409 0x00, 0x09, 0x10, 0x16, 0x1C, 0x21, 0x27, 0x2C,
00410 0x31, 0x35, 0x3A, 0x3F, 0x43, 0x48, 0x4C, 0x50,
00411 0x54, 0x59, 0x5D, 0x61, 0x65, 0x69, 0x6D, 0x71,
00412 0x75, 0x79, 0x7D, 0x80, 0x84, 0x88, 0x8C, 0x8F,
00413 0x93, 0x97, 0x9A, 0x9E, 0xA2, 0xA5, 0xA9, 0xAC,
00414 0xB0, 0xB3, 0xB7, 0xBA, 0xBE, 0xC1, 0xC5, 0xC8,
00415 0xCB, 0xCF, 0xD2, 0xD5, 0xD9, 0xDC, 0xDF, 0xE3,
00416 0xE6, 0xE9, 0xED, 0xF0, 0xF3, 0xF6, 0xFA, 0xFD,
00417 0x03, 0x0B, 0x12, 0x18, 0x1D, 0x23, 0x28, 0x2D,
00418 0x32, 0x36, 0x3B, 0x40, 0x44, 0x49, 0x4D, 0x51,
00419 0x56, 0x5A, 0x5E, 0x62, 0x66, 0x6A, 0x6E, 0x72,
00420 0x76, 0x7A, 0x7D, 0x81, 0x85, 0x89, 0x8D, 0x90,
00421 0x94, 0x98, 0x9B, 0x9F, 0xA2, 0xA6, 0xAA, 0xAD,
00422 0xB1, 0xB4, 0xB8, 0xBB, 0xBF, 0xC2, 0xC5, 0xC9,
00423 0xCC, 0xD0, 0xD3, 0xD6, 0xDA, 0xDD, 0xE0, 0xE4,
00424 0xE7, 0xEA, 0xED, 0xF1, 0xF4, 0xF7, 0xFA, 0xFD,
00425 0x05, 0x0D, 0x13, 0x19, 0x1F, 0x24, 0x29, 0x2E,
00426 0x33, 0x38, 0x3C, 0x41, 0x45, 0x4A, 0x4E, 0x52,
00427 0x57, 0x5B, 0x5F, 0x63, 0x67, 0x6B, 0x6F, 0x73,
00428 0x77, 0x7B, 0x7E, 0x82, 0x86, 0x8A, 0x8D, 0x91,
00429 0x95, 0x99, 0x9C, 0xA0, 0xA3, 0xA7, 0xAA, 0xAE,
00430 0xB2, 0xB5, 0xB9, 0xBC, 0xBF, 0xC3, 0xC6, 0xCA,
00431 0xCD, 0xD0, 0xD4, 0xD7, 0xDA, 0xDE, 0xE1, 0xE4,
00432 0xE8, 0xEB, 0xEE, 0xF1, 0xF5, 0xF8, 0xFB, 0xFD,
00433 0x07, 0x0E, 0x15, 0x1A, 0x20, 0x25, 0x2A, 0x2F,
00434 0x34, 0x39, 0x3D, 0x42, 0x46, 0x4B, 0x4F, 0x53,
00435 0x58, 0x5C, 0x60, 0x64, 0x68, 0x6C, 0x70, 0x74,
00436 0x78, 0x7C, 0x7F, 0x83, 0x87, 0x8B, 0x8E, 0x92,
00437 0x96, 0x99, 0x9D, 0xA1, 0xA4, 0xA8, 0xAB, 0xAF,
00438 0xB2, 0xB6, 0xB9, 0xBD, 0xC0, 0xC4, 0xC7, 0xCB,
00439 0xCE, 0xD1, 0xD5, 0xD8, 0xDB, 0xDF, 0xE2, 0xE5,
00440 0xE9, 0xEC, 0xEF, 0xF2, 0xF6, 0xF9, 0xFC, 0xFD
00441 };
00442 #endif
00443
00444 static int xan_decode_frame(AVCodecContext *avctx,
00445 void *data, int *data_size,
00446 AVPacket *avpkt)
00447 {
00448 const uint8_t *buf = avpkt->data;
00449 int ret, buf_size = avpkt->size;
00450 XanContext *s = avctx->priv_data;
00451
00452 if (avctx->codec->id == CODEC_ID_XAN_WC3) {
00453 const uint8_t *buf_end = buf + buf_size;
00454 int tag = 0;
00455 while (buf_end - buf > 8 && tag != VGA__TAG) {
00456 unsigned *tmpptr;
00457 uint32_t new_pal;
00458 int size;
00459 int i;
00460 tag = bytestream_get_le32(&buf);
00461 size = bytestream_get_be32(&buf);
00462 size = FFMIN(size, buf_end - buf);
00463 switch (tag) {
00464 case PALT_TAG:
00465 if (size < PALETTE_SIZE)
00466 return AVERROR_INVALIDDATA;
00467 if (s->palettes_count >= PALETTES_MAX)
00468 return AVERROR_INVALIDDATA;
00469 tmpptr = av_realloc(s->palettes, (s->palettes_count + 1) * AVPALETTE_SIZE);
00470 if (!tmpptr)
00471 return AVERROR(ENOMEM);
00472 s->palettes = tmpptr;
00473 tmpptr += s->palettes_count * AVPALETTE_COUNT;
00474 for (i = 0; i < PALETTE_COUNT; i++) {
00475 #if RUNTIME_GAMMA
00476 int r = gamma_corr(*buf++);
00477 int g = gamma_corr(*buf++);
00478 int b = gamma_corr(*buf++);
00479 #else
00480 int r = gamma_lookup[*buf++];
00481 int g = gamma_lookup[*buf++];
00482 int b = gamma_lookup[*buf++];
00483 #endif
00484 *tmpptr++ = (r << 16) | (g << 8) | b;
00485 }
00486 s->palettes_count++;
00487 break;
00488 case SHOT_TAG:
00489 if (size < 4)
00490 return AVERROR_INVALIDDATA;
00491 new_pal = bytestream_get_le32(&buf);
00492 if (new_pal < s->palettes_count) {
00493 s->cur_palette = new_pal;
00494 } else
00495 av_log(avctx, AV_LOG_ERROR, "Invalid palette selected\n");
00496 break;
00497 case VGA__TAG:
00498 break;
00499 default:
00500 buf += size;
00501 break;
00502 }
00503 }
00504 buf_size = buf_end - buf;
00505 }
00506 if ((ret = avctx->get_buffer(avctx, &s->current_frame))) {
00507 av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00508 return ret;
00509 }
00510 s->current_frame.reference = 3;
00511
00512 if (!s->frame_size)
00513 s->frame_size = s->current_frame.linesize[0] * s->avctx->height;
00514
00515 memcpy(s->current_frame.data[1], s->palettes + s->cur_palette * AVPALETTE_COUNT, AVPALETTE_SIZE);
00516
00517 s->buf = buf;
00518 s->size = buf_size;
00519
00520 xan_wc3_decode_frame(s);
00521
00522
00523 if (s->last_frame.data[0])
00524 avctx->release_buffer(avctx, &s->last_frame);
00525
00526 *data_size = sizeof(AVFrame);
00527 *(AVFrame*)data = s->current_frame;
00528
00529
00530 FFSWAP(AVFrame, s->current_frame, s->last_frame);
00531
00532
00533 return buf_size;
00534 }
00535
00536 static av_cold int xan_decode_end(AVCodecContext *avctx)
00537 {
00538 XanContext *s = avctx->priv_data;
00539
00540
00541 if (s->last_frame.data[0])
00542 avctx->release_buffer(avctx, &s->last_frame);
00543 if (s->current_frame.data[0])
00544 avctx->release_buffer(avctx, &s->current_frame);
00545
00546 av_freep(&s->buffer1);
00547 av_freep(&s->buffer2);
00548 av_freep(&s->palettes);
00549
00550 return 0;
00551 }
00552
00553 AVCodec ff_xan_wc3_decoder = {
00554 "xan_wc3",
00555 AVMEDIA_TYPE_VIDEO,
00556 CODEC_ID_XAN_WC3,
00557 sizeof(XanContext),
00558 xan_decode_init,
00559 NULL,
00560 xan_decode_end,
00561 xan_decode_frame,
00562 CODEC_CAP_DR1,
00563 .long_name = NULL_IF_CONFIG_SMALL("Wing Commander III / Xan"),
00564 };
00565