Libav 0.7.1
|
00001 /* 00002 * Wing Commander/Xan Video Decoder 00003 * Copyright (C) 2003 the ffmpeg project 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 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 // for av_memcpy_backptr 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 /* scratch space */ 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 00152 size = opcode & 3; 00153 00154 back = ((opcode & 0x60) << 3) + *src++ + 1; 00155 size2 = ((opcode & 0x1c) >> 2) + 3; 00156 00157 } else if ( (opcode & 0x40) == 0 ) { 00158 00159 size = *src >> 6; 00160 00161 back = (bytestream_get_be16(&src) & 0x3fff) + 1; 00162 size2 = (opcode & 0x3f) + 4; 00163 00164 } else { 00165 00166 size = opcode & 3; 00167 00168 back = ((opcode & 0x10) << 12) + bytestream_get_be16(&src) + 1; 00169 size2 = ((opcode & 0x0c) << 6) + *src++ + 5; 00170 } 00171 if (dest_end - dest < size + size2 || 00172 dest + size - dest_org < back || 00173 src_end - src < size) 00174 return; 00175 memcpy(dest, src, size); dest += size; src += size; 00176 av_memcpy_backptr(dest, back, size2); 00177 dest += size2; 00178 } else { 00179 int finish = opcode >= 0xfc; 00180 size = finish ? opcode & 3 : ((opcode & 0x1f) << 2) + 4; 00181 00182 if (dest_end - dest < size || src_end - src < size) 00183 return; 00184 memcpy(dest, src, size); dest += size; src += size; 00185 if (finish) 00186 return; 00187 } 00188 } 00189 } 00190 00191 static inline void xan_wc3_output_pixel_run(XanContext *s, 00192 const unsigned char *pixel_buffer, int x, int y, int pixel_count) 00193 { 00194 int stride; 00195 int line_inc; 00196 int index; 00197 int current_x; 00198 int width = s->avctx->width; 00199 unsigned char *palette_plane; 00200 00201 palette_plane = s->current_frame.data[0]; 00202 stride = s->current_frame.linesize[0]; 00203 line_inc = stride - width; 00204 index = y * stride + x; 00205 current_x = x; 00206 while(pixel_count && (index < s->frame_size)) { 00207 int count = FFMIN(pixel_count, width - current_x); 00208 memcpy(palette_plane + index, pixel_buffer, count); 00209 pixel_count -= count; 00210 index += count; 00211 pixel_buffer += count; 00212 current_x += count; 00213 00214 if (current_x >= width) { 00215 index += line_inc; 00216 current_x = 0; 00217 } 00218 } 00219 } 00220 00221 static inline void xan_wc3_copy_pixel_run(XanContext *s, 00222 int x, int y, int pixel_count, int motion_x, int motion_y) 00223 { 00224 int stride; 00225 int line_inc; 00226 int curframe_index, prevframe_index; 00227 int curframe_x, prevframe_x; 00228 int width = s->avctx->width; 00229 unsigned char *palette_plane, *prev_palette_plane; 00230 00231 if ( y + motion_y < 0 || y + motion_y >= s->avctx->height || 00232 x + motion_x < 0 || x + motion_x >= s->avctx->width) 00233 return; 00234 00235 palette_plane = s->current_frame.data[0]; 00236 prev_palette_plane = s->last_frame.data[0]; 00237 if (!prev_palette_plane) 00238 prev_palette_plane = palette_plane; 00239 stride = s->current_frame.linesize[0]; 00240 line_inc = stride - width; 00241 curframe_index = y * stride + x; 00242 curframe_x = x; 00243 prevframe_index = (y + motion_y) * stride + x + motion_x; 00244 prevframe_x = x + motion_x; 00245 while(pixel_count && 00246 curframe_index < s->frame_size && 00247 prevframe_index < s->frame_size) { 00248 int count = FFMIN3(pixel_count, width - curframe_x, width - prevframe_x); 00249 00250 memcpy(palette_plane + curframe_index, prev_palette_plane + prevframe_index, count); 00251 pixel_count -= count; 00252 curframe_index += count; 00253 prevframe_index += count; 00254 curframe_x += count; 00255 prevframe_x += count; 00256 00257 if (curframe_x >= width) { 00258 curframe_index += line_inc; 00259 curframe_x = 0; 00260 } 00261 00262 if (prevframe_x >= width) { 00263 prevframe_index += line_inc; 00264 prevframe_x = 0; 00265 } 00266 } 00267 } 00268 00269 static int xan_wc3_decode_frame(XanContext *s) { 00270 00271 int width = s->avctx->width; 00272 int height = s->avctx->height; 00273 int total_pixels = width * height; 00274 unsigned char opcode; 00275 unsigned char flag = 0; 00276 int size = 0; 00277 int motion_x, motion_y; 00278 int x, y; 00279 00280 unsigned char *opcode_buffer = s->buffer1; 00281 unsigned char *opcode_buffer_end = s->buffer1 + s->buffer1_size; 00282 int opcode_buffer_size = s->buffer1_size; 00283 const unsigned char *imagedata_buffer = s->buffer2; 00284 00285 /* pointers to segments inside the compressed chunk */ 00286 const unsigned char *huffman_segment; 00287 const unsigned char *size_segment; 00288 const unsigned char *vector_segment; 00289 const unsigned char *imagedata_segment; 00290 int huffman_offset, size_offset, vector_offset, imagedata_offset, 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 /* use the decoded data segments to build the frame */ 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 if (size > total_pixels) 00376 break; 00377 00378 if (opcode < 12) { 00379 flag ^= 1; 00380 if (flag) { 00381 /* run of (size) pixels is unchanged from last frame */ 00382 xan_wc3_copy_pixel_run(s, x, y, size, 0, 0); 00383 } else { 00384 /* output a run of pixels from imagedata_buffer */ 00385 if (imagedata_size < size) 00386 break; 00387 xan_wc3_output_pixel_run(s, imagedata_buffer, x, y, size); 00388 imagedata_buffer += size; 00389 imagedata_size -= size; 00390 } 00391 } else { 00392 /* run-based motion compensation from last frame */ 00393 motion_x = sign_extend(*vector_segment >> 4, 4); 00394 motion_y = sign_extend(*vector_segment & 0xF, 4); 00395 vector_segment++; 00396 00397 /* copy a run of pixels from the previous frame */ 00398 xan_wc3_copy_pixel_run(s, x, y, size, motion_x, motion_y); 00399 00400 flag = 0; 00401 } 00402 00403 /* coordinate accounting */ 00404 total_pixels -= size; 00405 y += (x + size) / width; 00406 x = (x + size) % width; 00407 } 00408 return 0; 00409 } 00410 00411 #if RUNTIME_GAMMA 00412 static inline unsigned mul(unsigned a, unsigned b) 00413 { 00414 return (a * b) >> 16; 00415 } 00416 00417 static inline unsigned pow4(unsigned a) 00418 { 00419 unsigned square = mul(a, a); 00420 return mul(square, square); 00421 } 00422 00423 static inline unsigned pow5(unsigned a) 00424 { 00425 return mul(pow4(a), a); 00426 } 00427 00428 static uint8_t gamma_corr(uint8_t in) { 00429 unsigned lo, hi = 0xff40, target; 00430 int i = 15; 00431 in = (in << 2) | (in >> 6); 00432 /* equivalent float code: 00433 if (in >= 252) 00434 return 253; 00435 return round(pow(in / 256.0, 0.8) * 256); 00436 */ 00437 lo = target = in << 8; 00438 do { 00439 unsigned mid = (lo + hi) >> 1; 00440 unsigned pow = pow5(mid); 00441 if (pow > target) hi = mid; 00442 else lo = mid; 00443 } while (--i); 00444 return (pow4((lo + hi) >> 1) + 0x80) >> 8; 00445 } 00446 #else 00447 00458 static const uint8_t gamma_lookup[256] = { 00459 0x00, 0x09, 0x10, 0x16, 0x1C, 0x21, 0x27, 0x2C, 00460 0x31, 0x35, 0x3A, 0x3F, 0x43, 0x48, 0x4C, 0x50, 00461 0x54, 0x59, 0x5D, 0x61, 0x65, 0x69, 0x6D, 0x71, 00462 0x75, 0x79, 0x7D, 0x80, 0x84, 0x88, 0x8C, 0x8F, 00463 0x93, 0x97, 0x9A, 0x9E, 0xA2, 0xA5, 0xA9, 0xAC, 00464 0xB0, 0xB3, 0xB7, 0xBA, 0xBE, 0xC1, 0xC5, 0xC8, 00465 0xCB, 0xCF, 0xD2, 0xD5, 0xD9, 0xDC, 0xDF, 0xE3, 00466 0xE6, 0xE9, 0xED, 0xF0, 0xF3, 0xF6, 0xFA, 0xFD, 00467 0x03, 0x0B, 0x12, 0x18, 0x1D, 0x23, 0x28, 0x2D, 00468 0x32, 0x36, 0x3B, 0x40, 0x44, 0x49, 0x4D, 0x51, 00469 0x56, 0x5A, 0x5E, 0x62, 0x66, 0x6A, 0x6E, 0x72, 00470 0x76, 0x7A, 0x7D, 0x81, 0x85, 0x89, 0x8D, 0x90, 00471 0x94, 0x98, 0x9B, 0x9F, 0xA2, 0xA6, 0xAA, 0xAD, 00472 0xB1, 0xB4, 0xB8, 0xBB, 0xBF, 0xC2, 0xC5, 0xC9, 00473 0xCC, 0xD0, 0xD3, 0xD6, 0xDA, 0xDD, 0xE0, 0xE4, 00474 0xE7, 0xEA, 0xED, 0xF1, 0xF4, 0xF7, 0xFA, 0xFD, 00475 0x05, 0x0D, 0x13, 0x19, 0x1F, 0x24, 0x29, 0x2E, 00476 0x33, 0x38, 0x3C, 0x41, 0x45, 0x4A, 0x4E, 0x52, 00477 0x57, 0x5B, 0x5F, 0x63, 0x67, 0x6B, 0x6F, 0x73, 00478 0x77, 0x7B, 0x7E, 0x82, 0x86, 0x8A, 0x8D, 0x91, 00479 0x95, 0x99, 0x9C, 0xA0, 0xA3, 0xA7, 0xAA, 0xAE, 00480 0xB2, 0xB5, 0xB9, 0xBC, 0xBF, 0xC3, 0xC6, 0xCA, 00481 0xCD, 0xD0, 0xD4, 0xD7, 0xDA, 0xDE, 0xE1, 0xE4, 00482 0xE8, 0xEB, 0xEE, 0xF1, 0xF5, 0xF8, 0xFB, 0xFD, 00483 0x07, 0x0E, 0x15, 0x1A, 0x20, 0x25, 0x2A, 0x2F, 00484 0x34, 0x39, 0x3D, 0x42, 0x46, 0x4B, 0x4F, 0x53, 00485 0x58, 0x5C, 0x60, 0x64, 0x68, 0x6C, 0x70, 0x74, 00486 0x78, 0x7C, 0x7F, 0x83, 0x87, 0x8B, 0x8E, 0x92, 00487 0x96, 0x99, 0x9D, 0xA1, 0xA4, 0xA8, 0xAB, 0xAF, 00488 0xB2, 0xB6, 0xB9, 0xBD, 0xC0, 0xC4, 0xC7, 0xCB, 00489 0xCE, 0xD1, 0xD5, 0xD8, 0xDB, 0xDF, 0xE2, 0xE5, 00490 0xE9, 0xEC, 0xEF, 0xF2, 0xF6, 0xF9, 0xFC, 0xFD 00491 }; 00492 #endif 00493 00494 static int xan_decode_frame(AVCodecContext *avctx, 00495 void *data, int *data_size, 00496 AVPacket *avpkt) 00497 { 00498 const uint8_t *buf = avpkt->data; 00499 int ret, buf_size = avpkt->size; 00500 XanContext *s = avctx->priv_data; 00501 00502 if (avctx->codec->id == CODEC_ID_XAN_WC3) { 00503 const uint8_t *buf_end = buf + buf_size; 00504 int tag = 0; 00505 while (buf_end - buf > 8 && tag != VGA__TAG) { 00506 unsigned *tmpptr; 00507 uint32_t new_pal; 00508 int size; 00509 int i; 00510 tag = bytestream_get_le32(&buf); 00511 size = bytestream_get_be32(&buf); 00512 size = FFMIN(size, buf_end - buf); 00513 switch (tag) { 00514 case PALT_TAG: 00515 if (size < PALETTE_SIZE) 00516 return AVERROR_INVALIDDATA; 00517 if (s->palettes_count >= PALETTES_MAX) 00518 return AVERROR_INVALIDDATA; 00519 tmpptr = av_realloc(s->palettes, (s->palettes_count + 1) * AVPALETTE_SIZE); 00520 if (!tmpptr) 00521 return AVERROR(ENOMEM); 00522 s->palettes = tmpptr; 00523 tmpptr += s->palettes_count * AVPALETTE_COUNT; 00524 for (i = 0; i < PALETTE_COUNT; i++) { 00525 #if RUNTIME_GAMMA 00526 int r = gamma_corr(*buf++); 00527 int g = gamma_corr(*buf++); 00528 int b = gamma_corr(*buf++); 00529 #else 00530 int r = gamma_lookup[*buf++]; 00531 int g = gamma_lookup[*buf++]; 00532 int b = gamma_lookup[*buf++]; 00533 #endif 00534 *tmpptr++ = (r << 16) | (g << 8) | b; 00535 } 00536 s->palettes_count++; 00537 break; 00538 case SHOT_TAG: 00539 if (size < 4) 00540 return AVERROR_INVALIDDATA; 00541 new_pal = bytestream_get_le32(&buf); 00542 if (new_pal < s->palettes_count) { 00543 s->cur_palette = new_pal; 00544 } else 00545 av_log(avctx, AV_LOG_ERROR, "Invalid palette selected\n"); 00546 break; 00547 case VGA__TAG: 00548 break; 00549 default: 00550 buf += size; 00551 break; 00552 } 00553 } 00554 buf_size = buf_end - buf; 00555 } 00556 if (s->palettes_count <= 0) { 00557 av_log(s->avctx, AV_LOG_ERROR, "No palette found\n"); 00558 return AVERROR_INVALIDDATA; 00559 } 00560 00561 if ((ret = avctx->get_buffer(avctx, &s->current_frame))) { 00562 av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n"); 00563 return ret; 00564 } 00565 s->current_frame.reference = 3; 00566 00567 if (!s->frame_size) 00568 s->frame_size = s->current_frame.linesize[0] * s->avctx->height; 00569 00570 memcpy(s->current_frame.data[1], s->palettes + s->cur_palette * AVPALETTE_COUNT, AVPALETTE_SIZE); 00571 00572 s->buf = buf; 00573 s->size = buf_size; 00574 00575 if (xan_wc3_decode_frame(s) < 0) 00576 return AVERROR_INVALIDDATA; 00577 00578 /* release the last frame if it is allocated */ 00579 if (s->last_frame.data[0]) 00580 avctx->release_buffer(avctx, &s->last_frame); 00581 00582 *data_size = sizeof(AVFrame); 00583 *(AVFrame*)data = s->current_frame; 00584 00585 /* shuffle frames */ 00586 FFSWAP(AVFrame, s->current_frame, s->last_frame); 00587 00588 /* always report that the buffer was completely consumed */ 00589 return buf_size; 00590 } 00591 00592 static av_cold int xan_decode_end(AVCodecContext *avctx) 00593 { 00594 XanContext *s = avctx->priv_data; 00595 00596 /* release the frames */ 00597 if (s->last_frame.data[0]) 00598 avctx->release_buffer(avctx, &s->last_frame); 00599 if (s->current_frame.data[0]) 00600 avctx->release_buffer(avctx, &s->current_frame); 00601 00602 av_freep(&s->buffer1); 00603 av_freep(&s->buffer2); 00604 av_freep(&s->palettes); 00605 00606 return 0; 00607 } 00608 00609 AVCodec ff_xan_wc3_decoder = { 00610 "xan_wc3", 00611 AVMEDIA_TYPE_VIDEO, 00612 CODEC_ID_XAN_WC3, 00613 sizeof(XanContext), 00614 xan_decode_init, 00615 NULL, 00616 xan_decode_end, 00617 xan_decode_frame, 00618 CODEC_CAP_DR1, 00619 .long_name = NULL_IF_CONFIG_SMALL("Wing Commander III / Xan"), 00620 }; 00621