Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 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 
32
#include 
33
#include 
34
 
35
#include "libavutil/intreadwrite.h"
36
#include "libavutil/mem.h"
37
#include "avcodec.h"
38
#include "bytestream.h"
39
#define BITSTREAM_READER_LE
40
#include "get_bits.h"
41
#include "internal.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
 
57
    const uint8_t *buf;
58
    int size;
59
 
60
    /* scratch space */
61
    uint8_t *buffer1;
62
    int buffer1_size;
63
    uint8_t *buffer2;
64
    int buffer2_size;
65
 
66
    unsigned *palettes;
67
    int palettes_count;
68
    int cur_palette;
69
 
70
    int frame_size;
71
 
72
} XanContext;
73
 
74
static av_cold int xan_decode_end(AVCodecContext *avctx);
75
 
76
static av_cold int xan_decode_init(AVCodecContext *avctx)
77
{
78
    XanContext *s = avctx->priv_data;
79
 
80
    s->avctx = avctx;
81
    s->frame_size = 0;
82
 
83
    avctx->pix_fmt = AV_PIX_FMT_PAL8;
84
 
85
    s->buffer1_size = avctx->width * avctx->height;
86
    s->buffer1 = av_malloc(s->buffer1_size);
87
    if (!s->buffer1)
88
        return AVERROR(ENOMEM);
89
    s->buffer2_size = avctx->width * avctx->height;
90
    s->buffer2 = av_malloc(s->buffer2_size + 130);
91
    if (!s->buffer2) {
92
        av_freep(&s->buffer1);
93
        return AVERROR(ENOMEM);
94
    }
95
    s->last_frame = av_frame_alloc();
96
    if (!s->last_frame) {
97
        xan_decode_end(avctx);
98
        return AVERROR(ENOMEM);
99
    }
100
 
101
    return 0;
102
}
103
 
104
static int xan_huffman_decode(uint8_t *dest, int dest_len,
105
                              const uint8_t *src, int src_len)
106
{
107
    uint8_t byte = *src++;
108
    uint8_t ival = byte + 0x16;
109
    const uint8_t * ptr = src + byte*2;
110
    int ptr_len = src_len - 1 - byte*2;
111
    uint8_t val = ival;
112
    uint8_t *dest_end = dest + dest_len;
113
    uint8_t *dest_start = dest;
114
    GetBitContext gb;
115
 
116
    if (ptr_len < 0)
117
        return AVERROR_INVALIDDATA;
118
 
119
    init_get_bits(&gb, ptr, ptr_len * 8);
120
 
121
    while (val != 0x16) {
122
        unsigned idx = val - 0x17 + get_bits1(&gb) * byte;
123
        if (idx >= 2 * byte)
124
            return AVERROR_INVALIDDATA;
125
        val = src[idx];
126
 
127
        if (val < 0x16) {
128
            if (dest >= dest_end)
129
                return dest_len;
130
            *dest++ = val;
131
            val = ival;
132
        }
133
    }
134
 
135
    return dest - dest_start;
136
}
137
 
138
/**
139
 * unpack simple compression
140
 *
141
 * @param dest destination buffer of dest_len, must be padded with at least 130 bytes
142
 */
143
static void xan_unpack(uint8_t *dest, int dest_len,
144
                       const uint8_t *src, int src_len)
