~ubuntu-branches/ubuntu/feisty/avidemux/feisty

« back to all changes in this revision

Viewing changes to avidemux/ADM_lavcodec/xan.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel T Chen
  • Date: 2006-12-15 17:13:20 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20061215171320-w79pvpehxx2fr217
Tags: 1:2.3.0-0.0ubuntu1
* Merge from debian-multimedia.org, remaining Ubuntu change:
  - desktop file,
  - no support for ccache and make -j.
* Closes Ubuntu: #69614.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
18
 *
 
19
 */
 
20
 
 
21
/**
 
22
 * @file xan.c
 
23
 * Xan video decoder for Wing Commander III computer game
 
24
 * by Mario Brito (mbrito@student.dei.uc.pt)
 
25
 * and Mike Melanson (melanson@pcisys.net)
 
26
 *
 
27
 * The xan_wc3 decoder outputs PAL8 data.
 
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
 
 
38
typedef struct XanContext {
 
39
 
 
40
    AVCodecContext *avctx;
 
41
    AVFrame last_frame;
 
42
    AVFrame current_frame;
 
43
 
 
44
    unsigned char *buf;
 
45
    int size;
 
46
 
 
47
    /* scratch space */
 
48
    unsigned char *buffer1;
 
49
    int buffer1_size;
 
50
    unsigned char *buffer2;
 
51
    int buffer2_size;
 
52
 
 
53
    int frame_size;
 
54
 
 
55
} XanContext;
 
56
 
 
57
static int xan_decode_init(AVCodecContext *avctx)
 
58
{
 
59
    XanContext *s = avctx->priv_data;
 
60
 
 
61
    s->avctx = avctx;
 
62
    s->frame_size = 0;
 
63
 
 
64
    if ((avctx->codec->id == CODEC_ID_XAN_WC3) &&
 
65
        (s->avctx->palctrl == NULL)) {
 
66
        av_log(avctx, AV_LOG_ERROR, " WC3 Xan video: palette expected.\n");
 
67
        return -1;
 
68
    }
 
69
 
 
70
    avctx->pix_fmt = PIX_FMT_PAL8;
 
71
    avctx->has_b_frames = 0;
 
72
 
 
73
    if(avcodec_check_dimensions(avctx, avctx->width, avctx->height))
 
74
        return -1;
 
75
 
 
76
    s->buffer1_size = avctx->width * avctx->height;
 
77
    s->buffer1 = av_malloc(s->buffer1_size);
 
78
    s->buffer2_size = avctx->width * avctx->height;
 
79
    s->buffer2 = av_malloc(s->buffer2_size);
 
80
    if (!s->buffer1 || !s->buffer2)
 
81
        return -1;
 
82
 
 
83
    return 0;
 
84
}
 
85
 
 
86
/* This function is used in lieu of memcpy(). This decoder can not use
 
87
 * memcpy because the memory locations often overlap and
 
88
 * memcpy doesn't like that; it's not uncommon, for example, for
 
89
 * dest = src+1, to turn byte A into  pattern AAAAAAAA.
 
90
 * This was originally repz movsb in Intel x86 ASM. */
 
91
static inline void bytecopy(unsigned char *dest, unsigned char *src, int count)
 
92
{
 
93
    int i;
 
94
 
 
95
    for (i = 0; i < count; i++)
 
96
        dest[i] = src[i];
 
97
}
 
98
 
 
99
static int xan_huffman_decode(unsigned char *dest, unsigned char *src,
 
100
    int dest_len)
 
101
{
 
102
    unsigned char byte = *src++;
 
103
    unsigned char ival = byte + 0x16;
 
104
    unsigned char * ptr = src + byte*2;
 
105
    unsigned char val = ival;
 
106
    int counter = 0;
 
107
    unsigned char *dest_end = dest + dest_len;
 
108
 
 
109
    unsigned char bits = *ptr++;
 
110
 
 
111
    while ( val != 0x16 ) {
 
112
        if ( (1 << counter) & bits )
 
113
            val = src[byte + val - 0x17];
 
114
        else
 
115
            val = src[val - 0x17];
 
116
 
 
117
        if ( val < 0x16 ) {
 
118
            if (dest + 1 > dest_end)
 
119
                return 0;
 
120
            *dest++ = val;
 
121
            val = ival;
 
122
        }
 
123
 
 
124
        if (counter++ == 7) {
 
125
            counter = 0;
 
126
            bits = *ptr++;
 
127
        }
 
128
    }
 
129
 
 
130
    return 0;
 
131
}
 
132
 
 
133
static void xan_unpack(unsigned char *dest, unsigned char *src, int dest_len)
 
