Statistics
| Branch: | Revision:

ffmpeg / libavcodec / xan.c @ fe037229

History | View | Annotate | Download (12.7 KB)

1
/*
2
 * Wing Commander/Xan Video Decoder
3
 * Copyright (C) 2003 the ffmpeg project
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 *
21
 */
22

    
23
/**
24
 * @file xan.c
25
 * Xan video decoder for Wing Commander III computer game
26
 * by Mario Brito (mbrito@student.dei.uc.pt)
27
 * and Mike Melanson (melanson@pcisys.net)
28
 *
29
 * The xan_wc3 decoder outputs PAL8 data.
30
 */
31

    
32
#include <stdio.h>
33
#include <stdlib.h>
34
#include <string.h>
35
#include <unistd.h>
36

    
37
#include "common.h"
38
#include "avcodec.h"
39

    
40
typedef struct XanContext {
41

    
42
    AVCodecContext *avctx;
43
    AVFrame last_frame;
44
    AVFrame current_frame;
45

    
46
    unsigned char *buf;
47
    int size;
48

    
49
    /* scratch space */
50
    unsigned char *buffer1;
51
    int buffer1_size;
52
    unsigned char *buffer2;
53
    int buffer2_size;
54

    
55
    int frame_size;
56

    
57
} XanContext;
58

    
59
static int xan_decode_init(AVCodecContext *avctx)
60
{
61
    XanContext *s = avctx->priv_data;
62

    
63
    s->avctx = avctx;
64
    s->frame_size = 0;
65

    
66
    if ((avctx->codec->id == CODEC_ID_XAN_WC3) &&
67
        (s->avctx->palctrl == NULL)) {
68
        av_log(avctx, AV_LOG_ERROR, " WC3 Xan video: palette expected.\n");
69
        return -1;
70
    }
71

    
72
    avctx->pix_fmt = PIX_FMT_PAL8;
73
    avctx->has_b_frames = 0;
74

    
75
    if(avcodec_check_dimensions(avctx, avctx->width, avctx->height))
76
        return -1;
77

    
78
    s->buffer1_size = avctx->width * avctx->height;
79
    s->buffer1 = av_malloc(s->buffer1_size);
80
    s->buffer2_size = avctx->width * avctx->height;
81
    s->buffer2 = av_malloc(s->buffer2_size);
82
    if (!s->buffer1 || !s->buffer2)
83
        return -1;
84

    
85
    return 0;
86
}
87

    
88
/* This function is used in lieu of memcpy(). This decoder cannot use
89
 * memcpy because the memory locations often overlap and
90
 * memcpy doesn't like that; it's not uncommon, for example, for
91
 * dest = src+1, to turn byte A into  pattern AAAAAAAA.
92
 * This was originally repz movsb in Intel x86 ASM. */
93
static inline void bytecopy(unsigned char *dest, unsigned char *src, int count)
94
{
95
    int i;
96

    
97
    for (i = 0; i < count; i++)
98
        dest[i] = src[i];
99
}
100

    
101
static int xan_huffman_decode(unsigned char *dest, unsigned char *src,
102
    int dest_len)
