GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/xan.c Lines: 245 291 84.2 %
Date: 2020-08-14 10:39:37 Branches: 94 147 63.9 %

Line Branch Exec Source
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 "libavutil/mem.h"
37
38
#define BITSTREAM_READER_LE
39
#include "avcodec.h"
40
#include "bytestream.h"
41
#include "get_bits.h"
42
#include "internal.h"
43
44
#define RUNTIME_GAMMA 0
45
46
#define VGA__TAG MKTAG('V', 'G', 'A', ' ')
47
#define PALT_TAG MKTAG('P', 'A', 'L', 'T')
48
#define SHOT_TAG MKTAG('S', 'H', 'O', 'T')
49
#define PALETTE_COUNT 256
50
#define PALETTE_SIZE (PALETTE_COUNT * 3)
51
#define PALETTES_MAX 256
52
53
typedef struct XanContext {
54
55
    AVCodecContext *avctx;
56
    AVFrame *last_frame;
57
58
    const uint8_t *buf;
59
    int size;
60
61
    /* scratch space */
62
    uint8_t *buffer1;
63
    int buffer1_size;
64
    uint8_t *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
2
static av_cold int xan_decode_end(AVCodecContext *avctx)
76
{
77
2
    XanContext *s = avctx->priv_data;
78
79
2
    av_frame_free(&s->last_frame);
80
81
2
    av_freep(&s->buffer1);
82
2
    av_freep(&s->buffer2);
83
2
    av_freep(&s->palettes);
84
85
2
    return 0;
86
}
87
88
2
static av_cold int xan_decode_init(AVCodecContext *avctx)
89
{
90
2
    XanContext *s = avctx->priv_data;
91
92
2
    s->avctx = avctx;
93
2
    s->frame_size = 0;
94
95
2
    avctx->pix_fmt = AV_PIX_FMT_PAL8;
96
97
2
    s->buffer1_size = avctx->width * avctx->height;
98
2
    s->buffer1 = av_malloc(s->buffer1_size);
99
2
    if (!s->buffer1)
100
        return AVERROR(ENOMEM);
101
2
    s->buffer2_size = avctx->width * avctx->height;
102
2
    s->buffer2 = av_malloc(s->buffer2_size + 130);
103
2
    if (!s->buffer2) {
104
        av_freep(&s->buffer1);
105
        return AVERROR(ENOMEM);
106
    }
107
108
2
    s->last_frame = av_frame_alloc();
109
2
    if (!s->last_frame) {
110
        xan_decode_end(avctx);
111
        return AVERROR(ENOMEM);
112
    }
113
114
2
    return 0;
115
}
116
117
35
static int xan_huffman_decode(uint8_t *dest, int dest_len,
118
                              const uint8_t *src, int src_len)
119
{
120
35
    uint8_t byte = *src++;
121
35
    uint8_t ival = byte + 0x16;
122
35
    const uint8_t * ptr = src + byte*2;
123
35
    int ptr_len = src_len - 1 - byte*2;
124
35
    uint8_t val = ival;
125
35
    uint8_t *dest_end = dest + dest_len;
126
35
    uint8_t *dest_start = dest;
127
    int ret;
128
    GetBitContext gb;
129
130
35
    if ((ret = init_get_bits8(&gb, ptr, ptr_len)) < 0)
131
        return ret;
132
133
568491
    while (val != 0x16) {
134
        unsigned idx;
135
568456
        if (get_bits_left(&gb) < 1)
136
            return AVERROR_INVALIDDATA;
137
568456
        idx = val - 0x17 + get_bits1(&gb) * byte;
138
568456
        if (idx >= 2 * byte)
139
            return AVERROR_INVALIDDATA;
140
568456
        val = src[idx];
141
142
568456
        if (val < 0x16) {
143
170624
            if (dest >= dest_end)
144
                return dest_len;
145
170624
            *dest++ = val;
146
170624
            val = ival;
147
        }
148
    }
149
150
35
    return dest - dest_start;
151
}
152
153
/**
154
 * unpack simple compression
155
 *
156
 * @param dest destination buffer of dest_len, must be padded with at least 130 bytes
157
 */
158
21
static void xan_unpack(uint8_t *dest, int dest_len,
159
                       const uint8_t *src, int src_len)
160
{
161
    uint8_t opcode;
162
    int size;
163
21
    uint8_t *dest_org = dest;
164
21
    uint8_t *dest_end = dest + dest_len;
165
    GetByteContext ctx;
166
167
21
    bytestream2_init(&ctx, src, src_len);
168

29044
    while (dest < dest_end && bytestream2_get_bytes_left(&ctx)) {
169
29043
        opcode = bytestream2_get_byte(&ctx);
170
171
29043
        if (opcode < 0xe0) {
172
            int size2, back;
173
22017
            if ((opcode & 0x80) == 0) {
174
17508
                size = opcode & 3;
175
176
17508
                back  = ((opcode & 0x60) << 3) + bytestream2_get_byte(&ctx) + 1;
177
17508
                size2 = ((opcode & 0x1c) >> 2) + 3;
178
4509
            } else if ((opcode & 0x40) == 0) {
179
4241
                size = bytestream2_peek_byte(&ctx) >> 6;
180
181
4241
                back  = (bytestream2_get_be16(&ctx) & 0x3fff) + 1;
182
4241
                size2 = (opcode & 0x3f) + 4;
183
            } else {
184
268
                size = opcode & 3;
185
186
268
                back  = ((opcode & 0x10) << 12) + bytestream2_get_be16(&ctx) + 1;
187
268
                size2 = ((opcode & 0x0c) <<  6) + bytestream2_get_byte(&ctx) + 5;
188
            }
189
190
22017
            if (dest_end - dest < size + size2 ||
191

44034
                dest + size - dest_org < back ||
192
22017
                bytestream2_get_bytes_left(&ctx) < size)
193
20
                return;
194
22017
            bytestream2_get_buffer(&ctx, dest, size);
195
22017
            dest += size;
196
22017
            av_memcpy_backptr(dest, back, size2);
197
22017
            dest += size2;
198
        } else {
199
7026
            int finish = opcode >= 0xfc;
200
7026
            size = finish ? opcode & 3 : ((opcode & 0x1f) << 2) + 4;
201
202

7026
            if (dest_end - dest < size || bytestream2_get_bytes_left(&ctx) < size)
203
                return;
204
7026
            bytestream2_get_buffer(&ctx, dest, size);
205
7026
            dest += size;
206
7026
            if (finish)
207
20
                return;
208
        }
209
    }
210
}
211
212
50368
static inline void xan_wc3_output_pixel_run(XanContext *s, AVFrame *frame,
213
    const uint8_t *pixel_buffer, int x, int y, int pixel_count)
214
{
215
    int stride;
216
    int line_inc;
217
    int index;
218
    int current_x;
219
50368
    int width = s->avctx->width;
220
    uint8_t *palette_plane;
221
222
50368
    palette_plane = frame->data[0];
223
50368
    stride = frame->linesize[0];
224
50368
    line_inc = stride - width;
225
50368
    index = y * stride + x;
226
50368
    current_x = x;
227

100937
    while (pixel_count && index < s->frame_size) {
228
50569
        int count = FFMIN(pixel_count, width - current_x);
229
50569
        memcpy(palette_plane + index, pixel_buffer, count);
230
50569
        pixel_count  -= count;
231
50569
        index        += count;
232
50569
        pixel_buffer += count;
233
50569
        current_x    += count;
234
235
50569
        if (current_x >= width) {
236
1828
            index += line_inc;
237
1828
            current_x = 0;
238
        }
239
    }
240
50368
}
241
242
111283
static inline void xan_wc3_copy_pixel_run(XanContext *s, AVFrame *frame,
243
                                          int x, int y,
244
                                          int pixel_count, int motion_x,
245
                                          int motion_y)
246
{
247
    int stride;
248
    int line_inc;
249
    int curframe_index, prevframe_index;
250
    int curframe_x, prevframe_x;
251
111283
    int width = s->avctx->width;
252
    uint8_t *palette_plane, *prev_palette_plane;
253
254

111283
    if (y + motion_y < 0 || y + motion_y >= s->avctx->height ||
255

111283
        x + motion_x < 0 || x + motion_x >= s->avctx->width)
256
        return;
257
258
111283
    palette_plane = frame->data[0];
259
111283
    prev_palette_plane = s->last_frame->data[0];
260
111283
    if (!prev_palette_plane)
261
        prev_palette_plane = palette_plane;
262
111283
    stride = frame->linesize[0];
263
111283
    line_inc = stride - width;
264
111283
    curframe_index = y * stride + x;
265
111283
    curframe_x = x;
266
111283
    prevframe_index = (y + motion_y) * stride + x + motion_x;
267
111283
    prevframe_x = x + motion_x;
268
269

111283
    if (prev_palette_plane == palette_plane && FFABS(motion_x + width*motion_y) < pixel_count) {
270
         avpriv_request_sample(s->avctx, "Overlapping copy");
271
         return ;
272
    }
273
274
225956
    while (pixel_count &&
275
114673
           curframe_index  < s->frame_size &&
276
114673
           prevframe_index < s->frame_size) {
277
114673
        int count = FFMIN3(pixel_count, width - curframe_x,
278
                           width - prevframe_x);
279
280
114673
        memcpy(palette_plane + curframe_index,
281
114673
               prev_palette_plane + prevframe_index, count);
282
114673
        pixel_count     -= count;
283
114673
        curframe_index  += count;
284
114673
        prevframe_index += count;
285
114673
        curframe_x      += count;
286
114673
        prevframe_x     += count;
287
288
114673
        if (curframe_x >= width) {
289
3947
            curframe_index += line_inc;
290
3947
            curframe_x = 0;
291
        }
292
293
114673
        if (prevframe_x >= width) {
294
3892
            prevframe_index += line_inc;
295
3892
            prevframe_x = 0;
296
        }
297
    }
298
}
299
300
35
static int xan_wc3_decode_frame(XanContext *s, AVFrame *frame)
301
{
302
303
35
    int width  = s->avctx->width;
304
35
    int height = s->avctx->height;
305
35
    int total_pixels = width * height;
306
    uint8_t opcode;
307
35
    uint8_t flag = 0;
308
35
    int size = 0;
309
    int motion_x, motion_y;
310
    int x, y, ret;
311
312
35
    uint8_t *opcode_buffer = s->buffer1;
313
35
    uint8_t *opcode_buffer_end = s->buffer1 + s->buffer1_size;
314
35
    int opcode_buffer_size = s->buffer1_size;
315
35
    const uint8_t *imagedata_buffer = s->buffer2;
316
317
    /* pointers to segments inside the compressed chunk */
318
    const uint8_t *huffman_segment;
319
    GetByteContext       size_segment;
320
    GetByteContext       vector_segment;
321
    const uint8_t *imagedata_segment;
322
    int huffman_offset, size_offset, vector_offset, imagedata_offset,
323
        imagedata_size;
324
325
35
    if (s->size < 8)
326
        return AVERROR_INVALIDDATA;
327
328
35
    huffman_offset    = AV_RL16(&s->buf[0]);
329
35
    size_offset       = AV_RL16(&s->buf[2]);
330
35
    vector_offset     = AV_RL16(&s->buf[4]);
331
35
    imagedata_offset  = AV_RL16(&s->buf[6]);
332
333
35
    if (huffman_offset   >= s->size ||
334
35
        size_offset      >= s->size ||
335
35
        vector_offset    >= s->size ||
336
35
        imagedata_offset >= s->size)
337
        return AVERROR_INVALIDDATA;
338
339
35
    huffman_segment   = s->buf + huffman_offset;
340
35
    bytestream2_init(&size_segment,   s->buf + size_offset,   s->size - size_offset);
341
35
    bytestream2_init(&vector_segment, s->buf + vector_offset, s->size - vector_offset);
342
35
    imagedata_segment = s->buf + imagedata_offset;
343
344
35
    if ((ret = xan_huffman_decode(opcode_buffer, opcode_buffer_size,
345
35
                                  huffman_segment, s->size - huffman_offset)) < 0)
346
        return AVERROR_INVALIDDATA;
347
35
    opcode_buffer_end = opcode_buffer + ret;
348
349
35
    if (imagedata_segment[0] == 2) {
350
21
        xan_unpack(s->buffer2, s->buffer2_size,
351
21
                   &imagedata_segment[1], s->size - imagedata_offset - 1);
352
21
        imagedata_size = s->buffer2_size;
353
    } else {
354
14
        imagedata_size = s->size - imagedata_offset - 1;
355
14
        imagedata_buffer = &imagedata_segment[1];
356
    }
357
358
    /* use the decoded data segments to build the frame */
359
35
    x = y = 0;
360

170655
    while (total_pixels && opcode_buffer < opcode_buffer_end) {
361
362
170620
        opcode = *opcode_buffer++;
363
170620
        size = 0;
364
365

170620
        switch (opcode) {
366
367
8969
        case 0:
368
8969
            flag ^= 1;
369
8969
            continue;
370
371
91913
        case 1:
372
        case 2:
373
        case 3:
374
        case 4:
375
        case 5:
376
        case 6:
377
        case 7:
378
        case 8:
379
91913
            size = opcode;
380
91913
            break;
381
382
48168
        case 12:
383
        case 13:
384
        case 14:
385
        case 15:
386
        case 16:
387
        case 17:
388
        case 18:
389
48168
            size += (opcode - 10);
390
48168
            break;
391
392
20805
        case 9:
393
        case 19:
394
20805
            if (bytestream2_get_bytes_left(&size_segment) < 1) {
395
                av_log(s->avctx, AV_LOG_ERROR, "size_segment overread\n");
396
                return AVERROR_INVALIDDATA;
397
            }
398
20805
            size = bytestream2_get_byte(&size_segment);
399
20805
            break;
400
401
765
        case 10:
402
        case 20:
403
765
            if (bytestream2_get_bytes_left(&size_segment) < 2) {
404
                av_log(s->avctx, AV_LOG_ERROR, "size_segment overread\n");
405
                return AVERROR_INVALIDDATA;
406
            }
407
765
            size = bytestream2_get_be16(&size_segment);
408
765
            break;
409
410
        case 11:
411
        case 21:
412
            if (bytestream2_get_bytes_left(&size_segment) < 3) {
413
                av_log(s->avctx, AV_LOG_ERROR, "size_segment overread\n");
414
                return AVERROR_INVALIDDATA;
415
            }
416
            size = bytestream2_get_be24(&size_segment);
417
            break;
418
        }
419
420
161651
        if (size > total_pixels)
421
            break;
422
423
161651
        if (opcode < 12) {
424
112748
            flag ^= 1;
425
112748
            if (flag) {
426
                /* run of (size) pixels is unchanged from last frame */
427
62380
                xan_wc3_copy_pixel_run(s, frame, x, y, size, 0, 0);
428
            } else {
429
                /* output a run of pixels from imagedata_buffer */
430
50368
                if (imagedata_size < size)
431
                    break;
432
50368
                xan_wc3_output_pixel_run(s, frame, imagedata_buffer, x, y, size);
433
50368
                imagedata_buffer += size;
434
50368
                imagedata_size -= size;
435
            }
436
        } else {
437
            uint8_t vector;
438
48903
            if (bytestream2_get_bytes_left(&vector_segment) <= 0) {
439
                av_log(s->avctx, AV_LOG_ERROR, "vector_segment overread\n");
440
                return AVERROR_INVALIDDATA;
441
            }
442
            /* run-based motion compensation from last frame */
443
48903
            vector = bytestream2_get_byte(&vector_segment);
444
48903
            motion_x = sign_extend(vector >> 4,  4);
445
48903
            motion_y = sign_extend(vector & 0xF, 4);
446
447
            /* copy a run of pixels from the previous frame */
448
48903
            xan_wc3_copy_pixel_run(s, frame, x, y, size, motion_x, motion_y);
449
450
48903
            flag = 0;
451
        }
452
453
        /* coordinate accounting */
454
161651
        total_pixels -= size;
455
161651
        y += (x + size) / width;
456
161651
        x  = (x + size) % width;
457
    }
458
35
    return 0;
459
}
460
461
#if RUNTIME_GAMMA
462
static inline unsigned mul(unsigned a, unsigned b)
463
{
464
    return (a * b) >> 16;
465
}
466
467
static inline unsigned pow4(unsigned a)
468
{
469
    unsigned square = mul(a, a);
470
    return mul(square, square);
471
}
472
473
static inline unsigned pow5(unsigned a)
474
{
475
    return mul(pow4(a), a);
476
}
477
478
static uint8_t gamma_corr(uint8_t in) {
479
    unsigned lo, hi = 0xff40, target;
480
    int i = 15;
481
    in = (in << 2) | (in >> 6);
482
    /*  equivalent float code:
483
    if (in >= 252)
484
        return 253;
485
    return round(pow(in / 256.0, 0.8) * 256);
486
    */
487
    lo = target = in << 8;
488
    do {
489
        unsigned mid = (lo + hi) >> 1;
490
        unsigned pow = pow5(mid);
491
        if (pow > target) hi = mid;
492
        else lo = mid;
493
    } while (--i);
494
    return (pow4((lo + hi) >> 1) + 0x80) >> 8;
495
}
496
#else
497
/**
498
 * This is a gamma correction that xan3 applies to all palette entries.
499
 *
500
 * There is a peculiarity, namely that the values are clamped to 253 -
501
 * it seems likely that this table was calculated by a buggy fixed-point
502
 * implementation, the one above under RUNTIME_GAMMA behaves like this for
503
 * example.
504
 * The exponent value of 0.8 can be explained by this as well, since 0.8 = 4/5
505
 * and thus pow(x, 0.8) is still easy to calculate.
506
 * Also, the input values are first rotated to the left by 2.
507
 */
508
static const uint8_t gamma_lookup[256] = {
509
    0x00, 0x09, 0x10, 0x16, 0x1C, 0x21, 0x27, 0x2C,
510
    0x31, 0x35, 0x3A, 0x3F, 0x43, 0x48, 0x4C, 0x50,
511
    0x54, 0x59, 0x5D, 0x61, 0x65, 0x69, 0x6D, 0x71,
512
    0x75, 0x79, 0x7D, 0x80, 0x84, 0x88, 0x8C, 0x8F,
513
    0x93, 0x97, 0x9A, 0x9E, 0xA2, 0xA5, 0xA9, 0xAC,
514
    0xB0, 0xB3, 0xB7, 0xBA, 0xBE, 0xC1, 0xC5, 0xC8,
515
    0xCB, 0xCF, 0xD2, 0xD5, 0xD9, 0xDC, 0xDF, 0xE3,
516
    0xE6, 0xE9, 0xED, 0xF0, 0xF3, 0xF6, 0xFA, 0xFD,
517
    0x03, 0x0B, 0x12, 0x18, 0x1D, 0x23, 0x28, 0x2D,
518
    0x32, 0x36, 0x3B, 0x40, 0x44, 0x49, 0x4D, 0x51,
519
    0x56, 0x5A, 0x5E, 0x62, 0x66, 0x6A, 0x6E, 0x72,
520
    0x76, 0x7A, 0x7D, 0x81, 0x85, 0x89, 0x8D, 0x90,
521
    0x94, 0x98, 0x9B, 0x9F, 0xA2, 0xA6, 0xAA, 0xAD,
522
    0xB1, 0xB4, 0xB8, 0xBB, 0xBF, 0xC2, 0xC5, 0xC9,
523
    0xCC, 0xD0, 0xD3, 0xD6, 0xDA, 0xDD, 0xE0, 0xE4,
524
    0xE7, 0xEA, 0xED, 0xF1, 0xF4, 0xF7, 0xFA, 0xFD,
525
    0x05, 0x0D, 0x13, 0x19, 0x1F, 0x24, 0x29, 0x2E,
526
    0x33, 0x38, 0x3C, 0x41, 0x45, 0x4A, 0x4E, 0x52,
527
    0x57, 0x5B, 0x5F, 0x63, 0x67, 0x6B, 0x6F, 0x73,
528
    0x77, 0x7B, 0x7E, 0x82, 0x86, 0x8A, 0x8D, 0x91,
529
    0x95, 0x99, 0x9C, 0xA0, 0xA3, 0xA7, 0xAA, 0xAE,
530
    0xB2, 0xB5, 0xB9, 0xBC, 0xBF, 0xC3, 0xC6, 0xCA,
531
    0xCD, 0xD0, 0xD4, 0xD7, 0xDA, 0xDE, 0xE1, 0xE4,
532
    0xE8, 0xEB, 0xEE, 0xF1, 0xF5, 0xF8, 0xFB, 0xFD,
533
    0x07, 0x0E, 0x15, 0x1A, 0x20, 0x25, 0x2A, 0x2F,
534
    0x34, 0x39, 0x3D, 0x42, 0x46, 0x4B, 0x4F, 0x53,
535
    0x58, 0x5C, 0x60, 0x64, 0x68, 0x6C, 0x70, 0x74,
536
    0x78, 0x7C, 0x7F, 0x83, 0x87, 0x8B, 0x8E, 0x92,
537
    0x96, 0x99, 0x9D, 0xA1, 0xA4, 0xA8, 0xAB, 0xAF,
538
    0xB2, 0xB6, 0xB9, 0xBD, 0xC0, 0xC4, 0xC7, 0xCB,
539
    0xCE, 0xD1, 0xD5, 0xD8, 0xDB, 0xDF, 0xE2, 0xE5,
540
    0xE9, 0xEC, 0xEF, 0xF2, 0xF6, 0xF9, 0xFC, 0xFD
541
};
542
#endif
543
544
35
static int xan_decode_frame(AVCodecContext *avctx,
545
                            void *data, int *got_frame,
546
                            AVPacket *avpkt)
547
{
548
35
    AVFrame *frame = data;
549
35
    const uint8_t *buf = avpkt->data;
550
35
    int ret, buf_size = avpkt->size;
551
35
    XanContext *s = avctx->priv_data;
552
    GetByteContext ctx;
553
35
    int tag = 0;
554
555
35
    bytestream2_init(&ctx, buf, buf_size);
556

95
    while (bytestream2_get_bytes_left(&ctx) > 8 && tag != VGA__TAG) {
557
        unsigned *tmpptr;
558
        uint32_t new_pal;
559
        int size;
560
        int i;
561
60
        tag  = bytestream2_get_le32(&ctx);
562
60
        size = bytestream2_get_be32(&ctx);
563
60
        if (size < 0) {
564
            av_log(avctx, AV_LOG_ERROR, "Invalid tag size %d\n", size);
565
            return AVERROR_INVALIDDATA;
566
        }
567
60
        size = FFMIN(size, bytestream2_get_bytes_left(&ctx));
568

60
        switch (tag) {
569
24
        case PALT_TAG:
570
24
            if (size < PALETTE_SIZE)
571
                return AVERROR_INVALIDDATA;
572
24
            if (s->palettes_count >= PALETTES_MAX)
573
                return AVERROR_INVALIDDATA;
574
24
            tmpptr = av_realloc_array(s->palettes,
575
24
                                      s->palettes_count + 1, AVPALETTE_SIZE);
576
24
            if (!tmpptr)
577
                return AVERROR(ENOMEM);
578
24
            s->palettes = tmpptr;
579
24
            tmpptr += s->palettes_count * AVPALETTE_COUNT;
580
6168
            for (i = 0; i < PALETTE_COUNT; i++) {
581
#if RUNTIME_GAMMA
582
                int r = gamma_corr(bytestream2_get_byteu(&ctx));
583
                int g = gamma_corr(bytestream2_get_byteu(&ctx));
584
                int b = gamma_corr(bytestream2_get_byteu(&ctx));
585
#else
586
6144
                int r = gamma_lookup[bytestream2_get_byteu(&ctx)];
587
6144
                int g = gamma_lookup[bytestream2_get_byteu(&ctx)];
588
6144
                int b = gamma_lookup[bytestream2_get_byteu(&ctx)];
589
#endif
590
6144
                *tmpptr++ = (0xFFU << 24) | (r << 16) | (g << 8) | b;
591
            }
592
24
            s->palettes_count++;
593
24
            break;
594
1
        case SHOT_TAG:
595
1
            if (size < 4)
596
                return AVERROR_INVALIDDATA;
597
1
            new_pal = bytestream2_get_le32(&ctx);
598
1
            if (new_pal < s->palettes_count) {
599
1
                s->cur_palette = new_pal;
600
            } else
601
                av_log(avctx, AV_LOG_ERROR, "Invalid palette selected\n");
602
1
            break;
603
35
        case VGA__TAG:
604
35
            break;
605
        default:
606
            bytestream2_skip(&ctx, size);
607
            break;
608
        }
609
    }
610
35
    buf_size = bytestream2_get_bytes_left(&ctx);
611
612
35
    if (s->palettes_count <= 0) {
613
        av_log(s->avctx, AV_LOG_ERROR, "No palette found\n");
614
        return AVERROR_INVALIDDATA;
615
    }
616
617
35
    if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
618
        return ret;
619
620
35
    if (!s->frame_size)
621
1
        s->frame_size = frame->linesize[0] * s->avctx->height;
622
623
35
    memcpy(frame->data[1],
624
35
           s->palettes + s->cur_palette * AVPALETTE_COUNT, AVPALETTE_SIZE);
625
626
35
    s->buf = ctx.buffer;
627
35
    s->size = buf_size;
628
629
35
    if (xan_wc3_decode_frame(s, frame) < 0)
630
        return AVERROR_INVALIDDATA;
631
632
35
    av_frame_unref(s->last_frame);
633
35
    if ((ret = av_frame_ref(s->last_frame, frame)) < 0)
634
        return ret;
635
636
35
    *got_frame = 1;
637
638
    /* always report that the buffer was completely consumed */
639
35
    return buf_size;
640
}
641
642
AVCodec ff_xan_wc3_decoder = {
643
    .name           = "xan_wc3",
644
    .long_name      = NULL_IF_CONFIG_SMALL("Wing Commander III / Xan"),
645
    .type           = AVMEDIA_TYPE_VIDEO,
646
    .id             = AV_CODEC_ID_XAN_WC3,
647
    .priv_data_size = sizeof(XanContext),
648
    .init           = xan_decode_init,
649
    .close          = xan_decode_end,
650
    .decode         = xan_decode_frame,
651
    .capabilities   = AV_CODEC_CAP_DR1,
652
};