145
{
146
    uint8_t opcode;
147
    int size;
148
    uint8_t *dest_org = dest;
149
    uint8_t *dest_end = dest + dest_len;
150
    GetByteContext ctx;
151
 
152
    bytestream2_init(&ctx, src, src_len);
153
    while (dest < dest_end && bytestream2_get_bytes_left(&ctx)) {
154
        opcode = bytestream2_get_byte(&ctx);
155
 
156
        if (opcode < 0xe0) {
157
            int size2, back;
158
            if ((opcode & 0x80) == 0) {
159
                size = opcode & 3;
160
 
161
                back  = ((opcode & 0x60) << 3) + bytestream2_get_byte(&ctx) + 1;
162
                size2 = ((opcode & 0x1c) >> 2) + 3;
163
            } else if ((opcode & 0x40) == 0) {
164
                size = bytestream2_peek_byte(&ctx) >> 6;
165
 
166
                back  = (bytestream2_get_be16(&ctx) & 0x3fff) + 1;
167
                size2 = (opcode & 0x3f) + 4;
168
            } else {
169
                size = opcode & 3;
170
 
171
                back  = ((opcode & 0x10) << 12) + bytestream2_get_be16(&ctx) + 1;
172
                size2 = ((opcode & 0x0c) <<  6) + bytestream2_get_byte(&ctx) + 5;
173
            }
174
 
175
            if (dest_end - dest < size + size2 ||
176
                dest + size - dest_org < back ||
177
                bytestream2_get_bytes_left(&ctx) < size)
178
                return;
179
            bytestream2_get_buffer(&ctx, dest, size);
180
            dest += size;
181
            av_memcpy_backptr(dest, back, size2);
182
            dest += size2;
183
        } else {
184
            int finish = opcode >= 0xfc;
185
            size = finish ? opcode & 3 : ((opcode & 0x1f) << 2) + 4;
186
 
187
            if (dest_end - dest < size || bytestream2_get_bytes_left(&ctx) < size)
188
                return;
189
            bytestream2_get_buffer(&ctx, dest, size);
190
            dest += size;
191
            if (finish)
192
                return;
193
        }
194
    }
195
}
196
 
197
static inline void xan_wc3_output_pixel_run(XanContext *s, AVFrame *frame,
198
    const uint8_t *pixel_buffer, int x, int y, int pixel_count)
199
{
200
    int stride;
201
    int line_inc;
202
    int index;
203
    int current_x;
204
    int width = s->avctx->width;
205
    uint8_t *palette_plane;
206
 
207
    palette_plane = frame->data[0];
208
    stride = frame->linesize[0];
209
    line_inc = stride - width;
210
    index = y * stride + x;
211
    current_x = x;
212
    while (pixel_count && index < s->frame_size) {
213
        int count = FFMIN(pixel_count, width - current_x);
214
        memcpy(palette_plane + index, pixel_buffer, count);
215
        pixel_count  -= count;
216
        index        += count;
217
        pixel_buffer += count;
218
        current_x    += count;
219
 
220
        if (current_x >= width) {
221
            index += line_inc;
222
            current_x = 0;
223
        }
224
    }
225
}
226
 
227
static inline void xan_wc3_copy_pixel_run(XanContext *s, AVFrame *frame,
228
                                          int x, int y,
229
                                          int pixel_count, int motion_x,
230
                                          int motion_y)
231
{
232
    int stride;
233
    int line_inc;
234
    int curframe_index, prevframe_index;
235
    int curframe_x, prevframe_x;
236
    int width = s->avctx->width;
237
    uint8_t *palette_plane, *prev_palette_plane;
238
 
239
    if (y + motion_y < 0 || y + motion_y >= s->avctx->height ||
240
        x + motion_x < 0 || x + motion_x >= s->avctx->width)
241
        return;
242
 
243
    palette_plane = frame->data[0];
244
    prev_palette_plane = s->last_frame->data[0];
245
    if (!prev_palette_plane)
246
        prev_palette_plane = palette_plane;
247
    stride = frame->linesize[0];
248
    line_inc = stride - width;
249
    curframe_index = y * stride + x;
250
    curframe_x = x;
251
    prevframe_index = (y + motion_y) * stride + x + motion_x;
252
    prevframe_x = x + motion_x;
253
 
254
    if (prev_palette_plane == palette_plane && FFABS(curframe_index - prevframe_index) < pixel_count) {
255
         avpriv_request_sample(s->avctx, "Overlapping copy\n");
256
         return ;
257
    }
258
 
259
    while (pixel_count &&
260
           curframe_index  < s->frame_size &&
261
           prevframe_index < s->frame_size) {
262
        int count = FFMIN3(pixel_count, width - curframe_x,
263
                           width - prevframe_x);
264
 
265
        memcpy(palette_plane + curframe_index,
266
               prev_palette_plane + prevframe_index, count);
267
        pixel_count     -= count;
268
        curframe_index  += count;
269
        prevframe_index += count;
270
        curframe_x      += count;
271
        prevframe_x     += count;
272
 
273
        if (curframe_x >= width) {
274
            curframe_index += line_inc;
275
            curframe_x = 0;
276
        }
277
 
278
        if (prevframe_x >= width) {
279
            prevframe_index += line_inc;
280
            prevframe_x = 0;
281
        }
282
    }
283
}
284
 
