GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/xan.c Lines: 245 289 84.8 %
Date: 2021-01-20 23:14:43 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
        return AVERROR(ENOMEM);
105
106
2
    s->last_frame = av_frame_alloc();
107
2
    if (!s->last_frame)
108
        return AVERROR(ENOMEM);
109
110
2
    return 0;
111
}
112
113
35
static int xan_huffman_decode(uint8_t *dest, int dest_len,
114
                              const uint8_t *src, int src_len)
115
{
116
35
    uint8_t byte = *src++;
117
35
    uint8_t ival = byte + 0x16;
118
35
    const uint8_t * ptr = src + byte*2;
119
35
    int ptr_len = src_len - 1 - byte*2;
120
35
    uint8_t val = ival;
121
35
    uint8_t *dest_end = dest + dest_len;
122
35
    uint8_t *dest_start = dest;
123
    int ret;
124
    GetBitContext gb;
125
126
35
    if ((ret = init_get_bits8(&gb, ptr, ptr_len)) < 0)
127
        return ret;
128
129
568491
    while (val != 0x16) {
130
        unsigned idx;
131
568456
        if (get_bits_left(&gb) < 1)
132
            return AVERROR_INVALIDDATA;
133
568456
        idx = val - 0x17 + get_bits1(&gb) * byte;
134
568456
        if (idx >= 2 * byte)
135
            return AVERROR_INVALIDDATA;
136
568456
        val = src[idx];
137
138
568456
        if (val < 0x16) {
139
170624
            if (dest >= dest_end)
140
                return dest_len;
141
170624
            *dest++ = val;
142
170624
            val = ival;
143
        }
144
    }
145
146
35
    return dest - dest_start;
147
}
148
149
/**
150
 * unpack simple compression
151
 *
152
 * @param dest destination buffer of dest_len, must be padded with at least 130 bytes
153
 */
154
21
static void xan_unpack(uint8_t *dest, int dest_len,
155
                       const uint8_t *src, int src_len)
156
{
157
    uint8_t opcode;
158
    int size;
159
21
    uint8_t *dest_org = dest;
160
21
    uint8_t *dest_end = dest + dest_len;
161
    GetByteContext ctx;
162
163
21
    bytestream2_init(&ctx, src, src_len);
164

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

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

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

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

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

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

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

170655
    while (total_pixels && opcode_buffer < opcode_buffer_end) {
357
358
170620
        opcode = *opcode_buffer++;
359
170620
        size = 0;
360
361

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

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

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