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