285
static int xan_wc3_decode_frame(XanContext *s, AVFrame *frame)
286
{
287
 
288
    int width  = s->avctx->width;
289
    int height = s->avctx->height;
290
    int total_pixels = width * height;
291
    uint8_t opcode;
292
    uint8_t flag = 0;
293
    int size = 0;
294
    int motion_x, motion_y;
295
    int x, y, ret;
296
 
297
    uint8_t *opcode_buffer = s->buffer1;
298
    uint8_t *opcode_buffer_end = s->buffer1 + s->buffer1_size;
299
    int opcode_buffer_size = s->buffer1_size;
300
    const uint8_t *imagedata_buffer = s->buffer2;
301
 
302
    /* pointers to segments inside the compressed chunk */
303
    const uint8_t *huffman_segment;
304
    GetByteContext       size_segment;
305
    GetByteContext       vector_segment;
306
    const uint8_t *imagedata_segment;
307
    int huffman_offset, size_offset, vector_offset, imagedata_offset,
308
        imagedata_size;
309
 
310
    if (s->size < 8)
311
        return AVERROR_INVALIDDATA;
312
 
313
    huffman_offset    = AV_RL16(&s->buf[0]);
314
    size_offset       = AV_RL16(&s->buf[2]);
315
    vector_offset     = AV_RL16(&s->buf[4]);
316
    imagedata_offset  = AV_RL16(&s->buf[6]);
317
 
318
    if (huffman_offset   >= s->size ||
319
        size_offset      >= s->size ||
320
        vector_offset    >= s->size ||
321
        imagedata_offset >= s->size)
322
        return AVERROR_INVALIDDATA;
323
 
324
    huffman_segment   = s->buf + huffman_offset;
325
    bytestream2_init(&size_segment,   s->buf + size_offset,   s->size - size_offset);
326
    bytestream2_init(&vector_segment, s->buf + vector_offset, s->size - vector_offset);
327
    imagedata_segment = s->buf + imagedata_offset;
328
 
329
    if ((ret = xan_huffman_decode(opcode_buffer, opcode_buffer_size,
330
                                  huffman_segment, s->size - huffman_offset)) < 0)
331
        return AVERROR_INVALIDDATA;
332
    opcode_buffer_end = opcode_buffer + ret;
333
 
334
    if (imagedata_segment[0] == 2) {
335
        xan_unpack(s->buffer2, s->buffer2_size,
336
                   &imagedata_segment[1], s->size - imagedata_offset - 1);
337
        imagedata_size = s->buffer2_size;
338
    } else {
339
        imagedata_size = s->size - imagedata_offset - 1;
340
        imagedata_buffer = &imagedata_segment[1];
341
    }
342
 
343
    /* use the decoded data segments to build the frame */
344
    x = y = 0;
345
    while (total_pixels && opcode_buffer < opcode_buffer_end) {
346
 
347
        opcode = *opcode_buffer++;
348
        size = 0;
349
 
350
        switch (opcode) {
351
 
352
        case 0:
353
            flag ^= 1;
354
            continue;
355
 
356
        case 1:
357
        case 2:
358
        case 3:
359
        case 4:
360
        case 5:
361
        case 6:
362
        case 7:
363
        case 8:
364
            size = opcode;
365
            break;
366
 
367
        case 12:
368
        case 13:
369
        case 14:
370
        case 15:
371
        case 16:
372
        case 17:
373
        case 18:
374
            size += (opcode - 10);
375
            break;
376
 
377
        case 9:
378
        case 19:
379
            if (bytestream2_get_bytes_left(&size_segment) < 1) {
380
                av_log(s->avctx, AV_LOG_ERROR, "size_segment overread\n");
381
                return AVERROR_INVALIDDATA;
382
            }
383
            size = bytestream2_get_byte(&size_segment);
384
            break;
385
 
386
        case 10:
387
        case 20:
388
            if (bytestream2_get_bytes_left(&size_segment) < 2) {
389
                av_log(s->avctx, AV_LOG_ERROR, "size_segment overread\n");
390
                return AVERROR_INVALIDDATA;
391
            }
392
            size = bytestream2_get_be16(&size_segment);
393
            break;
394
 
395
        case 11:
396
        case 21:
397
            if (bytestream2_get_bytes_left(&size_segment) < 3) {
398
                av_log(s->avctx, AV_LOG_ERROR, "size_segment overread\n");
399
                return AVERROR_INVALIDDATA;
400
            }
401
            size = bytestream2_get_be24(&size_segment);
402
            break;
403
        }
404
 
405
        if (size > total_pixels)
406
            break;
407
 
408
        if (opcode < 12) {
409
            flag ^= 1;
410
            if (flag) {
411
                /* run of (size) pixels is unchanged from last frame */
412
                xan_wc3_copy_pixel_run(s, frame, x, y, size, 0, 0);
413
            } else {
414
                /* output a run of pixels from imagedata_buffer */
415
                if (imagedata_size < size)
416
                    break;
417
                xan_wc3_output_pixel_run(s, frame, imagedata_buffer, x, y, size);
418
                imagedata_buffer += size;
419
                imagedata_size -= size;
420
            }
421
        } else {
422
            uint8_t vector;
423
            if (bytestream2_get_bytes_left(&vector_segment) <= 0) {
424
                av_log(s->avctx, AV_LOG_ERROR, "vector_segment overread\n");
425
                return AVERROR_INVALIDDATA;
426
            }
427
            /* run-based motion compensation from last frame */
428
            vector = bytestream2_get_byte(&vector_segment);
429
            motion_x = sign_extend(vector >> 4,  4);
430
            motion_y = sign_extend(vector & 0xF, 4);
431
 
432
            /* copy a run of pixels from the previous frame */
433
            xan_wc3_copy_pixel_run(s, frame, x, y, size, motion_x, motion_y);
434
 
435
            flag = 0;
436
        }
437
 
438
        /* coordinate accounting */
439
        total_pixels -= size;
440
        y += (x + size) / width;
441
        x  = (x + size) % width;
442
    }
443
    return 0;
444
}
445
 