103
{
104
    unsigned char byte = *src++;
105
    unsigned char ival = byte + 0x16;
106
    unsigned char * ptr = src + byte*2;
107
    unsigned char val = ival;
108
    int counter = 0;
109
    unsigned char *dest_end = dest + dest_len;
110

    
111
    unsigned char bits = *ptr++;
112

    
113
    while ( val != 0x16 ) {
114
        if ( (1 << counter) & bits )
115
            val = src[byte + val - 0x17];
116
        else
117
            val = src[val - 0x17];
118

    
119
        if ( val < 0x16 ) {
120
            if (dest + 1 > dest_end)
121
                return 0;
122
            *dest++ = val;
123
            val = ival;
124
        }
125

    
126
        if (counter++ == 7) {
127
            counter = 0;
128
            bits = *ptr++;
129
        }
130
    }
131

    
132
    return 0;
133
}
134

    
135
static void xan_unpack(unsigned char *dest, unsigned char *src, int dest_len)
136
{
137
    unsigned char opcode;
138
    int size;
139
    int offset;
140
    int byte1, byte2, byte3;
141
    unsigned char *dest_end = dest + dest_len;
142

    
143
    for (;;) {
144
        opcode = *src++;
145

    
146
        if ( (opcode & 0x80) == 0 ) {
147

    
148
            offset = *src++;
149

    
150
            size = opcode & 3;
151
            if (dest + size > dest_end)
152
                return;
153
            bytecopy(dest, src, size);  dest += size;  src += size;
154

    
155
            size = ((opcode & 0x1c) >> 2) + 3;
156
            if (dest + size > dest_end)
157
                return;
158
            bytecopy (dest, dest - (((opcode & 0x60) << 3) + offset + 1), size);
159
            dest += size;
160

    
161
        } else if ( (opcode & 0x40) == 0 ) {
162

    
163
            byte1 = *src++;
164
            byte2 = *src++;
165

    
166
            size = byte1 >> 6;
167
            if (dest + size > dest_end)
168
                return;
169
            bytecopy (dest, src, size);  dest += size;  src += size;
170

    
171
            size = (opcode & 0x3f) + 4;
172
            if (dest + size > dest_end)
173
                return;
174
            bytecopy (dest, dest - (((byte1 & 0x3f) << 8) + byte2 + 1), size);
175
            dest += size;
176

    
177
        } else if ( (opcode & 0x20) == 0 ) {
178

    
179
            byte1 = *src++;
180
            byte2 = *src++;
181
            byte3 = *src++;
182

    
183
            size = opcode & 3;
184
            if (dest + size > dest_end)
185
                return;
186
            bytecopy (dest, src, size);  dest += size;  src += size;
187

    
188
            size = byte3 + 5 + ((opcode & 0xc) << 6);
189
            if (dest + size > dest_end)
190
                return;
191
            bytecopy (dest,
192
                dest - ((((opcode & 0x10) >> 4) << 0x10) + 1 + (byte1 << 8) + byte2),
193
                size);
194
            dest += size;
195
        } else {
196
            size = ((opcode & 0x1f) << 2) + 4;
197

    
198
            if (size > 0x70)
199
                break;
200

    
201
            if (dest + size > dest_end)
202
                return;
203
            bytecopy (dest, src, size);  dest += size;  src += size;
204
        }
205
    }
206

    
207
    size = opcode & 3;
208
    bytecopy(dest, src, size);  dest += size;  src += size;
209
}
210

    
211
static void inline xan_wc3_output_pixel_run(XanContext *s,
212
    unsigned char *pixel_buffer, int x, int y, int pixel_count)
213
{
214
    int stride;
215
    int line_inc;
216
    int index;
217
    int current_x;
218
    int width = s->avctx->width;
219
    unsigned char *palette_plane;
220

    
221
    palette_plane = s->current_frame.data[0];
222
    stride = s->current_frame.linesize[0];
223
    line_inc = stride - width;
224
    index = y * stride + x;
225
    current_x = x;
226
    while((pixel_count--) && (index < s->frame_size)) {
227

    
228
        /* don't do a memcpy() here; keyframes generally copy an entire
229
         * frame of data and the stride needs to be accounted for */
230
        palette_plane[index++] = *pixel_buffer++;
231

    
232
        current_x++;
233
        if (current_x >= width) {
234
            index += line_inc;
235
            current_x = 0;
236
        }
237
    }
238
}
239

    
240
static void inline xan_wc3_copy_pixel_run(XanContext *s,
241
    int x, int y, int pixel_count, int motion_x, int motion_y)
