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 size = FFMIN(size, buf_end - buf);
00515 switch (tag) {
00516 case PALT_TAG:
00517 if (size < PALETTE_SIZE)
00518 return AVERROR_INVALIDDATA;
00519 if (s->palettes_count >= PALETTES_MAX)
00520 return AVERROR_INVALIDDATA;
00521 tmpptr = av_realloc(s->palettes, (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], s->palettes + s->cur_palette * AVPALETTE_COUNT, AVPALETTE_SIZE);
00573
00574 s->buf = buf;
00575 s->size = buf_size;
00576
00577 if (xan_wc3_decode_frame(s) < 0)
00578 return AVERROR_INVALIDDATA;
00579
00580
00581 if (s->last_frame.data[0])
00582 avctx->release_buffer(avctx, &s->last_frame);
00583
00584 *data_size = sizeof(AVFrame);
00585 *(AVFrame*)data = s->current_frame;
00586
00587
00588 FFSWAP(AVFrame, s->current_frame, s->last_frame);
00589
00590
00591 return buf_size;
00592 }
00593
00594 static av_cold int xan_decode_end(AVCodecContext *avctx)
00595 {
00596 XanContext *s = avctx->priv_data;
00597
00598
00599 if (s->last_frame.data[0])
00600 avctx->release_buffer(avctx, &s->last_frame);
00601 if (s->current_frame.data[0])
00602 avctx->release_buffer(avctx, &s->current_frame);
00603
00604 av_freep(&s->buffer1);
00605 av_freep(&s->buffer2);
00606 av_freep(&s->palettes);
00607
00608 return 0;
00609 }
00610
00611 AVCodec ff_xan_wc3_decoder = {
00612 "xan_wc3",
00613 AVMEDIA_TYPE_VIDEO,
00614 CODEC_ID_XAN_WC3,
00615 sizeof(XanContext),
00616 xan_decode_init,
00617 NULL,
00618 xan_decode_end,
00619 xan_decode_frame,
00620 CODEC_CAP_DR1,
00621 .long_name = NULL_IF_CONFIG_SMALL("Wing Commander III / Xan"),
00622 };