Statistics
| Branch: | Revision:

ffmpeg / libavcodec / xan.c @ 72415b2a

History | View | Annotate | Download (11.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
 * @file libavcodec/xan.c
24
 * Xan video decoder for Wing Commander III computer game
25
 * by Mario Brito (mbrito@student.dei.uc.pt)
26
 * and Mike Melanson (melanson@pcisys.net)
27
 *
28
 * The xan_wc3 decoder outputs PAL8 data.
29
 */
30

    
31
#include <stdio.h>
32
#include <stdlib.h>
33
#include <string.h>
34

    
35
#include "libavutil/intreadwrite.h"
36
#include "avcodec.h"
37
#include "bytestream.h"
38
#define ALT_BITSTREAM_READER_LE
39
#include "get_bits.h"
40
// for av_memcpy_backptr
41
#include "libavutil/lzo.h"
42

    
43
typedef struct XanContext {
44

    
45
    AVCodecContext *avctx;
46
    AVFrame last_frame;
47
    AVFrame current_frame;
48

    
49
    const unsigned char *buf;
50
    int size;
51

    
52
    /* scratch space */
53
    unsigned char *buffer1;
54
    int buffer1_size;
55
    unsigned char *buffer2;
56
    int buffer2_size;
57

    
58
    int frame_size;
59

    
60
} XanContext;
61

    
62
static av_cold int xan_decode_init(AVCodecContext *avctx)
63
{
64
    XanContext *s = avctx->priv_data;
65

    
66
    s->avctx = avctx;
67
    s->frame_size = 0;
68

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

    
75
    avctx->pix_fmt = PIX_FMT_PAL8;
76

    
77
    s->buffer1_size = avctx->width * avctx->height;
78
    s->buffer1 = av_malloc(s->buffer1_size);
79
    if (!s->buffer1)
80
        return -1;
81
    s->buffer2_size = avctx->width * avctx->height;
82
    s->buffer2 = av_malloc(s->buffer2_size + 130);
83
    if (!s->buffer2) {
84
        av_freep(&s->buffer1);
85
        return -1;
86
    }
87

    
88
    return 0;
89
}
90

    
91
static int xan_huffman_decode(unsigned char *dest, const unsigned char *src,
92
    int dest_len)
93
{
94
    unsigned char byte = *src++;
95
    unsigned char ival = byte + 0x16;
96
    const unsigned char * ptr = src + byte*2;
97
    unsigned char val = ival;
98
    unsigned char *dest_end = dest + dest_len;
99
    GetBitContext gb;
100

    
101
    init_get_bits(&gb, ptr, 0); // FIXME: no src size available
102

    
103
    while ( val != 0x16 ) {
104
        val = src[val - 0x17 + get_bits1(&gb) * byte];
105

    
106
        if ( val < 0x16 ) {
107
            if (dest >= dest_end)
108
                return 0;
109
            *dest++ = val;
110
            val = ival;
111
        }
112
    }
113

    
114
    return 0;
115
}
116

    
117
/**
118
 * unpack simple compression
119
 *
120
 * @param dest destination buffer of dest_len, must be padded with at least 130 bytes
121
 */
122
static void xan_unpack(unsigned char *dest, const unsigned char *src, int dest_len)
123
{
124
    unsigned char opcode;
125
    int size;
126
    unsigned char *dest_end = dest + dest_len;
127

    
128
    while (dest < dest_end) {
129
        opcode = *src++;
130

    
131
        if (opcode < 0xe0) {
132
            int size2, back;
133
            if ( (opcode & 0x80) == 0 ) {
134

    
135
                size = opcode & 3;
136

    
137
                back  = ((opcode & 0x60) << 3) + *src++ + 1;
138
                size2 = ((opcode & 0x1c) >> 2) + 3;
139

    
140
            } else if ( (opcode & 0x40) == 0 ) {
141

    
142
                size = *src >> 6;
143

    
144
                back  = (bytestream_get_be16(&src) & 0x3fff) + 1;
145
                size2 = (opcode & 0x3f) + 4;
146

    
147
            } else {
148

    
149
                size = opcode & 3;
150

    
151
                back  = ((opcode & 0x10) << 12) + bytestream_get_be16(&src) + 1;
152
                size2 = ((opcode & 0x0c) <<  6) + *src++ + 5;
153
                if (size + size2 > dest_end - dest)
154
                    return;
155
            }
156
            memcpy(dest, src, size);  dest += size;  src += size;
157
            av_memcpy_backptr(dest, back, size2);
158
            dest += size2;
159
        } else {
160
            int finish = opcode >= 0xfc;
161
            size = finish ? opcode & 3 : ((opcode & 0x1f) << 2) + 4;
162

    
163
            memcpy(dest, src, size);  dest += size;  src += size;
164
            if (finish)
165
                return;
166
        }
167
    }
168
}
169

    
170
static inline void xan_wc3_output_pixel_run(XanContext *s,
171
    const unsigned char *pixel_buffer, int x, int y, int pixel_count)
172
{
173
    int stride;
174
    int line_inc;
175
    int index;
176
    int current_x;
177
    int width = s->avctx->width;
178
    unsigned char *palette_plane;
179

    
180
    palette_plane = s->current_frame.data[0];
181
    stride = s->current_frame.linesize[0];
182
    line_inc = stride - width;
183
    index = y * stride + x;
184
    current_x = x;
185
    while(pixel_count && (index < s->frame_size)) {
186
        int count = FFMIN(pixel_count, width - current_x);
187
        memcpy(palette_plane + index, pixel_buffer, count);
188
        pixel_count  -= count;
189
        index        += count;
190
        pixel_buffer += count;
191
        current_x    += count;
192

    
193
        if (current_x >= width) {
194
            index += line_inc;
195
            current_x = 0;
196
        }
197
    }
198
}
199

    
200
static inline void xan_wc3_copy_pixel_run(XanContext *s,
201
    int x, int y, int pixel_count, int motion_x, int motion_y)
202
{
203
    int stride;
204
    int line_inc;
205
    int curframe_index, prevframe_index;
206
    int curframe_x, prevframe_x;
207
    int width = s->avctx->width;
208
    unsigned char *palette_plane, *prev_palette_plane;
209

    
210
    palette_plane = s->current_frame.data[0];
211
    prev_palette_plane = s->last_frame.data[0];
212
    stride = s->current_frame.linesize[0];
213
    line_inc = stride - width;
214
    curframe_index = y * stride + x;
215
    curframe_x = x;
216
    prevframe_index = (y + motion_y) * stride + x + motion_x;
217
    prevframe_x = x + motion_x;
218
    while(pixel_count && (curframe_index < s->frame_size)) {
219
        int count = FFMIN3(pixel_count, width - curframe_x, width - prevframe_x);
220

    
221
        memcpy(palette_plane + curframe_index, prev_palette_plane + prevframe_index, count);
222
        pixel_count     -= count;
223
        curframe_index  += count;
224
        prevframe_index += count;
225
        curframe_x      += count;
226
        prevframe_x     += count;
227

    
228
        if (curframe_x >= width) {
229
            curframe_index += line_inc;
230
            curframe_x = 0;
231
        }
232

    
233
        if (prevframe_x >= width) {
234
            prevframe_index += line_inc;
235
            prevframe_x = 0;
236
        }
237
    }
238
}
239

    
240
static void xan_wc3_decode_frame(XanContext *s) {
241

    
242
    int width = s->avctx->width;
243
    int height = s->avctx->height;
244
    int total_pixels = width * height;
245
    unsigned char opcode;
246
    unsigned char flag = 0;
247
    int size = 0;
248
    int motion_x, motion_y;
249
    int x, y;
250

    
251
    unsigned char *opcode_buffer = s->buffer1;
252
    int opcode_buffer_size = s->buffer1_size;
253
    const unsigned char *imagedata_buffer = s->buffer2;
254

    
255
    /* pointers to segments inside the compressed chunk */
256
    const unsigned char *huffman_segment;
257
    const unsigned char *size_segment;
258
    const unsigned char *vector_segment;
259
    const unsigned char *imagedata_segment;
260

    
261
    huffman_segment =   s->buf + AV_RL16(&s->buf[0]);
262
    size_segment =      s->buf + AV_RL16(&s->buf[2]);
263
    vector_segment =    s->buf + AV_RL16(&s->buf[4]);
264
    imagedata_segment = s->buf + AV_RL16(&s->buf[6]);
265

    
266
    xan_huffman_decode(opcode_buffer, huffman_segment, opcode_buffer_size);
267

    
268
    if (imagedata_segment[0] == 2)
269
        xan_unpack(s->buffer2, &imagedata_segment[1], s->buffer2_size);
270
    else
271
        imagedata_buffer = &imagedata_segment[1];
272

    
273
    /* use the decoded data segments to build the frame */
274
    x = y = 0;
275
    while (total_pixels) {
276

    
277
        opcode = *opcode_buffer++;
278
        size = 0;
279

    
280
        switch (opcode) {
281

    
282
        case 0:
283
            flag ^= 1;
284
            continue;
285

    
286
        case 1:
287
        case 2:
288
        case 3:
289
        case 4:
290
        case 5:
291
        case 6:
292
        case 7:
293
        case 8:
294
            size = opcode;
295
            break;
296

    
297
        case 12:
298
        case 13:
299
        case 14:
300
        case 15:
301
        case 16:
302
        case 17:
303
        case 18:
304
            size += (opcode - 10);
305
            break;
306

    
307
        case 9:
308
        case 19:
309
            size = *size_segment++;
310
            break;
311

    
312
        case 10:
313
        case 20:
314
            size = AV_RB16(&size_segment[0]);
315
            size_segment += 2;
316
            break;
317

    
318
        case 11:
319
        case 21:
320
            size = AV_RB24(size_segment);
321
            size_segment += 3;
322
            break;
323
        }
324

    
325
        if (opcode < 12) {
326
            flag ^= 1;
327
            if (flag) {
328
                /* run of (size) pixels is unchanged from last frame */
329
                xan_wc3_copy_pixel_run(s, x, y, size, 0, 0);
330
            } else {
331
                /* output a run of pixels from imagedata_buffer */
332
                xan_wc3_output_pixel_run(s, imagedata_buffer, x, y, size);
333
                imagedata_buffer += size;
334
            }
335
        } else {
336
            /* run-based motion compensation from last frame */
337
            motion_x = sign_extend(*vector_segment >> 4,  4);
338
            motion_y = sign_extend(*vector_segment & 0xF, 4);
339
            vector_segment++;
340

    
341
            /* copy a run of pixels from the previous frame */
342
            xan_wc3_copy_pixel_run(s, x, y, size, motion_x, motion_y);
343

    
344
            flag = 0;
345
        }
346

    
347
        /* coordinate accounting */
348
        total_pixels -= size;
349
        y += (x + size) / width;
350
        x  = (x + size) % width;
351
    }
352
}
353

    
354
static void xan_wc4_decode_frame(XanContext *s) {
355
}
356

    
357
static int xan_decode_frame(AVCodecContext *avctx,
358
                            void *data, int *data_size,
359
                            AVPacket *avpkt)
360
{
361
    const uint8_t *buf = avpkt->data;
362
    int buf_size = avpkt->size;
363
    XanContext *s = avctx->priv_data;
364
    AVPaletteControl *palette_control = avctx->palctrl;
365

    
366
    if (avctx->get_buffer(avctx, &s->current_frame)) {
367
        av_log(s->avctx, AV_LOG_ERROR, "  Xan Video: get_buffer() failed\n");
368
        return -1;
369
    }
370
    s->current_frame.reference = 3;
371

    
372
    if (!s->frame_size)
373
        s->frame_size = s->current_frame.linesize[0] * s->avctx->height;
374

    
375
    palette_control->palette_changed = 0;
376
    memcpy(s->current_frame.data[1], palette_control->palette,
377
           AVPALETTE_SIZE);
378
    s->current_frame.palette_has_changed = 1;
379

    
380
    s->buf = buf;
381
    s->size = buf_size;
382

    
383
    if (avctx->codec->id == CODEC_ID_XAN_WC3)
384
        xan_wc3_decode_frame(s);
385
    else if (avctx->codec->id == CODEC_ID_XAN_WC4)
386
        xan_wc4_decode_frame(s);
387

    
388
    /* release the last frame if it is allocated */
389
    if (s->last_frame.data[0])
390
        avctx->release_buffer(avctx, &s->last_frame);
391

    
392
    *data_size = sizeof(AVFrame);
393
    *(AVFrame*)data = s->current_frame;
394

    
395
    /* shuffle frames */
396
    FFSWAP(AVFrame, s->current_frame, s->last_frame);
397

    
398
    /* always report that the buffer was completely consumed */
399
    return buf_size;
400
}
401

    
402
static av_cold int xan_decode_end(AVCodecContext *avctx)
403
{
404
    XanContext *s = avctx->priv_data;
405

    
406
    /* release the frames */
407
    if (s->last_frame.data[0])
408
        avctx->release_buffer(avctx, &s->last_frame);
409
    if (s->current_frame.data[0])
410
        avctx->release_buffer(avctx, &s->current_frame);
411

    
412
    av_freep(&s->buffer1);
413
    av_freep(&s->buffer2);
414

    
415
    return 0;
416
}
417

    
418
AVCodec xan_wc3_decoder = {
419
    "xan_wc3",
420
    AVMEDIA_TYPE_VIDEO,
421
    CODEC_ID_XAN_WC3,
422
    sizeof(XanContext),
423
    xan_decode_init,
424
    NULL,
425
    xan_decode_end,
426
    xan_decode_frame,
427
    CODEC_CAP_DR1,
428
    .long_name = NULL_IF_CONFIG_SMALL("Wing Commander III / Xan"),
429
};
430

    
431
/*
432
AVCodec xan_wc4_decoder = {
433
    "xan_wc4",
434
    AVMEDIA_TYPE_VIDEO,
435
    CODEC_ID_XAN_WC4,
436
    sizeof(XanContext),
437
    xan_decode_init,
438
    NULL,
439
    xan_decode_end,
440
    xan_decode_frame,
441
    CODEC_CAP_DR1,
442
    .long_name = NULL_IF_CONFIG_SMALL("Wing Commander IV / Xxan"),
443
};
444
*/