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