134
{
 
135
    unsigned char opcode;
 
136
    int size;
 
137
    int offset;
 
138
    int byte1, byte2, byte3;
 
139
    unsigned char *dest_end = dest + dest_len;
 
140
 
 
141
    for (;;) {
 
142
        opcode = *src++;
 
143
 
 
144
        if ( (opcode & 0x80) == 0 ) {
 
145
 
 
146
            offset = *src++;
 
147
 
 
148
            size = opcode & 3;
 
149
            if (dest + size > dest_end)
 
150
                return;
 
151
            bytecopy(dest, src, size);  dest += size;  src += size;
 
152
 
 
153
            size = ((opcode & 0x1c) >> 2) + 3;
 
154
            if (dest + size > dest_end)
 
155
                return;
 
156
            bytecopy (dest, dest - (((opcode & 0x60) << 3) + offset + 1), size);
 
157
            dest += size;
 
158
 
 
159
        } else if ( (opcode & 0x40) == 0 ) {
 
160
 
 
161
            byte1 = *src++;
 
162
            byte2 = *src++;
 
163
 
 
164
            size = byte1 >> 6;
 
165
            if (dest + size > dest_end)
 
166
                return;
 
167
            bytecopy (dest, src, size);  dest += size;  src += size;
 
168
 
 
169
            size = (opcode & 0x3f) + 4;
 
170
            if (dest + size > dest_end)
 
171
                return;
 
172
            bytecopy (dest, dest - (((byte1 & 0x3f) << 8) + byte2 + 1), size);
 
173
            dest += size;
 
174
 
 
175
        } else if ( (opcode & 0x20) == 0 ) {
 
176
 
 
177
            byte1 = *src++;
 
178
            byte2 = *src++;
 
179
            byte3 = *src++;
 
180
 
 
181
            size = opcode & 3;
 
182
            if (dest + size > dest_end)
 
183
                return;
 
184
            bytecopy (dest, src, size);  dest += size;  src += size;
 
185
 
 
186
            size = byte3 + 5 + ((opcode & 0xc) << 6);
 
187
            if (dest + size > dest_end)
 
188
                return;
 
189
            bytecopy (dest,
 
190
                dest - ((((opcode & 0x10) >> 4) << 0x10) + 1 + (byte1 << 8) + byte2),
 
191
                size);
 
192
            dest += size;
 
193
        } else {
 
194
            size = ((opcode & 0x1f) << 2) + 4;
 
195
 
 
196
            if (size > 0x70)
 
197
                break;
 
198
 
 
199
            if (dest + size > dest_end)
 
200
                return;
 
201
            bytecopy (dest, src, size);  dest += size;  src += size;
 
202
        }
 
203
    }
 
204
 
 
205
    size = opcode & 3;
 
206
    bytecopy(dest, src, size);  dest += size;  src += size;
 
207
}
 
208
 
 
209
static void inline xan_wc3_output_pixel_run(XanContext *s,
 
210
    unsigned char *pixel_buffer, int x, int y, int pixel_count)
 
211
{
 
212
    int stride;
 
213
    int line_inc;
 
214
    int index;
 
215
    int current_x;
 
216
    int width = s->avctx->width;
 
217
    unsigned char *palette_plane;
 
218
 
 
219
    palette_plane = s->current_frame.data[0];
 
220
    stride = s->current_frame.linesize[0];
 
221
    line_inc = stride - width;
 
222
    index = y * stride + x;
 
223
    current_x = x;
 
224
    while((pixel_count--) && (index < s->frame_size)) {
 
225
 
 
226
        /* don't do a memcpy() here; keyframes generally copy an entire
 
227
         * frame of data and the stride needs to be accounted for */
 
228
        palette_plane[index++] = *pixel_buffer++;
 
229
 
 
230
        current_x++;
 
231
        if (current_x >= width) {
 
232
            index += line_inc;
 
233
            current_x = 0;
 
234
        }
 
235
    }
 
236
}
 
237
 
 
238
static void inline xan_wc3_copy_pixel_run(XanContext *s,
 
239
    int x, int y, int pixel_count, int motion_x, int motion_y)
 
