Statistics
| Branch: | Revision:

ffmpeg / libavcodec / xan.c @ 18d761a1

History | View | Annotate | Download (16.9 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
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
#define RUNTIME_GAMMA 0
44

    
45
#define VGA__TAG MKTAG('V', 'G', 'A', ' ')
46
#define PALT_TAG MKTAG('P', 'A', 'L', 'T')
47
#define SHOT_TAG MKTAG('S', 'H', 'O', 'T')
48
#define PALETTE_COUNT 256
49
#define PALETTE_SIZE (PALETTE_COUNT * 3)
50
#define PALETTES_MAX 256
51

    
52
typedef struct XanContext {
53

    
54
    AVCodecContext *avctx;
55
    AVFrame last_frame;
56
    AVFrame current_frame;
57

    
58
    const unsigned char *buf;
59
    int size;
60

    
61
    /* scratch space */
62
    unsigned char *buffer1;
63
    int buffer1_size;
64
    unsigned char *buffer2;
65
    int buffer2_size;
66

    
67
    unsigned *palettes;
68
    int palettes_count;
69
    int cur_palette;
70

    
71
    int frame_size;
72

    
73
} XanContext;
74

    
75
static av_cold int xan_decode_init(AVCodecContext *avctx)
76
{
77
    XanContext *s = avctx->priv_data;
78

    
79
    s->avctx = avctx;
80
    s->frame_size = 0;
81

    
82
    avctx->pix_fmt = PIX_FMT_PAL8;
83

    
84
    s->buffer1_size = avctx->width * avctx->height;
85
    s->buffer1 = av_malloc(s->buffer1_size);
86
    if (!s->buffer1)
87
        return AVERROR(ENOMEM);
88
    s->buffer2_size = avctx->width * avctx->height;
89
    s->buffer2 = av_malloc(s->buffer2_size + 130);
90
    if (!s->buffer2) {
91
        av_freep(&s->buffer1);
92
        return AVERROR(ENOMEM);
93
    }
94

    
95
    return 0;
96
}
97

    
98
static int xan_huffman_decode(unsigned char *dest, const unsigned char *src,
99
    int dest_len)
100
{
101
    unsigned char byte = *src++;
102
    unsigned char ival = byte + 0x16;
103
    const unsigned char * ptr = src + byte*2;
104
    unsigned char val = ival;
105
    unsigned char *dest_end = dest + dest_len;
106
    GetBitContext gb;
107

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

    
110
    while ( val != 0x16 ) {
111
        val = src[val - 0x17 + get_bits1(&gb) * byte];
112

    
113
        if ( val < 0x16 ) {
114
            if (dest >= dest_end)
115
                return 0;
116
            *dest++ = val;
117
            val = ival;
118
        }
119
    }
120

    
121
    return 0;
122
}
123

    
124
/**
125
 * unpack simple compression
126
 *
127
 * @param dest destination buffer of dest_len, must be padded with at least 130 bytes
128
 */
129
static void xan_unpack(unsigned char *dest, const unsigned char *src, int dest_len)
130
{
131
    unsigned char opcode;
132
    int size;
133
    unsigned char *dest_end = dest + dest_len;
134

    
135
    while (dest < dest_end) {
136
        opcode = *src++;
137

    
138
        if (opcode < 0xe0) {
139
            int size2, back;
140
            if ( (opcode & 0x80) == 0 ) {
141

    
142
                size = opcode & 3;
143

    
144
                back  = ((opcode & 0x60) << 3) + *src++ + 1;
145
                size2 = ((opcode & 0x1c) >> 2) + 3;
146

    
147
            } else if ( (opcode & 0x40) == 0 ) {
148

    
149
                size = *src >> 6;
150

    
151
                back  = (bytestream_get_be16(&src) & 0x3fff) + 1;
152
                size2 = (opcode & 0x3f) + 4;
153

    
154
            } else {
155

    
156
                size = opcode & 3;
157

    
158
                back  = ((opcode & 0x10) << 12) + bytestream_get_be16(&src) + 1;
159
                size2 = ((opcode & 0x0c) <<  6) + *src++ + 5;
160
                if (size + size2 > dest_end - dest)
161
                    return;
162
            }
163
            memcpy(dest, src, size);  dest += size;  src += size;
164
            av_memcpy_backptr(dest, back, size2);
165
            dest += size2;
166
        } else {
167
            int finish = opcode >= 0xfc;
168
            size = finish ? opcode & 3 : ((opcode & 0x1f) << 2) + 4;
169

    
170
            memcpy(dest, src, size);  dest += size;  src += size;
171
            if (finish)
172
                return;
173
        }
174
    }
175
}
176

    
177
static inline void xan_wc3_output_pixel_run(XanContext *s,
178
    const unsigned char *pixel_buffer, int x, int y, int pixel_count)
179
{
180
    int stride;
181
    int line_inc;
182
    int index;
183
    int current_x;
184
    int width = s->avctx->width;
185
    unsigned char *palette_plane;
186

    
187
    palette_plane = s->current_frame.data[0];
188
    stride = s->current_frame.linesize[0];
189
    line_inc = stride - width;
190
    index = y * stride + x;
191
    current_x = x;
192
    while(pixel_count && (index < s->frame_size)) {
193
        int count = FFMIN(pixel_count, width - current_x);
194
        memcpy(palette_plane + index, pixel_buffer, count);
195
        pixel_count  -= count;
196
        index        += count;
197
        pixel_buffer += count;
198
        current_x    += count;
199

    
200
        if (current_x >= width) {
201
            index += line_inc;
202
            current_x = 0;
203
        }
204
    }
205
}
206

    
207
static inline void xan_wc3_copy_pixel_run(XanContext *s,
208
    int x, int y, int pixel_count, int motion_x, int motion_y)
209
{
210
    int stride;
211
    int line_inc;
212
    int curframe_index, prevframe_index;
213
    int curframe_x, prevframe_x;
214
    int width = s->avctx->width;
215
    unsigned char *palette_plane, *prev_palette_plane;
216

    
217
    palette_plane = s->current_frame.data[0];
218
    prev_palette_plane = s->last_frame.data[0];
219
    stride = s->current_frame.linesize[0];
220
    line_inc = stride - width;
221
    curframe_index = y * stride + x;
222
    curframe_x = x;
223
    prevframe_index = (y + motion_y) * stride + x + motion_x;
224
    prevframe_x = x + motion_x;
225
    while(pixel_count && (curframe_index < s->frame_size)) {
226
        int count = FFMIN3(pixel_count, width - curframe_x, width - prevframe_x);
227

    
228
        memcpy(palette_plane + curframe_index, prev_palette_plane + prevframe_index, count);
229
        pixel_count     -= count;
230
        curframe_index  += count;
231
        prevframe_index += count;
232
        curframe_x      += count;
233
        prevframe_x     += count;
234

    
235
        if (curframe_x >= width) {
236
            curframe_index += line_inc;
237
            curframe_x = 0;
238
        }
239

    
240
        if (prevframe_x >= width) {
241
            prevframe_index += line_inc;
242
            prevframe_x = 0;
243
        }
244
    }
245
}
246

    
247
static void xan_wc3_decode_frame(XanContext *s) {
248

    
249
    int width = s->avctx->width;
250
    int height = s->avctx->height;
251
    int total_pixels = width * height;
252
    unsigned char opcode;
253
    unsigned char flag = 0;
254
    int size = 0;
255
    int motion_x, motion_y;
256
    int x, y;
257

    
258
    unsigned char *opcode_buffer = s->buffer1;
259
    int opcode_buffer_size = s->buffer1_size;
260
    const unsigned char *imagedata_buffer = s->buffer2;
261

    
262
    /* pointers to segments inside the compressed chunk */
263
    const unsigned char *huffman_segment;
264
    const unsigned char *size_segment;
265
    const unsigned char *vector_segment;
266
    const unsigned char *imagedata_segment;
267

    
268
    huffman_segment =   s->buf + AV_RL16(&s->buf[0]);
269
    size_segment =      s->buf + AV_RL16(&s->buf[2]);
270
    vector_segment =    s->buf + AV_RL16(&s->buf[4]);
271
    imagedata_segment = s->buf + AV_RL16(&s->buf[6]);
272

    
273
    xan_huffman_decode(opcode_buffer, huffman_segment, opcode_buffer_size);
274

    
275
    if (imagedata_segment[0] == 2)
276
        xan_unpack(s->buffer2, &imagedata_segment[1], s->buffer2_size);
277
    else
278
        imagedata_buffer = &imagedata_segment[1];
279

    
280
    /* use the decoded data segments to build the frame */
281
    x = y = 0;
282
    while (total_pixels) {
283

    
284
        opcode = *opcode_buffer++;
285
        size = 0;
286

    
287
        switch (opcode) {
288

    
289
        case 0:
290
            flag ^= 1;
291
            continue;
292

    
293
        case 1:
294
        case 2:
295
        case 3:
296
        case 4:
297
        case 5:
298
        case 6:
299
        case 7:
300
        case 8:
301
            size = opcode;
302
            break;
303

    
304
        case 12:
305
        case 13:
306
        case 14:
307
        case 15:
308
        case 16:
309
        case 17:
310
        case 18:
311
            size += (opcode - 10);
312
            break;
313

    
314
        case 9:
315
        case 19:
316
            size = *size_segment++;
317
            break;
318

    
319
        case 10:
320
        case 20:
321
            size = AV_RB16(&size_segment[0]);
322
            size_segment += 2;
323
            break;
324

    
325
        case 11:
326
        case 21:
327
            size = AV_RB24(size_segment);
328
            size_segment += 3;
329
            break;
330
        }
331

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

    
348
            /* copy a run of pixels from the previous frame */
349
            xan_wc3_copy_pixel_run(s, x, y, size, motion_x, motion_y);
350

    
351
            flag = 0;
352
        }
353

    
354
        /* coordinate accounting */
355
        total_pixels -= size;
356
        y += (x + size) / width;
357
        x  = (x + size) % width;
358
    }
359
}
360

    
361
static void xan_wc4_decode_frame(XanContext *s) {
362
}
363

    
364
#if RUNTIME_GAMMA
365
static inline unsigned mul(unsigned a, unsigned b)
366
{
367
    return (a * b) >> 16;
368
}
369

    
370
static inline unsigned pow4(unsigned a)
371
{
372
    unsigned square = mul(a, a);
373
    return mul(square, square);
374
}
375

    
376
static inline unsigned pow5(unsigned a)
377
{
378
    return mul(pow4(a), a);
379
}
380

    
381
static uint8_t gamma_corr(uint8_t in) {
382
    unsigned lo, hi = 0xff40, target;
383
    int i = 15;
384
    in = (in << 2) | (in >> 6);
385
    /*  equivalent float code:
386
    if (in >= 252)
387
        return 253;
388
    return round(pow(in / 256.0, 0.8) * 256);
389
    */
390
    lo = target = in << 8;
391
    do {
392
        unsigned mid = (lo + hi) >> 1;
393
        unsigned pow = pow5(mid);
394
        if (pow > target) hi = mid;
395
        else lo = mid;
396
    } while (--i);
397
    return (pow4((lo + hi) >> 1) + 0x80) >> 8;
398
}
399
#else
400
/**
401
 * This is a gamma correction that xan3 applies to all palette entries.
402
 *
403
 * There is a peculiarity, namely that the values are clamped to 253 -
404
 * it seems likely that this table was calculated by a buggy fixed-point
405
 * implementation, the one above under RUNTIME_GAMMA behaves like this for
406
 * example.
407
 * The exponent value of 0.8 can be explained by this as well, since 0.8 = 4/5
408
 * and thus pow(x, 0.8) is still easy to calculate.
409
 * Also, the input values are first rotated to the left by 2.
410
 */
