Libav
|
00001 /* 00002 * Wing Commander/Xan Video Decoder 00003 * Copyright (C) 2003 the ffmpeg project 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg 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 * FFmpeg 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 FFmpeg; 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 typedef struct XanContext { 00044 00045 AVCodecContext *avctx; 00046 AVFrame last_frame; 00047 AVFrame current_frame; 00048 00049 const unsigned char *buf; 00050 int size; 00051 00052 /* scratch space */ 00053 unsigned char *buffer1; 00054 int buffer1_size; 00055 unsigned char *buffer2; 00056 int buffer2_size; 00057 00058 int frame_size; 00059 00060 } XanContext; 00061 00062 static av_cold int xan_decode_init(AVCodecContext *avctx) 00063 { 00064 XanContext *s = avctx->priv_data; 00065 00066 s->avctx = avctx; 00067 s->frame_size = 0; 00068 00069 if ((avctx->codec->id == CODEC_ID_XAN_WC3) && 00070 (s->avctx->palctrl == NULL)) { 00071 av_log(avctx, AV_LOG_ERROR, " WC3 Xan video: palette expected.\n"); 00072 return -1; 00073 } 00074 00075 avctx->pix_fmt = PIX_FMT_PAL8; 00076 00077 s->buffer1_size = avctx->width * avctx->height; 00078 s->buffer1 = av_malloc(s->buffer1_size); 00079 if (!s->buffer1) 00080 return -1; 00081 s->buffer2_size = avctx->width * avctx->height; 00082 s->buffer2 = av_malloc(s->buffer2_size + 130); 00083 if (!s->buffer2) { 00084 av_freep(&s->buffer1); 00085 return -1; 00086 } 00087 00088 return 0; 00089 } 00090 00091 static int xan_huffman_decode(unsigned char *dest, int dest_len, 00092 const unsigned char *src, int src_len) 00093 { 00094 unsigned char byte = *src++; 00095 unsigned char ival = byte + 0x16; 00096 const unsigned char * ptr = src + byte*2; 00097 int ptr_len = src_len - 1 - byte*2; 00098 unsigned char val = ival; 00099 unsigned char *dest_end = dest + dest_len; 00100 GetBitContext gb; 00101 00102 init_get_bits(&gb, ptr, ptr_len * 8); 00103 00104 while ( val != 0x16 ) { 00105 val = src[val - 0x17 + get_bits1(&gb) * byte]; 00106 00107 if ( val < 0x16 ) { 00108 if (dest >= dest_end) 00109 return 0; 00110 *dest++ = val; 00111 val = ival; 00112 } 00113 } 00114 00115 return 0; 00116 } 00117 00123 static void xan_unpack(unsigned char *dest, const unsigned char *src, int dest_len) 00124 { 00125 unsigned char opcode; 00126 int size; 00127 unsigned char *dest_end = dest + dest_len; 00128 00129 while (dest < dest_end) { 00130 opcode = *src++; 00131 00132 if (opcode < 0xe0) { 00133 int size2, back; 00134 if ( (opcode & 0x80) == 0 ) { 00135 00136 size = opcode & 3; 00137 00138 back = ((opcode & 0x60) << 3) + *src++ + 1; 00139 size2 = ((opcode & 0x1c) >> 2) + 3; 00140 00141 } else if ( (opcode & 0x40) == 0 ) { 00142 00143 size = *src >> 6; 00144 00145 back = (bytestream_get_be16(&src) & 0x3fff) + 1; 00146 size2 = (opcode & 0x3f) + 4; 00147 00148 } else { 00149 00150 size = opcode & 3; 00151 00152 back = ((opcode & 0x10) << 12) + bytestream_get_be16(&src) + 1; 00153 size2 = ((opcode & 0x0c) << 6) + *src++ + 5; 00154 if (size + size2 > dest_end - dest) 00155 return; 00156 } 00157 memcpy(dest, src, size); dest += size; src += size; 00158 av_memcpy_backptr(dest, back, size2); 00159 dest += size2; 00160 } else { 00161 int finish = opcode >= 0xfc; 00162 size = finish ? opcode & 3 : ((opcode & 0x1f) << 2) + 4; 00163 00164 memcpy(dest, src, size); dest += size; src += size; 00165 if (finish) 00166 return; 00167 } 00168 } 00169 } 00170 00171 static inline void xan_wc3_output_pixel_run(XanContext *s, 00172 const unsigned char *pixel_buffer, int x, int y, int pixel_count) 00173 { 00174 int stride; 00175 int line_inc; 00176 int index; 00177 int current_x; 00178 int width = s->avctx->width; 00179 unsigned char *palette_plane; 00180 00181 palette_plane = s->current_frame.data[0]; 00182 stride = s->current_frame.linesize[0]; 00183 line_inc = stride - width; 00184 index = y * stride + x; 00185 current_x = x; 00186 while(pixel_count && (index < s->frame_size)) { 00187 int count = FFMIN(pixel_count, width - current_x); 00188 memcpy(palette_plane + index, pixel_buffer, count); 00189 pixel_count -= count; 00190 index += count; 00191 pixel_buffer += count; 00192 current_x += count; 00193 00194 if (current_x >= width) { 00195 index += line_inc; 00196 current_x = 0; 00197 } 00198 } 00199 } 00200 00201 static inline void xan_wc3_copy_pixel_run(XanContext *s, 00202 int x, int y, int pixel_count, int motion_x, int motion_y) 00203 { 00204 int stride; 00205 int line_inc; 00206 int curframe_index, prevframe_index; 00207 int curframe_x, prevframe_x; 00208 int width = s->avctx->width; 00209 unsigned char *palette_plane, *prev_palette_plane; 00210 00211 palette_plane = s->current_frame.data[0]; 00212 prev_palette_plane = s->last_frame.data[0]; 00213 stride = s->current_frame.linesize[0]; 00214 line_inc = stride - width; 00215 curframe_index = y * stride + x; 00216 curframe_x = x; 00217 prevframe_index = (y + motion_y) * stride + x + motion_x; 00218 prevframe_x = x + motion_x; 00219 while(pixel_count && (curframe_index < s->frame_size)) { 00220 int count = FFMIN3(pixel_count, width - curframe_x, width - prevframe_x); 00221 00222 memcpy(palette_plane + curframe_index, prev_palette_plane + prevframe_index, count); 00223 pixel_count -= count; 00224 curframe_index += count; 00225 prevframe_index += count; 00226 curframe_x += count; 00227 prevframe_x += count; 00228 00229 if (curframe_x >= width) { 00230 curframe_index += line_inc; 00231 curframe_x = 0; 00232 } 00233 00234 if (prevframe_x >= width) { 00235 prevframe_index += line_inc; 00236 prevframe_x = 0; 00237 } 00238 } 00239 } 00240 00241 static void xan_wc3_decode_frame(XanContext *s) { 00242 00243 int width = s->avctx->width; 00244 int height = s->avctx->height; 00245 int total_pixels = width * height; 00246 unsigned char opcode; 00247 unsigned char flag = 0; 00248 int size = 0; 00249 int motion_x, motion_y; 00250 int x, y; 00251 00252 unsigned char *opcode_buffer = s->buffer1; 00253 int opcode_buffer_size = s->buffer1_size; 00254 const unsigned char *imagedata_buffer = s->buffer2; 00255 00256 /* pointers to segments inside the compressed chunk */ 00257 const unsigned char *huffman_segment; 00258 const unsigned char *size_segment; 00259 const unsigned char *vector_segment; 00260 const unsigned char *imagedata_segment; 00261 00262 huffman_segment = s->buf + AV_RL16(&s->buf[0]); 00263 size_segment = s->buf + AV_RL16(&s->buf[2]); 00264 vector_segment = s->buf + AV_RL16(&s->buf[4]); 00265 imagedata_segment = s->buf + AV_RL16(&s->buf[6]); 00266 00267 xan_huffman_decode(opcode_buffer, opcode_buffer_size, 00268 huffman_segment, s->size - (huffman_segment - s->buf) ); 00269 00270 if (imagedata_segment[0] == 2) 00271 xan_unpack(s->buffer2, &imagedata_segment[1], s->buffer2_size); 00272 else 00273 imagedata_buffer = &imagedata_segment[1]; 00274 00275 /* use the decoded data segments to build the frame */ 00276 x = y = 0; 00277 while (total_pixels) { 00278 00279 opcode = *opcode_buffer++; 00280 size = 0; 00281 00282 switch (opcode) { 00283 00284 case 0: 00285 flag ^= 1; 00286 continue; 00287 00288 case 1: 00289 case 2: 00290 case 3: 00291 case 4: 00292 case 5: 00293 case 6: 00294 case 7: 00295 case 8: 00296 size = opcode; 00297 break; 00298 00299 case 12: 00300 case 13: 00301 case 14: 00302 case 15: 00303 case 16: 00304 case 17: 00305 case 18: 00306 size += (opcode - 10); 00307 break; 00308 00309 case 9: 00310 case 19: 00311 size = *size_segment++; 00312 break; 00313 00314 case 10: 00315 case 20: 00316 size = AV_RB16(&size_segment[0]); 00317 size_segment += 2; 00318 break; 00319 00320 case 11: 00321 case 21: 00322 size = AV_RB24(size_segment); 00323 size_segment += 3; 00324 break; 00325 } 00326 00327 if (opcode < 12) { 00328 flag ^= 1; 00329 if (flag) { 00330 /* run of (size) pixels is unchanged from last frame */ 00331 xan_wc3_copy_pixel_run(s, x, y, size, 0, 0); 00332 } else { 00333 /* output a run of pixels from imagedata_buffer */ 00334 xan_wc3_output_pixel_run(s, imagedata_buffer, x, y, size); 00335 imagedata_buffer += size; 00336 } 00337 } else { 00338 /* run-based motion compensation from last frame */ 00339 motion_x = sign_extend(*vector_segment >> 4, 4); 00340 motion_y = sign_extend(*vector_segment & 0xF, 4); 00341 vector_segment++; 00342 00343 /* copy a run of pixels from the previous frame */ 00344 xan_wc3_copy_pixel_run(s, x, y, size, motion_x, motion_y); 00345 00346 flag = 0; 00347 } 00348 00349 /* coordinate accounting */ 00350 total_pixels -= size; 00351 y += (x + size) / width; 00352 x = (x + size) % width; 00353 } 00354 } 00355 00356 static void xan_wc4_decode_frame(XanContext *s) { 00357 } 00358 00359 static int xan_decode_frame(AVCodecContext *avctx, 00360 void *data, int *data_size, 00361 AVPacket *avpkt) 00362 { 00363 const uint8_t *buf = avpkt->data; 00364 int buf_size = avpkt->size; 00365 XanContext *s = avctx->priv_data; 00366 AVPaletteControl *palette_control = avctx->palctrl; 00367 00368 if (avctx->get_buffer(avctx, &s->current_frame)) { 00369 av_log(s->avctx, AV_LOG_ERROR, " Xan Video: get_buffer() failed\n"); 00370 return -1; 00371 } 00372 s->current_frame.reference = 3; 00373 00374 if (!s->frame_size) 00375 s->frame_size = s->current_frame.linesize[0] * s->avctx->height; 00376 00377 palette_control->palette_changed = 0; 00378 memcpy(s->current_frame.data[1], palette_control->palette, 00379 AVPALETTE_SIZE); 00380 s->current_frame.palette_has_changed = 1; 00381 00382 s->buf = buf; 00383 s->size = buf_size; 00384 00385 if (avctx->codec->id == CODEC_ID_XAN_WC3) 00386 xan_wc3_decode_frame(s); 00387 else if (avctx->codec->id == CODEC_ID_XAN_WC4) 00388 xan_wc4_decode_frame(s); 00389 00390 /* release the last frame if it is allocated */ 00391 if (s->last_frame.data[0]) 00392 avctx->release_buffer(avctx, &s->last_frame); 00393 00394 *data_size = sizeof(AVFrame); 00395 *(AVFrame*)data = s->current_frame; 00396 00397 /* shuffle frames */ 00398 FFSWAP(AVFrame, s->current_frame, s->last_frame); 00399 00400 /* always report that the buffer was completely consumed */ 00401 return buf_size; 00402 } 00403 00404 static av_cold int xan_decode_end(AVCodecContext *avctx) 00405 { 00406 XanContext *s = avctx->priv_data; 00407 00408 /* release the frames */ 00409 if (s->last_frame.data[0]) 00410 avctx->release_buffer(avctx, &s->last_frame); 00411 if (s->current_frame.data[0]) 00412 avctx->release_buffer(avctx, &s->current_frame); 00413 00414 av_freep(&s->buffer1); 00415 av_freep(&s->buffer2); 00416 00417 return 0; 00418 } 00419 00420 AVCodec xan_wc3_decoder = { 00421 "xan_wc3", 00422 AVMEDIA_TYPE_VIDEO, 00423 CODEC_ID_XAN_WC3, 00424 sizeof(XanContext), 00425 xan_decode_init, 00426 NULL, 00427 xan_decode_end, 00428 xan_decode_frame, 00429 CODEC_CAP_DR1, 00430 .long_name = NULL_IF_CONFIG_SMALL("Wing Commander III / Xan"), 00431 }; 00432 00433 /* 00434 AVCodec xan_wc4_decoder = { 00435 "xan_wc4", 00436 AVMEDIA_TYPE_VIDEO, 00437 CODEC_ID_XAN_WC4, 00438 sizeof(XanContext), 00439 xan_decode_init, 00440 NULL, 00441 xan_decode_end, 00442 xan_decode_frame, 00443 CODEC_CAP_DR1, 00444 .long_name = NULL_IF_CONFIG_SMALL("Wing Commander IV / Xxan"), 00445 }; 00446 */