240
{
 
241
    int stride;
 
242
    int line_inc;
 
243
    int curframe_index, prevframe_index;
 
244
    int curframe_x, prevframe_x;
 
245
    int width = s->avctx->width;
 
246
    unsigned char *palette_plane, *prev_palette_plane;
 
247
 
 
248
    palette_plane = s->current_frame.data[0];
 
249
    prev_palette_plane = s->last_frame.data[0];
 
250
    stride = s->current_frame.linesize[0];
 
251
    line_inc = stride - width;
 
252
    curframe_index = y * stride + x;
 
253
    curframe_x = x;
 
254
    prevframe_index = (y + motion_y) * stride + x + motion_x;
 
255
    prevframe_x = x + motion_x;
 
256
    while((pixel_count--) && (curframe_index < s->frame_size)) {
 
257
 
 
258
        palette_plane[curframe_index++] =
 
259
            prev_palette_plane[prevframe_index++];
 
260
 
 
261
        curframe_x++;
 
262
        if (curframe_x >= width) {
 
263
            curframe_index += line_inc;
 
264
            curframe_x = 0;
 
265
        }
 
266
 
 
267
        prevframe_x++;
 
268
        if (prevframe_x >= width) {
 
269
            prevframe_index += line_inc;
 
270
            prevframe_x = 0;
 
271
        }
 
272
    }
 
273
}
 
274
 
 
275
static void xan_wc3_decode_frame(XanContext *s) {
 
276
 
 
277
    int width = s->avctx->width;
 
278
    int height = s->avctx->height;
 
279
    int total_pixels = width * height;
 
280
    unsigned char opcode;
 
281
    unsigned char flag = 0;
 
282
    int size = 0;
 
283
    int motion_x, motion_y;
 
284
    int x, y;
 
285
 
 
286
    unsigned char *opcode_buffer = s->buffer1;
 
287
    int opcode_buffer_size = s->buffer1_size;
 
288
    unsigned char *imagedata_buffer = s->buffer2;
 
289
    int imagedata_buffer_size = s->buffer2_size;
 
290
 
 
291
    /* pointers to segments inside the compressed chunk */
 
292
    unsigned char *huffman_segment;
 
293
    unsigned char *size_segment;
 
294
    unsigned char *vector_segment;
 
295
    unsigned char *imagedata_segment;
 
296
 
 
297
    huffman_segment =   s->buf + LE_16(&s->buf[0]);
 
298
    size_segment =      s->buf + LE_16(&s->buf[2]);
 
299
    vector_segment =    s->buf + LE_16(&s->buf[4]);
 
300
    imagedata_segment = s->buf + LE_16(&s->buf[6]);
 
301
 
 
302
    xan_huffman_decode(opcode_buffer, huffman_segment, opcode_buffer_size);
 
303
 
 
304
    if (imagedata_segment[0] == 2)
 
305
        xan_unpack(imagedata_buffer, &imagedata_segment[1],
 
306
            imagedata_buffer_size);
 
307
    else
 
308
        imagedata_buffer = &imagedata_segment[1];
 
309
 
 
310
    /* use the decoded data segments to build the frame */
 
311
    x = y = 0;
 
312
    while (total_pixels) {
 
313
 
 
314
        opcode = *opcode_buffer++;
 
315
        size = 0;
 
316
 
 
317
        switch (opcode) {
 
318
 
 
319
        case 0:
 
320
            flag ^= 1;
 
321
            continue;
 
322
 
 
323
        case 1:
 
324
        case 2:
 
325
        case 3:
 
326
        case 4:
 
327
        case 5:
 
328
        case 6:
 
329
        case 7:
 
330
        case 8:
 
331
            size = opcode;
 
332
            break;
 
333
 
 
334
        case 12:
 
335
        case 13:
 
336
        case 14:
 
337
        case 15:
 
338
        case 16:
 
339
        case 17:
 
340
        case 18:
 
341
            size += (opcode - 10);
 
342
            break;
 
343
 
 
344
        case 9:
 
345
        case 19:
 
346
            size = *size_segment++;
 
347
            break;
 
348
 
 
349
        case 10:
 
350
        case 20:
 
351
            size = BE_16(&size_segment[0]);
 
352
            size_segment += 2;
 
353
            break;
 
354
 
 
355
        case 11:
 
356
        case 21:
 
357
            size = (size_segment[0] << 16) | (size_segment[1] << 8) |
 
358
                size_segment[2];
 
359
            size_segment += 3;
 
360
            break;
 
361
        }
 
362
 
 
363
        if (opcode < 12) {
 
364
            flag ^= 1;
 
365
            if (flag) {
 
366
                /* run of (size) pixels is unchanged from last frame */
 
367
                xan_wc3_copy_pixel_run(s, x, y, size, 0, 0);
 
368
            } else {
 
369
                /* output a run of pixels from imagedata_buffer */
 
370
                xan_wc3_output_pixel_run(s, imagedata_buffer, x, y, size);
 
371
                imagedata_buffer += size;
 
372
            }
 
373
        } else {
 
374
            /* run-based motion compensation from last frame */
 
375
            motion_x = (*vector_segment >> 4) & 0xF;
 
376
            motion_y = *vector_segment & 0xF;
 
377
            vector_segment++;
 
378
 
 
379
            /* sign extension */
 
380
            if (motion_x & 0x8)
 
381
                motion_x |= 0xFFFFFFF0;
 
382
            if (motion_y & 0x8)
 
383
                motion_y |= 0xFFFFFFF0;
 
384
 
 
385
            /* copy a run of pixels from the previous frame */
 
386
            xan_wc3_copy_pixel_run(s, x, y, size, motion_x, motion_y);
 
387
 
 
388
            flag = 0;
 
389
        }
 
390
 
 
391
        /* coordinate accounting */
 
392
        total_pixels -= size;
 
393
        while (size) {
 
394
            if (x + size >= width) {
 
395
                y++;
 
396
                size -= (width - x);
 
397
                x = 0;
 
398
            } else {
 
399
                x += size;
 
400
                size = 0;
 
401
            }
 
402
        }
 
403
    }
 
404
}
 