446
#if RUNTIME_GAMMA
447
static inline unsigned mul(unsigned a, unsigned b)
448
{
449
    return (a * b) >> 16;
450
}
451
 
452
static inline unsigned pow4(unsigned a)
453
{
454
    unsigned square = mul(a, a);
455
    return mul(square, square);
456
}
457
 
458
static inline unsigned pow5(unsigned a)
459
{
460
    return mul(pow4(a), a);
461
}
462
 
463
static uint8_t gamma_corr(uint8_t in) {
464
    unsigned lo, hi = 0xff40, target;
465
    int i = 15;
466
    in = (in << 2) | (in >> 6);
467
    /*  equivalent float code:
468
    if (in >= 252)
469
        return 253;
470
    return round(pow(in / 256.0, 0.8) * 256);
471
    */
472
    lo = target = in << 8;
473
    do {
474
        unsigned mid = (lo + hi) >> 1;
475
        unsigned pow = pow5(mid);
476
        if (pow > target) hi = mid;
477
        else lo = mid;
478
    } while (--i);
479
    return (pow4((lo + hi) >> 1) + 0x80) >> 8;
480
}
481
#else
482
/**
483
 * This is a gamma correction that xan3 applies to all palette entries.
484
 *
485
 * There is a peculiarity, namely that the values are clamped to 253 -
486
 * it seems likely that this table was calculated by a buggy fixed-point
487
 * implementation, the one above under RUNTIME_GAMMA behaves like this for
488
 * example.
489
 * The exponent value of 0.8 can be explained by this as well, since 0.8 = 4/5
490
 * and thus pow(x, 0.8) is still easy to calculate.
491
 * Also, the input values are first rotated to the left by 2.
492
 */