242
{
243
    int stride;
244
    int line_inc;
245
    int curframe_index, prevframe_index;
246
    int curframe_x, prevframe_x;
247
    int width = s->avctx->width;
248
    unsigned char *palette_plane, *prev_palette_plane;
249

    
250
    palette_plane = s->current_frame.data[0];
251
    prev_palette_plane = s->last_frame.data[0];
252
    stride = s->current_frame.linesize[0];
253
    line_inc = stride - width;
254
    curframe_index = y * stride + x;
255
    curframe_x = x;
256
    prevframe_index = (y + motion_y) * stride + x + motion_x;
257
    prevframe_x = x + motion_x;
258
    while((pixel_count--) && (curframe_index < s->frame_size)) {
259

    
260
        palette_plane[curframe_index++] =
261
            prev_palette_plane[prevframe_index++];
262

    
263
        curframe_x++;
264
        if (curframe_x >= width) {
265
            curframe_index += line_inc;
266
            curframe_x = 0;
267
        }
268

    
269
        prevframe_x++;
270
        if (prevframe_x >= width) {
271
            prevframe_index += line_inc;
272
            prevframe_x = 0;
273
        }
274
    }
275
}
276

    
277
static void xan_wc3_decode_frame(XanContext *s) {
278

    
279
    int width = s->avctx->width;
280
    int height = s->avctx->height;
281
    int total_pixels = width * height;
282
    unsigned char opcode;
283
    unsigned char flag = 0;
284
    int size = 0;
285
    int motion_x, motion_y;
286
    int x, y;
287

    
288
    unsigned char *opcode_buffer = s->buffer1;
289
    int opcode_buffer_size = s->buffer1_size;
290
    unsigned char *imagedata_buffer = s->buffer2;
291
    int imagedata_buffer_size = s->buffer2_size;
292

    
293
    /* pointers to segments inside the compressed chunk */
294
    unsigned char *huffman_segment;
295
    unsigned char *size_segment;
296
    unsigned char *vector_segment;
297
    unsigned char *imagedata_segment;
298

    
299
    huffman_segment =   s->buf + AV_RL16(&s->buf[0]);
300
    size_segment =      s->buf + AV_RL16(&s->buf[2]);
301
    vector_segment =    s->buf + AV_RL16(&s->buf[4]);
302
    imagedata_segment = s->buf + AV_RL16(&s->buf[6]);
303

    
304
    xan_huffman_decode(opcode_buffer, huffman_segment, opcode_buffer_size);
305

    
306
    if (imagedata_segment[0] == 2)
307
        xan_unpack(imagedata_buffer, &imagedata_segment[1],
308
            imagedata_buffer_size);
309
    else
310
        imagedata_buffer = &imagedata_segment[1];
311

    
312
    /* use the decoded data segments to build the frame */
313
    x = y = 0;
314
    while (total_pixels) {
315

    
316
        opcode = *opcode_buffer++;
317
        size = 0;
318

    
319
        switch (opcode) {
320

    
321
        case 0:
322
            flag ^= 1;
323
            continue;
324

    
325
        case 1:
326
        case 2:
327
        case 3:
328
        case 4:
329
        case 5:
330
        case 6:
331
        case 7:
332
        case 8:
333
            size = opcode;
334
            break;
335

    
336
        case 12:
337
        case 13:
338
        case 14:
339
        case 15:
340
        case 16:
341
        case 17:
342
        case 18:
343
            size += (opcode - 10);
344
            break;
345

    
346
        case 9:
347
        case 19:
348
            size = *size_segment++;
349
            break;
350

    
351
        case 10:
352
        case 20:
353
            size = AV_RB16(&size_segment[0]);
354
            size_segment += 2;
355
            break;
356

    
357
        case 11:
358
        case 21:
359
            size = (size_segment[0] << 16) | (size_segment[1] << 8) |
360
                size_segment[2];
361
            size_segment += 3;
362
            break;
363
        }
364

    
365
        if (opcode < 12) {
366
            flag ^= 1;
367
            if (flag) {
368
                /* run of (size) pixels is unchanged from last frame */
369
                xan_wc3_copy_pixel_run(s, x, y, size, 0, 0);
370
            } else {
371
                /* output a run of pixels from imagedata_buffer */
372
                xan_wc3_output_pixel_run(s, imagedata_buffer, x, y, size);
373
                imagedata_buffer += size;
374
            }
375
        } else {
376
            /* run-based motion compensation from last frame */
377
            motion_x = (*vector_segment >> 4) & 0xF;
378
            motion_y = *vector_segment & 0xF;
379
            vector_segment++;
380

    
381
            /* sign extension */
382
            if (motion_x & 0x8)
383
                motion_x |= 0xFFFFFFF0;
384
            if (motion_y & 0x8)
385
                motion_y |= 0xFFFFFFF0;
386

    
387
            /* copy a run of pixels from the previous frame */
388
            xan_wc3_copy_pixel_run(s, x, y, size, motion_x, motion_y);
389

    
390
            flag = 0;
391
        }
392

    
393
        /* coordinate accounting */
394
        total_pixels -= size;
395
        while (size) {
396
            if (x + size >= width) {
397
                y++;
398
                size -= (width - x);
399
                x = 0;
400
            } else {
401
                x += size;
402
                size = 0;
403
            }
404
        }
405
    }
406
}
407

    
408
static void xan_wc4_decode_frame(XanContext *s) {
409
}
410

    
411
static int xan_decode_frame(AVCodecContext *avctx,
412
                            void *data, int *data_size,
413
                            uint8_t *buf, int buf_size)
