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 #include <unistd.h>
00035
00036 #include "libavutil/intreadwrite.h"
00037 #include "avcodec.h"
00038
00039 typedef struct XanContext {
00040
00041 AVCodecContext *avctx;
00042 AVFrame last_frame;
00043 AVFrame current_frame;
00044
00045 const unsigned char *buf;
00046 int size;
00047
00048
00049 unsigned char *buffer1;
00050 int buffer1_size;
00051 unsigned char *buffer2;
00052 int buffer2_size;
00053
00054 int frame_size;
00055
00056 } XanContext;
00057
00058 static av_cold int xan_decode_init(AVCodecContext *avctx)
00059 {
00060 XanContext *s = avctx->priv_data;
00061
00062 s->avctx = avctx;
00063 s->frame_size = 0;
00064
00065 if ((avctx->codec->id == CODEC_ID_XAN_WC3) &&
00066 (s->avctx->palctrl == NULL)) {
00067 av_log(avctx, AV_LOG_ERROR, " WC3 Xan video: palette expected.\n");
00068 return -1;
00069 }
00070
00071 avctx->pix_fmt = PIX_FMT_PAL8;
00072
00073 if(avcodec_check_dimensions(avctx, avctx->width, avctx->height))
00074 return -1;
00075
00076 s->buffer1_size = avctx->width * avctx->height;
00077 s->buffer1 = av_malloc(s->buffer1_size);
00078 s->buffer2_size = avctx->width * avctx->height;
00079 s->buffer2 = av_malloc(s->buffer2_size);
00080 if (!s->buffer1 || !s->buffer2)
00081 return -1;
00082
00083 return 0;
00084 }
00085
00086
00087
00088
00089
00090
00091 static inline void bytecopy(unsigned char *dest, const unsigned char *src, int count)
00092 {
00093 int i;
00094
00095 for (i = 0; i < count; i++)
00096 dest[i] = src[i];
00097 }
00098
00099 static int xan_huffman_decode(unsigned char *dest, const unsigned char *src,
00100 int dest_len)
00101 {
00102 unsigned char byte = *src++;
00103 unsigned char ival = byte + 0x16;
00104 const unsigned char * ptr = src + byte*2;
00105 unsigned char val = ival;
00106 int counter = 0;
00107 unsigned char *dest_end = dest + dest_len;
00108
00109 unsigned char bits = *ptr++;
00110
00111 while ( val != 0x16 ) {
00112 if ( (1 << counter) & bits )
00113 val = src[byte + val - 0x17];
00114 else
00115 val = src[val - 0x17];
00116
00117 if ( val < 0x16 ) {
00118 if (dest + 1 > dest_end)
00119 return 0;
00120 *dest++ = val;
00121 val = ival;
00122 }
00123
00124 if (counter++ == 7) {
00125 counter = 0;
00126 bits = *ptr++;
00127 }
00128 }
00129
00130 return 0;
00131 }
00132
00133 static void xan_unpack(unsigned char *dest, const unsigned char *src, int dest_len)
00134 {
00135 unsigned char opcode;
00136 int size;
00137 int offset;
00138 int byte1, byte2, byte3;
00139 unsigned char *dest_end = dest + dest_len;
00140
00141 for (;;) {
00142 opcode = *src++;
00143
00144 if ( (opcode & 0x80) == 0 ) {
00145
00146 offset = *src++;
00147
00148 size = opcode & 3;
00149 if (dest + size > dest_end)
00150 return;
00151 bytecopy(dest, src, size); dest += size; src += size;
00152
00153 size = ((opcode & 0x1c) >> 2) + 3;
00154 if (dest + size > dest_end)
00155 return;
00156 bytecopy (dest, dest - (((opcode & 0x60) << 3) + offset + 1), size);
00157 dest += size;
00158
00159 } else if ( (opcode & 0x40) == 0 ) {
00160
00161 byte1 = *src++;
00162 byte2 = *src++;
00163
00164 size = byte1 >> 6;
00165 if (dest + size > dest_end)
00166 return;
00167 bytecopy (dest, src, size); dest += size; src += size;
00168
00169 size = (opcode & 0x3f) + 4;
00170 if (dest + size > dest_end)
00171 return;
00172 bytecopy (dest, dest - (((byte1 & 0x3f) << 8) + byte2 + 1), size);
00173 dest += size;
00174
00175 } else if ( (opcode & 0x20) == 0 ) {
00176
00177 byte1 = *src++;
00178 byte2 = *src++;
00179 byte3 = *src++;
00180
00181 size = opcode & 3;
00182 if (dest + size > dest_end)
00183 return;
00184 bytecopy (dest, src, size); dest += size; src += size;
00185
00186 size = byte3 + 5 + ((opcode & 0xc) << 6);
00187 if (dest + size > dest_end)
00188 return;
00189 bytecopy (dest,
00190 dest - ((((opcode & 0x10) >> 4) << 0x10) + 1 + (byte1 << 8) + byte2),
00191 size);
00192 dest += size;
00193 } else {
00194 size = ((opcode & 0x1f) << 2) + 4;
00195
00196 if (size > 0x70)
00197 break;
00198
00199 if (dest + size > dest_end)
00200 return;
00201 bytecopy (dest, src, size); dest += size; src += size;
00202 }
00203 }
00204
00205 size = opcode & 3;
00206 bytecopy(dest, src, size); dest += size; src += size;
00207 }
00208
00209 static inline void xan_wc3_output_pixel_run(XanContext *s,
00210 const unsigned char *pixel_buffer, int x, int y, int pixel_count)
00211 {
00212 int stride;
00213 int line_inc;
00214 int index;
00215 int current_x;
00216 int width = s->avctx->width;
00217 unsigned char *palette_plane;
00218
00219 palette_plane = s->current_frame.data[0];
00220 stride = s->current_frame.linesize[0];
00221 line_inc = stride - width;
00222 index = y * stride + x;
00223 current_x = x;
00224 while((pixel_count--) && (index < s->frame_size)) {
00225
00226
00227
00228 palette_plane[index++] = *pixel_buffer++;
00229
00230 current_x++;
00231 if (current_x >= width) {
00232 index += line_inc;
00233 current_x = 0;
00234 }
00235 }
00236 }
00237
00238 static inline void xan_wc3_copy_pixel_run(XanContext *s,
00239 int x, int y, int pixel_count, int motion_x, int motion_y)
00240 {
00241 int stride;
00242 int line_inc;
00243 int curframe_index, prevframe_index;
00244 int curframe_x, prevframe_x;
00245 int width = s->avctx->width;
00246 unsigned char *palette_plane, *prev_palette_plane;
00247
00248 palette_plane = s->current_frame.data[0];
00249 prev_palette_plane = s->last_frame.data[0];
00250 stride = s->current_frame.linesize[0];
00251 line_inc = stride - width;
00252 curframe_index = y * stride + x;
00253 curframe_x = x;
00254 prevframe_index = (y + motion_y) * stride + x + motion_x;
00255 prevframe_x = x + motion_x;
00256 while((pixel_count--) && (curframe_index < s->frame_size)) {
00257
00258 palette_plane[curframe_index++] =
00259 prev_palette_plane[prevframe_index++];
00260
00261 curframe_x++;
00262 if (curframe_x >= width) {
00263 curframe_index += line_inc;
00264 curframe_x = 0;
00265 }
00266
00267 prevframe_x++;
00268 if (prevframe_x >= width) {
00269 prevframe_index += line_inc;
00270 prevframe_x = 0;
00271 }
00272 }
00273 }
00274
00275 static void xan_wc3_decode_frame(XanContext *s) {
00276
00277 int width = s->avctx->width;
00278 int height = s->avctx->height;
00279 int total_pixels = width * height;
00280 unsigned char opcode;
00281 unsigned char flag = 0;
00282 int size = 0;
00283 int motion_x, motion_y;
00284 int x, y;
00285
00286 unsigned char *opcode_buffer = s->buffer1;
00287 int opcode_buffer_size = s->buffer1_size;
00288 const unsigned char *imagedata_buffer = s->buffer2;
00289
00290
00291 const unsigned char *huffman_segment;
00292 const unsigned char *size_segment;
00293 const unsigned char *vector_segment;
00294 const unsigned char *imagedata_segment;
00295
00296 huffman_segment = s->buf + AV_RL16(&s->buf[0]);
00297 size_segment = s->buf + AV_RL16(&s->buf[2]);
00298 vector_segment = s->buf + AV_RL16(&s->buf[4]);
00299 imagedata_segment = s->buf + AV_RL16(&s->buf[6]);
00300
00301 xan_huffman_decode(opcode_buffer, huffman_segment, opcode_buffer_size);
00302
00303 if (imagedata_segment[0] == 2)
00304 xan_unpack(s->buffer2, &imagedata_segment[1], s->buffer2_size);
00305 else
00306 imagedata_buffer = &imagedata_segment[1];
00307
00308
00309 x = y = 0;
00310 while (total_pixels) {
00311
00312 opcode = *opcode_buffer++;
00313 size = 0;
00314
00315 switch (opcode) {
00316
00317 case 0:
00318 flag ^= 1;
00319 continue;
00320
00321 case 1:
00322 case 2:
00323 case 3:
00324 case 4:
00325 case 5:
00326 case 6:
00327 case 7:
00328 case 8:
00329 size = opcode;
00330 break;
00331
00332 case 12:
00333 case 13:
00334 case 14:
00335 case 15:
00336 case 16:
00337 case 17:
00338 case 18:
00339 size += (opcode - 10);
00340 break;
00341
00342 case 9:
00343 case 19:
00344 size = *size_segment++;
00345 break;
00346
00347 case 10:
00348 case 20:
00349 size = AV_RB16(&size_segment[0]);
00350 size_segment += 2;
00351 break;
00352
00353 case 11:
00354 case 21:
00355 size = AV_RB24(size_segment);
00356 size_segment += 3;
00357 break;
00358 }
00359
00360 if (opcode < 12) {
00361 flag ^= 1;
00362 if (flag) {
00363
00364 xan_wc3_copy_pixel_run(s, x, y, size, 0, 0);
00365 } else {
00366
00367 xan_wc3_output_pixel_run(s, imagedata_buffer, x, y, size);
00368 imagedata_buffer += size;
00369 }
00370 } else {
00371
00372 motion_x = (*vector_segment >> 4) & 0xF;
00373 motion_y = *vector_segment & 0xF;
00374 vector_segment++;
00375
00376
00377 if (motion_x & 0x8)
00378 motion_x |= 0xFFFFFFF0;
00379 if (motion_y & 0x8)
00380 motion_y |= 0xFFFFFFF0;
00381
00382
00383 xan_wc3_copy_pixel_run(s, x, y, size, motion_x, motion_y);
00384
00385 flag = 0;
00386 }
00387
00388
00389 total_pixels -= size;
00390 while (size) {
00391 if (x + size >= width) {
00392 y++;
00393 size -= (width - x);
00394 x = 0;
00395 } else {
00396 x += size;
00397 size = 0;
00398 }
00399 }
00400 }
00401 }
00402
00403 static void xan_wc4_decode_frame(XanContext *s) {
00404 }
00405
00406 static int xan_decode_frame(AVCodecContext *avctx,
00407 void *data, int *data_size,
00408 const uint8_t *buf, int buf_size)
00409 {
00410 XanContext *s = avctx->priv_data;
00411 AVPaletteControl *palette_control = avctx->palctrl;
00412
00413 if (avctx->get_buffer(avctx, &s->current_frame)) {
00414 av_log(s->avctx, AV_LOG_ERROR, " Xan Video: get_buffer() failed\n");
00415 return -1;
00416 }
00417 s->current_frame.reference = 3;
00418
00419 if (!s->frame_size)
00420 s->frame_size = s->current_frame.linesize[0] * s->avctx->height;
00421
00422 palette_control->palette_changed = 0;
00423 memcpy(s->current_frame.data[1], palette_control->palette,
00424 AVPALETTE_SIZE);
00425 s->current_frame.palette_has_changed = 1;
00426
00427 s->buf = buf;
00428 s->size = buf_size;
00429
00430 if (avctx->codec->id == CODEC_ID_XAN_WC3)
00431 xan_wc3_decode_frame(s);
00432 else if (avctx->codec->id == CODEC_ID_XAN_WC4)
00433 xan_wc4_decode_frame(s);
00434
00435
00436 if (s->last_frame.data[0])
00437 avctx->release_buffer(avctx, &s->last_frame);
00438
00439 *data_size = sizeof(AVFrame);
00440 *(AVFrame*)data = s->current_frame;
00441
00442
00443 FFSWAP(AVFrame, s->current_frame, s->last_frame);
00444
00445
00446 return buf_size;
00447 }
00448
00449 static av_cold int xan_decode_end(AVCodecContext *avctx)
00450 {
00451 XanContext *s = avctx->priv_data;
00452
00453
00454 if (s->last_frame.data[0])
00455 avctx->release_buffer(avctx, &s->last_frame);
00456 if (s->current_frame.data[0])
00457 avctx->release_buffer(avctx, &s->current_frame);
00458
00459 av_free(s->buffer1);
00460 av_free(s->buffer2);
00461
00462 return 0;
00463 }
00464
00465 AVCodec xan_wc3_decoder = {
00466 "xan_wc3",
00467 CODEC_TYPE_VIDEO,
00468 CODEC_ID_XAN_WC3,
00469 sizeof(XanContext),
00470 xan_decode_init,
00471 NULL,
00472 xan_decode_end,
00473 xan_decode_frame,
00474 CODEC_CAP_DR1,
00475 .long_name = NULL_IF_CONFIG_SMALL("Wing Commander III / Xan"),
00476 };
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490