411
static const uint8_t gamma_lookup[256] = {
412
    0x00, 0x09, 0x10, 0x16, 0x1C, 0x21, 0x27, 0x2C,
413
    0x31, 0x35, 0x3A, 0x3F, 0x43, 0x48, 0x4C, 0x50,
414
    0x54, 0x59, 0x5D, 0x61, 0x65, 0x69, 0x6D, 0x71,
415
    0x75, 0x79, 0x7D, 0x80, 0x84, 0x88, 0x8C, 0x8F,
416
    0x93, 0x97, 0x9A, 0x9E, 0xA2, 0xA5, 0xA9, 0xAC,
417
    0xB0, 0xB3, 0xB7, 0xBA, 0xBE, 0xC1, 0xC5, 0xC8,
418
    0xCB, 0xCF, 0xD2, 0xD5, 0xD9, 0xDC, 0xDF, 0xE3,
419
    0xE6, 0xE9, 0xED, 0xF0, 0xF3, 0xF6, 0xFA, 0xFD,
420
    0x03, 0x0B, 0x12, 0x18, 0x1D, 0x23, 0x28, 0x2D,
421
    0x32, 0x36, 0x3B, 0x40, 0x44, 0x49, 0x4D, 0x51,
422
    0x56, 0x5A, 0x5E, 0x62, 0x66, 0x6A, 0x6E, 0x72,
423
    0x76, 0x7A, 0x7D, 0x81, 0x85, 0x89, 0x8D, 0x90,
424
    0x94, 0x98, 0x9B, 0x9F, 0xA2, 0xA6, 0xAA, 0xAD,
425
    0xB1, 0xB4, 0xB8, 0xBB, 0xBF, 0xC2, 0xC5, 0xC9,
426
    0xCC, 0xD0, 0xD3, 0xD6, 0xDA, 0xDD, 0xE0, 0xE4,
427
    0xE7, 0xEA, 0xED, 0xF1, 0xF4, 0xF7, 0xFA, 0xFD,
428
    0x05, 0x0D, 0x13, 0x19, 0x1F, 0x24, 0x29, 0x2E,
429
    0x33, 0x38, 0x3C, 0x41, 0x45, 0x4A, 0x4E, 0x52,
430
    0x57, 0x5B, 0x5F, 0x63, 0x67, 0x6B, 0x6F, 0x73,
431
    0x77, 0x7B, 0x7E, 0x82, 0x86, 0x8A, 0x8D, 0x91,
432
    0x95, 0x99, 0x9C, 0xA0, 0xA3, 0xA7, 0xAA, 0xAE,
433
    0xB2, 0xB5, 0xB9, 0xBC, 0xBF, 0xC3, 0xC6, 0xCA,
434
    0xCD, 0xD0, 0xD4, 0xD7, 0xDA, 0xDE, 0xE1, 0xE4,
435
    0xE8, 0xEB, 0xEE, 0xF1, 0xF5, 0xF8, 0xFB, 0xFD,
436
    0x07, 0x0E, 0x15, 0x1A, 0x20, 0x25, 0x2A, 0x2F,
437
    0x34, 0x39, 0x3D, 0x42, 0x46, 0x4B, 0x4F, 0x53,
438
    0x58, 0x5C, 0x60, 0x64, 0x68, 0x6C, 0x70, 0x74,
439
    0x78, 0x7C, 0x7F, 0x83, 0x87, 0x8B, 0x8E, 0x92,
440
    0x96, 0x99, 0x9D, 0xA1, 0xA4, 0xA8, 0xAB, 0xAF,
441
    0xB2, 0xB6, 0xB9, 0xBD, 0xC0, 0xC4, 0xC7, 0xCB,
442
    0xCE, 0xD1, 0xD5, 0xD8, 0xDB, 0xDF, 0xE2, 0xE5,
443
    0xE9, 0xEC, 0xEF, 0xF2, 0xF6, 0xF9, 0xFC, 0xFD
444
};
445
#endif
446

    
447
static int xan_decode_frame(AVCodecContext *avctx,
448
                            void *data, int *data_size,
449
                            AVPacket *avpkt)