414
{
415
    XanContext *s = avctx->priv_data;
416
    AVPaletteControl *palette_control = avctx->palctrl;
417

    
418
    if (avctx->get_buffer(avctx, &s->current_frame)) {
419
        av_log(s->avctx, AV_LOG_ERROR, "  Xan Video: get_buffer() failed\n");
420
        return -1;
421
    }
422
    s->current_frame.reference = 3;
423

    
424
    if (!s->frame_size)
425
        s->frame_size = s->current_frame.linesize[0] * s->avctx->height;
426

    
427
    palette_control->palette_changed = 0;
428
    memcpy(s->current_frame.data[1], palette_control->palette,
429
        AVPALETTE_SIZE);
430
    s->current_frame.palette_has_changed = 1;
431

    
432
    s->buf = buf;
433
    s->size = buf_size;
434

    
435
    if (avctx->codec->id == CODEC_ID_XAN_WC3)
436
        xan_wc3_decode_frame(s);
437
    else if (avctx->codec->id == CODEC_ID_XAN_WC4)
438
        xan_wc4_decode_frame(s);
439

    
440
    /* release the last frame if it is allocated */
441
    if (s->last_frame.data[0])
442
        avctx->release_buffer(avctx, &s->last_frame);
443

    
444
    /* shuffle frames */
445
    s->last_frame = s->current_frame;
446

    
447
    *data_size = sizeof(AVFrame);
448
    *(AVFrame*)data = s->current_frame;
449

    
450
    /* always report that the buffer was completely consumed */
451
    return buf_size;
452
}
453

    
454
static int xan_decode_end(AVCodecContext *avctx)
455
{
456
    XanContext *s = avctx->priv_data;
457

    
458
    /* release the last frame */
459
    if (s->last_frame.data[0])
460
        avctx->release_buffer(avctx, &s->last_frame);
461

    
462
    av_free(s->buffer1);
463
    av_free(s->buffer2);
464

    
465
    return 0;
466
}
467

    
468
AVCodec xan_wc3_decoder = {
469
    "xan_wc3",
470
    CODEC_TYPE_VIDEO,
471
    CODEC_ID_XAN_WC3,
472
    sizeof(XanContext),
473
    xan_decode_init,
474
    NULL,
475
    xan_decode_end,
476
    xan_decode_frame,
477
    CODEC_CAP_DR1,
478
};
479

    
480
/*
481
AVCodec xan_wc4_decoder = {
482
    "xan_wc4",
483
    CODEC_TYPE_VIDEO,
484
    CODEC_ID_XAN_WC4,
485
    sizeof(XanContext),
486
    xan_decode_init,
487
    NULL,
488
    xan_decode_end,
489
    xan_decode_frame,
490
    CODEC_CAP_DR1,
491
};
492
*/