405
 
 
406
static void xan_wc4_decode_frame(XanContext *s) {
 
407
}
 
408
 
 
409
static int xan_decode_frame(AVCodecContext *avctx,
 
410
                            void *data, int *data_size,
 
411
                            uint8_t *buf, int buf_size)
 
412
{
 
413
    XanContext *s = avctx->priv_data;
 
414
    AVPaletteControl *palette_control = avctx->palctrl;
 
415
 
 
416
    if (avctx->get_buffer(avctx, &s->current_frame)) {
 
417
        av_log(s->avctx, AV_LOG_ERROR, "  Xan Video: get_buffer() failed\n");
 
418
        return -1;
 
419
    }
 
420
    s->current_frame.reference = 3;
 
421
 
 
422
    if (!s->frame_size)
 
423
        s->frame_size = s->current_frame.linesize[0] * s->avctx->height;
 
424
 
 
425
    palette_control->palette_changed = 0;
 
426
    memcpy(s->current_frame.data[1], palette_control->palette,
 
427
        AVPALETTE_SIZE);
 
428
    s->current_frame.palette_has_changed = 1;
 
429
 
 
430
    s->buf = buf;
 
431
    s->size = buf_size;
 
432
 
 
433
    if (avctx->codec->id == CODEC_ID_XAN_WC3)
 
434
        xan_wc3_decode_frame(s);
 
435
    else if (avctx->codec->id == CODEC_ID_XAN_WC4)
 
436
        xan_wc4_decode_frame(s);
 
437
 
 
438
    /* release the last frame if it is allocated */
 
439
    if (s->last_frame.data[0])
 
440
        avctx->release_buffer(avctx, &s->last_frame);
 
441
 
 
442
    /* shuffle frames */
 
443
    s->last_frame = s->current_frame;
 
444
 
 
445
    *data_size = sizeof(AVFrame);
 
446
    *(AVFrame*)data = s->current_frame;
 
447
 
 
448
    /* always report that the buffer was completely consumed */
 
449
    return buf_size;
 
450
}
 
451
 
 
452
static int xan_decode_end(AVCodecContext *avctx)
 
453
{
 
454
    XanContext *s = avctx->priv_data;
 
455
 
 
456
    /* release the last frame */
 
457
    if (s->last_frame.data[0])
 
458
        avctx->release_buffer(avctx, &s->last_frame);
 
459
 
 
460
    av_free(s->buffer1);
 
461
    av_free(s->buffer2);
 
462
 
 
463
    return 0;
 
464
}
 
465
 
 
466
AVCodec xan_wc3_decoder = {
 
467
    "xan_wc3",
 
468
    CODEC_TYPE_VIDEO,
 
469
    CODEC_ID_XAN_WC3,
 
470
    sizeof(XanContext),
 
471
    xan_decode_init,
 
472
    NULL,
 
473
    xan_decode_end,
 
474
    xan_decode_frame,
 
475
    CODEC_CAP_DR1,
 
476
};
 
477
 
 
478
/*
 
479
AVCodec xan_wc4_decoder = {
 
480
    "xan_wc4",
 
481
    CODEC_TYPE_VIDEO,
 
482
    CODEC_ID_XAN_WC4,
 
483
    sizeof(XanContext),
 
484
    xan_decode_init,
 
485
    NULL,
 
486
    xan_decode_end,
 
487
    xan_decode_frame,
 
488
    CODEC_CAP_DR1,
 
489
};
 
490
*/