450
{
451
    const uint8_t *buf = avpkt->data;
452
    int ret, buf_size = avpkt->size;
453
    XanContext *s = avctx->priv_data;
454

    
455
    if (avctx->codec->id == CODEC_ID_XAN_WC3) {
456
        const uint8_t *buf_end = buf + buf_size;
457
        int tag = 0;
458
        while (buf_end - buf > 8 && tag != VGA__TAG) {
459
            unsigned *tmpptr;
460
            uint32_t new_pal;
461
            int size;
462
            int i;
463
            tag  = bytestream_get_le32(&buf);
464
            size = bytestream_get_be32(&buf);
465
            size = FFMIN(size, buf_end - buf);
466
            switch (tag) {
467
            case PALT_TAG:
468
                if (size < PALETTE_SIZE)
469
                    return AVERROR_INVALIDDATA;
470
                if (s->palettes_count >= PALETTES_MAX)
471
                    return AVERROR_INVALIDDATA;
472
                tmpptr = av_realloc(s->palettes, (s->palettes_count + 1) * AVPALETTE_SIZE);
473
                if (!tmpptr)
474
                    return AVERROR(ENOMEM);
475
                s->palettes = tmpptr;
476
                tmpptr += s->palettes_count * AVPALETTE_COUNT;
477
                for (i = 0; i < PALETTE_COUNT; i++) {
478
#if RUNTIME_GAMMA
479
                    int r = gamma_corr(*buf++);
480
                    int g = gamma_corr(*buf++);
481
                    int b = gamma_corr(*buf++);
482
#else
483
                    int r = gamma_lookup[*buf++];
484
                    int g = gamma_lookup[*buf++];
485
                    int b = gamma_lookup[*buf++];
486
#endif
487
                    *tmpptr++ = (r << 16) | (g << 8) | b;
488
                }
489
                s->palettes_count++;
490
                break;
491
            case SHOT_TAG:
492
                if (size < 4)
493
                    return AVERROR_INVALIDDATA;
494
                new_pal = bytestream_get_le32(&buf);
495
                if (new_pal < s->palettes_count) {
496
                    s->cur_palette = new_pal;
497
                } else
498
                    av_log(avctx, AV_LOG_ERROR, "Invalid palette selected\n");
499
                break;
500
            case VGA__TAG:
501
                break;
502
            default:
503
                buf += size;
504
                break;
505
            }
506
        }
507
        buf_size = buf_end - buf;
508
    }
509
    if ((ret = avctx->get_buffer(avctx, &s->current_frame))) {
510
        av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
511
        return ret;
512
    }
513
    s->current_frame.reference = 3;
514

    
515
    if (!s->frame_size)
516
        s->frame_size = s->current_frame.linesize[0] * s->avctx->height;
517

    
518
    if (avctx->codec->id == CODEC_ID_XAN_WC3) {
519
        memcpy(s->current_frame.data[1], s->palettes + s->cur_palette * AVPALETTE_COUNT, AVPALETTE_SIZE);
520
    } else {
521
        AVPaletteControl *palette_control = avctx->palctrl;
522
        palette_control->palette_changed = 0;
523
        memcpy(s->current_frame.data[1], palette_control->palette,
524
               AVPALETTE_SIZE);
525
        s->current_frame.palette_has_changed = 1;
526
    }
527

    
528
    s->buf = buf;
529
    s->size = buf_size;
530

    
531
    if (avctx->codec->id == CODEC_ID_XAN_WC3)
532
        xan_wc3_decode_frame(s);
533
    else if (avctx->codec->id == CODEC_ID_XAN_WC4)
534
        xan_wc4_decode_frame(s);
535

    
536
    /* release the last frame if it is allocated */
537
    if (s->last_frame.data[0])
538
        avctx->release_buffer(avctx, &s->last_frame);
539

    
540
    *data_size = sizeof(AVFrame);
541
    *(AVFrame*)data = s->current_frame;
542

    
543
    /* shuffle frames */
544
    FFSWAP(AVFrame, s->current_frame, s->last_frame);
545

    
546
    /* always report that the buffer was completely consumed */
547
    return buf_size;
548
}
549

    
550
static av_cold int xan_decode_end(AVCodecContext *avctx)
551
{
552
    XanContext *s = avctx->priv_data;
553

    
554
    /* release the frames */
555
    if (s->last_frame.data[0])
556
        avctx->release_buffer(avctx, &s->last_frame);
557
    if (s->current_frame.data[0])
558
        avctx->release_buffer(avctx, &s->current_frame);
559

    
560
    av_freep(&s->buffer1);
561
    av_freep(&s->buffer2);
562

    
563
    return 0;
564
}
565

    
566
AVCodec xan_wc3_decoder = {
567
    "xan_wc3",
568
    AVMEDIA_TYPE_VIDEO,
569
    CODEC_ID_XAN_WC3,
570
    sizeof(XanContext),
571
    xan_decode_init,
572
    NULL,
573
    xan_decode_end,
574
    xan_decode_frame,
575
    CODEC_CAP_DR1,
576
    .long_name = NULL_IF_CONFIG_SMALL("Wing Commander III / Xan"),
577
};
578

    
579
/*
580
AVCodec xan_wc4_decoder = {
581
    "xan_wc4",
582
    AVMEDIA_TYPE_VIDEO,
583
    CODEC_ID_XAN_WC4,
584
    sizeof(XanContext),
585
    xan_decode_init,
586
    NULL,
587
    xan_decode_end,
588
    xan_decode_frame,
589
    CODEC_CAP_DR1,
590
    .long_name = NULL_IF_CONFIG_SMALL("Wing Commander IV / Xxan"),
591
};
592
*/