493
static const uint8_t gamma_lookup[256] = {
494
    0x00, 0x09, 0x10, 0x16, 0x1C, 0x21, 0x27, 0x2C,
495
    0x31, 0x35, 0x3A, 0x3F, 0x43, 0x48, 0x4C, 0x50,
496
    0x54, 0x59, 0x5D, 0x61, 0x65, 0x69, 0x6D, 0x71,
497
    0x75, 0x79, 0x7D, 0x80, 0x84, 0x88, 0x8C, 0x8F,
498
    0x93, 0x97, 0x9A, 0x9E, 0xA2, 0xA5, 0xA9, 0xAC,
499
    0xB0, 0xB3, 0xB7, 0xBA, 0xBE, 0xC1, 0xC5, 0xC8,
500
    0xCB, 0xCF, 0xD2, 0xD5, 0xD9, 0xDC, 0xDF, 0xE3,
501
    0xE6, 0xE9, 0xED, 0xF0, 0xF3, 0xF6, 0xFA, 0xFD,
502
    0x03, 0x0B, 0x12, 0x18, 0x1D, 0x23, 0x28, 0x2D,
503
    0x32, 0x36, 0x3B, 0x40, 0x44, 0x49, 0x4D, 0x51,
504
    0x56, 0x5A, 0x5E, 0x62, 0x66, 0x6A, 0x6E, 0x72,
505
    0x76, 0x7A, 0x7D, 0x81, 0x85, 0x89, 0x8D, 0x90,
506
    0x94, 0x98, 0x9B, 0x9F, 0xA2, 0xA6, 0xAA, 0xAD,
507
    0xB1, 0xB4, 0xB8, 0xBB, 0xBF, 0xC2, 0xC5, 0xC9,
508
    0xCC, 0xD0, 0xD3, 0xD6, 0xDA, 0xDD, 0xE0, 0xE4,
509
    0xE7, 0xEA, 0xED, 0xF1, 0xF4, 0xF7, 0xFA, 0xFD,
510
    0x05, 0x0D, 0x13, 0x19, 0x1F, 0x24, 0x29, 0x2E,
511
    0x33, 0x38, 0x3C, 0x41, 0x45, 0x4A, 0x4E, 0x52,
512
    0x57, 0x5B, 0x5F, 0x63, 0x67, 0x6B, 0x6F, 0x73,
513
    0x77, 0x7B, 0x7E, 0x82, 0x86, 0x8A, 0x8D, 0x91,
514
    0x95, 0x99, 0x9C, 0xA0, 0xA3, 0xA7, 0xAA, 0xAE,
515
    0xB2, 0xB5, 0xB9, 0xBC, 0xBF, 0xC3, 0xC6, 0xCA,
516
    0xCD, 0xD0, 0xD4, 0xD7, 0xDA, 0xDE, 0xE1, 0xE4,
517
    0xE8, 0xEB, 0xEE, 0xF1, 0xF5, 0xF8, 0xFB, 0xFD,
518
    0x07, 0x0E, 0x15, 0x1A, 0x20, 0x25, 0x2A, 0x2F,
519
    0x34, 0x39, 0x3D, 0x42, 0x46, 0x4B, 0x4F, 0x53,
520
    0x58, 0x5C, 0x60, 0x64, 0x68, 0x6C, 0x70, 0x74,
521
    0x78, 0x7C, 0x7F, 0x83, 0x87, 0x8B, 0x8E, 0x92,
522
    0x96, 0x99, 0x9D, 0xA1, 0xA4, 0xA8, 0xAB, 0xAF,
523
    0xB2, 0xB6, 0xB9, 0xBD, 0xC0, 0xC4, 0xC7, 0xCB,
524
    0xCE, 0xD1, 0xD5, 0xD8, 0xDB, 0xDF, 0xE2, 0xE5,
525
    0xE9, 0xEC, 0xEF, 0xF2, 0xF6, 0xF9, 0xFC, 0xFD
526
};
527
#endif
528
 
529
static int xan_decode_frame(AVCodecContext *avctx,
530
                            void *data, int *got_frame,
531
                            AVPacket *avpkt)
