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 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
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
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
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
00331 xan_wc3_copy_pixel_run(s, x, y, size, 0, 0);
00332 } else {
00333
00334 xan_wc3_output_pixel_run(s, imagedata_buffer, x, y, size);
00335 imagedata_buffer += size;
00336 }
00337 } else {
00338
00339 motion_x = sign_extend(*vector_segment >> 4, 4);
00340 motion_y = sign_extend(*vector_segment & 0xF, 4);
00341 vector_segment++;
00342
00343
00344 xan_wc3_copy_pixel_run(s, x, y, size, motion_x, motion_y);
00345
00346 flag = 0;
00347 }
00348
00349
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
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
00398 FFSWAP(AVFrame, s->current_frame, s->last_frame);
00399
00400
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
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
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446