Mercurial > libavcodec.hg
comparison xan.c @ 1443:47f4c8a5a7fc libavcodec
New fringe codecs: WC3/Xan video, Xan DPCM, DK3 & DK4 ADPCM
author | tmmm |
---|---|
date | Mon, 08 Sep 2003 04:10:59 +0000 |
parents | |
children | 201d4e25c207 |
comparison
equal
deleted
inserted
replaced
1442:2a4bd3a11d4a | 1443:47f4c8a5a7fc |
---|---|
1 /* | |
2 * Wing Commander/Xan Video Decoder | |
3 * Copyright (C) 2003 the ffmpeg project | |
4 * | |
5 * This library is free software; you can redistribute it and/or | |
6 * modify it under the terms of the GNU Lesser General Public | |
7 * License as published by the Free Software Foundation; either | |
8 * version 2 of the License, or (at your option) any later version. | |
9 * | |
10 * This library is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 * Lesser General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU Lesser General Public | |
16 * License along with this library; if not, write to the Free Software | |
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 * | |
19 */ | |
20 | |
21 /** | |
22 * @file xan.c | |
23 * Xan video decoder for Wing Commander III & IV computer games | |
24 * by Mario Brito (mbrito@student.dei.uc.pt) | |
25 * and Mike Melanson (melanson@pcisys.net) | |
26 * For more information about the Xan format, visit: | |
27 * http://www.pcisys.net/~melanson/codecs/ | |
28 */ | |
29 | |
30 #include <stdio.h> | |
31 #include <stdlib.h> | |
32 #include <string.h> | |
33 #include <unistd.h> | |
34 | |
35 #include "common.h" | |
36 #include "avcodec.h" | |
37 #include "dsputil.h" | |
38 | |
39 #define PALETTE_COUNT 256 | |
40 #define PALETTE_CONTROL_SIZE ((256 * 3) + 1) | |
41 | |
42 typedef struct XanContext { | |
43 | |
44 AVCodecContext *avctx; | |
45 DSPContext dsp; | |
46 AVFrame last_frame; | |
47 AVFrame current_frame; | |
48 | |
49 unsigned char *buf; | |
50 int size; | |
51 | |
52 unsigned char palette[PALETTE_COUNT * 4]; | |
53 | |
54 /* scratch space */ | |
55 unsigned char *buffer1; | |
56 unsigned char *buffer2; | |
57 | |
58 } XanContext; | |
59 | |
60 #define BE_16(x) ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1]) | |
61 #define LE_16(x) ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0]) | |
62 #define LE_32(x) ((((uint8_t*)(x))[3] << 24) | \ | |
63 (((uint8_t*)(x))[2] << 16) | \ | |
64 (((uint8_t*)(x))[1] << 8) | \ | |
65 ((uint8_t*)(x))[0]) | |
66 | |
67 /* RGB -> YUV conversion stuff */ | |
68 #define SCALEFACTOR 65536 | |
69 #define CENTERSAMPLE 128 | |
70 | |
71 #define COMPUTE_Y(r, g, b) \ | |
72 (unsigned char) \ | |
73 ((y_r_table[r] + y_g_table[g] + y_b_table[b]) / SCALEFACTOR) | |
74 #define COMPUTE_U(r, g, b) \ | |
75 (unsigned char) \ | |
76 ((u_r_table[r] + u_g_table[g] + u_b_table[b]) / SCALEFACTOR + CENTERSAMPLE) | |
77 #define COMPUTE_V(r, g, b) \ | |
78 (unsigned char) \ | |
79 ((v_r_table[r] + v_g_table[g] + v_b_table[b]) / SCALEFACTOR + CENTERSAMPLE) | |
80 | |
81 #define Y_R (SCALEFACTOR * 0.29900) | |
82 #define Y_G (SCALEFACTOR * 0.58700) | |
83 #define Y_B (SCALEFACTOR * 0.11400) | |
84 | |
85 #define U_R (SCALEFACTOR * -0.16874) | |
86 #define U_G (SCALEFACTOR * -0.33126) | |
87 #define U_B (SCALEFACTOR * 0.50000) | |
88 | |
89 #define V_R (SCALEFACTOR * 0.50000) | |
90 #define V_G (SCALEFACTOR * -0.41869) | |
91 #define V_B (SCALEFACTOR * -0.08131) | |
92 | |
93 /* | |
94 * Precalculate all of the YUV tables since it requires fewer than | |
95 * 10 kilobytes to store them. | |
96 */ | |
97 static int y_r_table[256]; | |
98 static int y_g_table[256]; | |
99 static int y_b_table[256]; | |
100 | |
101 static int u_r_table[256]; | |
102 static int u_g_table[256]; | |
103 static int u_b_table[256]; | |
104 | |
105 static int v_r_table[256]; | |
106 static int v_g_table[256]; | |
107 static int v_b_table[256]; | |
108 | |
109 static int xan_decode_init(AVCodecContext *avctx) | |
110 { | |
111 XanContext *s = avctx->priv_data; | |
112 int i; | |
113 | |
114 s->avctx = avctx; | |
115 | |
116 if ((avctx->codec->id == CODEC_ID_XAN_WC3) && | |
117 (s->avctx->extradata_size != PALETTE_CONTROL_SIZE)) { | |
118 printf (" WC3 Xan video: expected extradata_size of %d\n", | |
119 PALETTE_CONTROL_SIZE); | |
120 return -1; | |
121 } | |
122 | |
123 avctx->pix_fmt = PIX_FMT_YUV444P; | |
124 avctx->has_b_frames = 0; | |
125 dsputil_init(&s->dsp, avctx); | |
126 | |
127 /* initialize the RGB -> YUV tables */ | |
128 for (i = 0; i < 256; i++) { | |
129 y_r_table[i] = Y_R * i; | |
130 y_g_table[i] = Y_G * i; | |
131 y_b_table[i] = Y_B * i; | |
132 | |
133 u_r_table[i] = U_R * i; | |
134 u_g_table[i] = U_G * i; | |
135 u_b_table[i] = U_B * i; | |
136 | |
137 v_r_table[i] = V_R * i; | |
138 v_g_table[i] = V_G * i; | |
139 v_b_table[i] = V_B * i; | |
140 } | |
141 | |
142 s->buffer1 = av_malloc(avctx->width * avctx->height * 4); | |
143 s->buffer2 = av_malloc(avctx->width * avctx->height * 4); | |
144 if (!s->buffer1 || !s->buffer2) | |
145 return -1; | |
146 | |
147 return 0; | |
148 } | |
149 | |
150 /* This function is used in lieu of memcpy(). This decoder can not use | |
151 * memcpy because the memory locations often overlap and | |
152 * memcpy doesn't like that; it's not uncommon, for example, for | |
153 * dest = src+1, to turn byte A into pattern AAAAAAAA. | |
154 * This was originally repz movsb in Intel x86 ASM. */ | |
155 static inline void bytecopy(unsigned char *dest, unsigned char *src, int count) | |
156 { | |
157 int i; | |
158 | |
159 for (i = 0; i < count; i++) | |
160 dest[i] = src[i]; | |
161 } | |
162 | |
163 static int xan_decode_method_1(unsigned char *dest, unsigned char *src) | |
164 { | |
165 unsigned char byte = *src++; | |
166 unsigned char ival = byte + 0x16; | |
167 unsigned char * ptr = src + byte*2; | |
168 unsigned char val = ival; | |
169 int counter = 0; | |
170 | |
171 unsigned char bits = *ptr++; | |
172 | |
173 while ( val != 0x16 ) { | |
174 if ( (1 << counter) & bits ) | |
175 val = src[byte + val - 0x17]; | |
176 else | |
177 val = src[val - 0x17]; | |
178 | |
179 if ( val < 0x16 ) { | |
180 *dest++ = val; | |
181 val = ival; | |
182 } | |
183 | |
184 if (counter++ == 7) { | |
185 counter = 0; | |
186 bits = *ptr++; | |
187 } | |
188 } | |
189 | |
190 return 0; | |
191 } | |
192 | |
193 static int xan_decode_method_2(unsigned char *dest, unsigned char *src) | |
194 { | |
195 unsigned char opcode; | |
196 int size; | |
197 int offset; | |
198 int byte1, byte2, byte3; | |
199 | |
200 for (;;) { | |
201 opcode = *src++; | |
202 | |
203 if ( (opcode & 0x80) == 0 ) { | |
204 | |
205 offset = *src++; | |
206 | |
207 size = opcode & 3; | |
208 bytecopy(dest, src, size); dest += size; src += size; | |
209 | |
210 size = ((opcode & 0x1c) >> 2) + 3; | |
211 bytecopy (dest, dest - (((opcode & 0x60) << 3) + offset + 1), size); | |
212 dest += size; | |
213 | |
214 } else if ( (opcode & 0x40) == 0 ) { | |
215 | |
216 byte1 = *src++; | |
217 byte2 = *src++; | |
218 | |
219 size = byte1 >> 6; | |
220 bytecopy (dest, src, size); dest += size; src += size; | |
221 | |
222 size = (opcode & 0x3f) + 4; | |
223 bytecopy (dest, dest - (((byte1 & 0x3f) << 8) + byte2 + 1), size); | |
224 dest += size; | |
225 | |
226 } else if ( (opcode & 0x20) == 0 ) { | |
227 | |
228 byte1 = *src++; | |
229 byte2 = *src++; | |
230 byte3 = *src++; | |
231 | |
232 size = opcode & 3; | |
233 bytecopy (dest, src, size); dest += size; src += size; | |
234 | |
235 size = byte3 + 5 + ((opcode & 0xc) << 6); | |
236 bytecopy (dest, | |
237 dest - ((((opcode & 0x10) >> 4) << 0x10) + 1 + (byte1 << 8) + byte2), | |
238 size); | |
239 dest += size; | |
240 } else { | |
241 size = ((opcode & 0x1f) << 2) + 4; | |
242 | |
243 if (size > 0x70) | |
244 break; | |
245 | |
246 bytecopy (dest, src, size); dest += size; src += size; | |
247 } | |
248 } | |
249 | |
250 size = opcode & 3; | |
251 bytecopy(dest, src, size); dest += size; src += size; | |
252 | |
253 return 0; | |
254 } | |
255 | |
256 static void inline xan_wc3_build_palette(XanContext *s, | |
257 unsigned char *palette_data) | |
258 { | |
259 int i; | |
260 unsigned char r, g, b; | |
261 | |
262 /* transform the palette passed through the palette control structure | |
263 * into the necessary internal format depending on colorspace */ | |
264 | |
265 switch (s->avctx->pix_fmt) { | |
266 | |
267 case PIX_FMT_YUV444P: | |
268 for (i = 0; i < PALETTE_COUNT; i++) { | |
269 r = *palette_data++; | |
270 g = *palette_data++; | |
271 b = *palette_data++; | |
272 s->palette[i * 4 + 0] = COMPUTE_Y(r, g, b); | |
273 s->palette[i * 4 + 1] = COMPUTE_U(r, g, b); | |
274 s->palette[i * 4 + 2] = COMPUTE_V(r, g, b); | |
275 } | |
276 break; | |
277 | |
278 default: | |
279 printf (" Xan WC3: Unhandled colorspace\n"); | |
280 break; | |
281 } | |
282 } | |
283 | |
284 static void inline xan_wc3_output_pixel_run(XanContext *s, | |
285 unsigned char *pixel_buffer, int x, int y, int pixel_count) | |
286 { | |
287 int stride; | |
288 int line_inc; | |
289 int index; | |
290 int current_x; | |
291 int width = s->avctx->width; | |
292 unsigned char pixel; | |
293 unsigned char *y_plane; | |
294 unsigned char *u_plane; | |
295 unsigned char *v_plane; | |
296 | |
297 switch (s->avctx->pix_fmt) { | |
298 | |
299 case PIX_FMT_YUV444P: | |
300 y_plane = s->current_frame.data[0]; | |
301 u_plane = s->current_frame.data[1]; | |
302 v_plane = s->current_frame.data[2]; | |
303 stride = s->current_frame.linesize[0]; | |
304 line_inc = stride - width; | |
305 index = y * stride + x; | |
306 current_x = x; | |
307 while(pixel_count--) { | |
308 pixel = *pixel_buffer++; | |
309 | |
310 y_plane[index] = s->palette[pixel * 4 + 0]; | |
311 u_plane[index] = s->palette[pixel * 4 + 1]; | |
312 v_plane[index] = s->palette[pixel * 4 + 2]; | |
313 | |
314 index++; | |
315 current_x++; | |
316 if (current_x >= width) { | |
317 /* reset accounting variables */ | |
318 index += line_inc; | |
319 current_x = 0; | |
320 } | |
321 } | |
322 break; | |
323 | |
324 default: | |
325 printf (" Xan WC3: Unhandled colorspace\n"); | |
326 break; | |
327 } | |
328 } | |
329 | |
330 static void inline xan_wc3_copy_pixel_run(XanContext *s, | |
331 int x, int y, int pixel_count, int motion_x, int motion_y) | |
332 { | |
333 int stride; | |
334 int line_inc; | |
335 int curframe_index, prevframe_index; | |
336 int curframe_x, prevframe_x; | |
337 int width = s->avctx->width; | |
338 unsigned char *y_plane, *u_plane, *v_plane; | |
339 unsigned char *prev_y_plane, *prev_u_plane, *prev_v_plane; | |
340 | |
341 switch (s->avctx->pix_fmt) { | |
342 | |
343 case PIX_FMT_YUV444P: | |
344 y_plane = s->current_frame.data[0]; | |
345 u_plane = s->current_frame.data[1]; | |
346 v_plane = s->current_frame.data[2]; | |
347 prev_y_plane = s->last_frame.data[0]; | |
348 prev_u_plane = s->last_frame.data[1]; | |
349 prev_v_plane = s->last_frame.data[2]; | |
350 stride = s->current_frame.linesize[0]; | |
351 line_inc = stride - width; | |
352 curframe_index = y * stride + x; | |
353 curframe_x = x; | |
354 prevframe_index = (y + motion_x) * stride + x + motion_x; | |
355 prevframe_x = x + motion_x; | |
356 while(pixel_count--) { | |
357 | |
358 y_plane[curframe_index] = prev_y_plane[prevframe_index]; | |
359 u_plane[curframe_index] = prev_u_plane[prevframe_index]; | |
360 v_plane[curframe_index] = prev_v_plane[prevframe_index]; | |
361 | |
362 curframe_index++; | |
363 curframe_x++; | |
364 if (curframe_x >= width) { | |
365 /* reset accounting variables */ | |
366 curframe_index += line_inc; | |
367 curframe_x = 0; | |
368 } | |
369 | |
370 prevframe_index++; | |
371 prevframe_x++; | |
372 if (prevframe_x >= width) { | |
373 /* reset accounting variables */ | |
374 prevframe_index += line_inc; | |
375 prevframe_x = 0; | |
376 } | |
377 } | |
378 break; | |
379 | |
380 default: | |
381 printf (" Xan WC3: Unhandled colorspace\n"); | |
382 break; | |
383 } | |
384 } | |
385 | |
386 static void xan_wc3_decode_frame(XanContext *s) { | |
387 | |
388 int width = s->avctx->width; | |
389 int height = s->avctx->height; | |
390 int total_pixels = width * height; | |
391 unsigned char opcode; | |
392 unsigned char flag = 0; | |
393 int size = 0; | |
394 int motion_x, motion_y; | |
395 int x, y; | |
396 | |
397 unsigned char *method1_buffer = s->buffer1; | |
398 unsigned char *method2_buffer = s->buffer2; | |
399 | |
400 /* pointers to segments inside the compressed chunk */ | |
401 unsigned char *method1_segment; | |
402 unsigned char *size_segment; | |
403 unsigned char *vector_segment; | |
404 unsigned char *method2_segment; | |
405 | |
406 method1_segment = s->buf + LE_16(&s->buf[0]); | |
407 size_segment = s->buf + LE_16(&s->buf[2]); | |
408 vector_segment = s->buf + LE_16(&s->buf[4]); | |
409 method2_segment = s->buf + LE_16(&s->buf[6]); | |
410 | |
411 xan_decode_method_1(method1_buffer, method1_segment); | |
412 if (method2_segment[0] == 2) | |
413 xan_decode_method_2(method2_buffer, method2_segment + 1); | |
414 else | |
415 method2_buffer = method2_segment + 1; | |
416 | |
417 /* use the decoded data segments to build the frame */ | |
418 x = y = 0; | |
419 while (total_pixels) { | |
420 | |
421 opcode = *method1_buffer++; | |
422 size = 0; | |
423 | |
424 switch (opcode) { | |
425 | |
426 case 0: | |
427 flag ^= 1; | |
428 continue; | |
429 | |
430 case 1: | |
431 case 2: | |
432 case 3: | |
433 case 4: | |
434 case 5: | |
435 case 6: | |
436 case 7: | |
437 case 8: | |
438 size = opcode; | |
439 break; | |
440 | |
441 case 12: | |
442 case 13: | |
443 case 14: | |
444 case 15: | |
445 case 16: | |
446 case 17: | |
447 case 18: | |
448 size += (opcode - 10); | |
449 break; | |
450 | |
451 case 9: | |
452 case 19: | |
453 size = *size_segment++; | |
454 break; | |
455 | |
456 case 10: | |
457 case 20: | |
458 size = BE_16(&size_segment[0]); | |
459 size_segment += 2; | |
460 break; | |
461 | |
462 case 11: | |
463 case 21: | |
464 size = (size_segment[0] << 16) | (size_segment[1] << 8) | | |
465 size_segment[2]; | |
466 size_segment += 3; | |
467 break; | |
468 } | |
469 | |
470 if (opcode < 12) { | |
471 flag ^= 1; | |
472 if (flag) { | |
473 /* run of (size) pixels is unchanged from last frame */ | |
474 xan_wc3_copy_pixel_run(s, x, y, size, 0, 0); | |
475 } else { | |
476 /* output a run of pixels from method2_buffer */ | |
477 xan_wc3_output_pixel_run(s, method2_buffer, x, y, size); | |
478 method2_buffer += size; | |
479 } | |
480 } else { | |
481 /* run-based motion compensation from last frame */ | |
482 motion_x = (*vector_segment >> 4) & 0xF; | |
483 motion_y = *vector_segment & 0xF; | |
484 vector_segment++; | |
485 | |
486 /* sign extension */ | |
487 if (motion_x & 0x8) | |
488 motion_x |= 0xFFFFFFF0; | |
489 if (motion_y & 0x8) | |
490 motion_y |= 0xFFFFFFF0; | |
491 | |
492 /* copy a run of pixels from the previous frame */ | |
493 xan_wc3_copy_pixel_run(s, x, y, size, motion_x, motion_y); | |
494 | |
495 flag = 0; | |
496 } | |
497 | |
498 /* coordinate accounting */ | |
499 total_pixels -= size; | |
500 while (size) { | |
501 if (x + size >= width) { | |
502 y++; | |
503 size -= (width - x); | |
504 x = 0; | |
505 } else { | |
506 x += size; | |
507 size = 0; | |
508 } | |
509 } | |
510 } | |
511 } | |
512 | |
513 static void xan_wc4_decode_frame(XanContext *s) { | |
514 } | |
515 | |
516 static int xan_decode_frame(AVCodecContext *avctx, | |
517 void *data, int *data_size, | |
518 uint8_t *buf, int buf_size) | |
519 { | |
520 XanContext *s = avctx->priv_data; | |
521 unsigned char *palette_control = avctx->extradata; | |
522 int keyframe = 0; | |
523 | |
524 if (palette_control[0]) { | |
525 /* load the new palette and reset the palette control */ | |
526 xan_wc3_build_palette(s, &palette_control[1]); | |
527 palette_control[0] = 0; | |
528 keyframe = 1; | |
529 } | |
530 | |
531 if (avctx->get_buffer(avctx, &s->current_frame)) { | |
532 printf (" Interplay Video: get_buffer() failed\n"); | |
533 return -1; | |
534 } | |
535 | |
536 s->buf = buf; | |
537 s->size = buf_size; | |
538 | |
539 if (avctx->codec->id == CODEC_ID_XAN_WC3) { | |
540 // if (keyframe) | |
541 if (1) | |
542 xan_wc3_decode_frame(s); | |
543 else { | |
544 memcpy(s->current_frame.data[0], s->last_frame.data[0], | |
545 s->current_frame.linesize[0] * avctx->height); | |
546 memcpy(s->current_frame.data[1], s->last_frame.data[1], | |
547 s->current_frame.linesize[1] * avctx->height); | |
548 memcpy(s->current_frame.data[2], s->last_frame.data[2], | |
549 s->current_frame.linesize[2] * avctx->height); | |
550 } | |
551 } else if (avctx->codec->id == CODEC_ID_XAN_WC4) | |
552 xan_wc4_decode_frame(s); | |
553 | |
554 /* release the last frame if it is allocated */ | |
555 if (s->last_frame.data[0]) | |
556 avctx->release_buffer(avctx, &s->last_frame); | |
557 | |
558 /* shuffle frames */ | |
559 s->last_frame = s->current_frame; | |
560 | |
561 *data_size = sizeof(AVFrame); | |
562 *(AVFrame*)data = s->current_frame; | |
563 | |
564 /* always report that the buffer was completely consumed */ | |
565 return buf_size; | |
566 } | |
567 | |
568 static int xan_decode_end(AVCodecContext *avctx) | |
569 { | |
570 XanContext *s = avctx->priv_data; | |
571 | |
572 /* release the last frame */ | |
573 avctx->release_buffer(avctx, &s->last_frame); | |
574 | |
575 av_free(s->buffer1); | |
576 av_free(s->buffer2); | |
577 | |
578 return 0; | |
579 } | |
580 | |
581 AVCodec xan_wc3_decoder = { | |
582 "xan_wc3", | |
583 CODEC_TYPE_VIDEO, | |
584 CODEC_ID_XAN_WC3, | |
585 sizeof(XanContext), | |
586 xan_decode_init, | |
587 NULL, | |
588 xan_decode_end, | |
589 xan_decode_frame, | |
590 CODEC_CAP_DR1, | |
591 }; | |
592 | |
593 /* | |
594 AVCodec xan_wc4_decoder = { | |
595 "xan_wc4", | |
596 CODEC_TYPE_VIDEO, | |
597 CODEC_ID_XAN_WC4, | |
598 sizeof(XanContext), | |
599 xan_decode_init, | |
600 NULL, | |
601 xan_decode_end, | |
602 xan_decode_frame, | |
603 CODEC_CAP_DR1, | |
604 }; | |
605 */ |