532
{
533
    AVFrame *frame = data;
534
    const uint8_t *buf = avpkt->data;
535
    int ret, buf_size = avpkt->size;
536
    XanContext *s = avctx->priv_data;
537
    GetByteContext ctx;
538
    int tag = 0;
539
 
540
    bytestream2_init(&ctx, buf, buf_size);
541
    while (bytestream2_get_bytes_left(&ctx) > 8 && tag != VGA__TAG) {
542
        unsigned *tmpptr;
543
        uint32_t new_pal;
544
        int size;
545
        int i;
546
        tag  = bytestream2_get_le32(&ctx);
547
        size = bytestream2_get_be32(&ctx);
548
        if(size < 0) {
549
            av_log(avctx, AV_LOG_ERROR, "Invalid tag size %d\n", size);
550
            return AVERROR_INVALIDDATA;
551
        }
552
        size = FFMIN(size, bytestream2_get_bytes_left(&ctx));
553
        switch (tag) {
554
        case PALT_TAG:
555
            if (size < PALETTE_SIZE)
556
                return AVERROR_INVALIDDATA;
557
            if (s->palettes_count >= PALETTES_MAX)
558
                return AVERROR_INVALIDDATA;
559
            tmpptr = av_realloc(s->palettes,
560
                                (s->palettes_count + 1) * AVPALETTE_SIZE);
561
            if (!tmpptr)
562
                return AVERROR(ENOMEM);
563
            s->palettes = tmpptr;
564
            tmpptr += s->palettes_count * AVPALETTE_COUNT;
565
            for (i = 0; i < PALETTE_COUNT; i++) {
566
#if RUNTIME_GAMMA
567
                int r = gamma_corr(bytestream2_get_byteu(&ctx));
568
                int g = gamma_corr(bytestream2_get_byteu(&ctx));
569
                int b = gamma_corr(bytestream2_get_byteu(&ctx));
570
#else
571
                int r = gamma_lookup[bytestream2_get_byteu(&ctx)];
572
                int g = gamma_lookup[bytestream2_get_byteu(&ctx)];
573
                int b = gamma_lookup[bytestream2_get_byteu(&ctx)];
574
#endif
575
                *tmpptr++ = (0xFFU << 24) | (r << 16) | (g << 8) | b;
576
            }
577
            s->palettes_count++;
578
            break;
579
        case SHOT_TAG:
580
            if (size < 4)
581
                return AVERROR_INVALIDDATA;
582
            new_pal = bytestream2_get_le32(&ctx);
583
            if (new_pal < s->palettes_count) {
584
                s->cur_palette = new_pal;
585
            } else
586
                av_log(avctx, AV_LOG_ERROR, "Invalid palette selected\n");
587
            break;
588
        case VGA__TAG:
589
            break;
590
        default:
591
            bytestream2_skip(&ctx, size);
592
            break;
593
        }
594
    }
595
    buf_size = bytestream2_get_bytes_left(&ctx);
596
 
597
    if (s->palettes_count <= 0) {
598
        av_log(s->avctx, AV_LOG_ERROR, "No palette found\n");
599
        return AVERROR_INVALIDDATA;
600
    }
601
 
602
    if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
603
        return ret;
604
 
605
    if (!s->frame_size)
606
        s->frame_size = frame->linesize[0] * s->avctx->height;
607
 
608
    memcpy(frame->data[1],
609
           s->palettes + s->cur_palette * AVPALETTE_COUNT, AVPALETTE_SIZE);
610
 
611
    s->buf = ctx.buffer;
612
    s->size = buf_size;
613
 
614
    if (xan_wc3_decode_frame(s, frame) < 0)
615
        return AVERROR_INVALIDDATA;
616
 
617
    av_frame_unref(s->last_frame);
618
    if ((ret = av_frame_ref(s->last_frame, frame)) < 0)
619
        return ret;
620
 
621
    *got_frame = 1;
622
 
623
    /* always report that the buffer was completely consumed */
624
    return buf_size;
625
}
626
 
627
static av_cold int xan_decode_end(AVCodecContext *avctx)
628
{
629
    XanContext *s = avctx->priv_data;
630
 
631
    av_frame_free(&s->last_frame);
632
 
633
    av_freep(&s->buffer1);
634
    av_freep(&s->buffer2);
635
    av_freep(&s->palettes);
636
 
637
    return 0;
638
}
639
 
640
AVCodec ff_xan_wc3_decoder = {
641
    .name           = "xan_wc3",
642
    .long_name      = NULL_IF_CONFIG_SMALL("Wing Commander III / Xan"),
643
    .type           = AVMEDIA_TYPE_VIDEO,
644
    .id             = AV_CODEC_ID_XAN_WC3,
645
    .priv_data_size = sizeof(XanContext),
646
    .init           = xan_decode_init,
647
    .close          = xan_decode_end,
648
    .decode         = xan_decode_frame,
649
    .capabilities   = CODEC_CAP_DR1,
650
};