GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/xxan.c Lines: 228 267 85.4 %
Date: 2021-04-22 14:24:15 Branches: 87 123 70.7 %

Line Branch Exec Source
1
/*
2
 * Wing Commander/Xan Video Decoder
3
 * Copyright (C) 2011 Konstantin Shishkov
4
 * based on work by Mike Melanson
5
 *
6
 * This file is part of FFmpeg.
7
 *
8
 * FFmpeg is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2.1 of the License, or (at your option) any later version.
12
 *
13
 * FFmpeg is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with FFmpeg; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
 */
22
23
#include "libavutil/intreadwrite.h"
24
#include "libavutil/mem.h"
25
26
#include "avcodec.h"
27
#include "bytestream.h"
28
#include "internal.h"
29
30
typedef struct XanContext {
31
    AVCodecContext *avctx;
32
    AVFrame *pic;
33
34
    uint8_t *y_buffer;
35
    uint8_t *scratch_buffer;
36
    int     buffer_size;
37
    GetByteContext gb;
38
} XanContext;
39
40
3
static av_cold int xan_decode_end(AVCodecContext *avctx)
41
{
42
3
    XanContext *s = avctx->priv_data;
43
44
3
    av_frame_free(&s->pic);
45
46
3
    av_freep(&s->y_buffer);
47
3
    av_freep(&s->scratch_buffer);
48
49
3
    return 0;
50
}
51
52
3
static av_cold int xan_decode_init(AVCodecContext *avctx)
53
{
54
3
    XanContext *s = avctx->priv_data;
55
56
3
    s->avctx = avctx;
57
58
3
    avctx->pix_fmt = AV_PIX_FMT_YUV420P;
59
60
3
    if (avctx->height < 8) {
61
        av_log(avctx, AV_LOG_ERROR, "Invalid frame height: %d.\n", avctx->height);
62
        return AVERROR(EINVAL);
63
    }
64
3
    if (avctx->width & 1) {
65
        av_log(avctx, AV_LOG_ERROR, "Invalid frame width: %d.\n", avctx->width);
66
        return AVERROR(EINVAL);
67
    }
68
69
3
    s->buffer_size = avctx->width * avctx->height;
70
3
    s->y_buffer = av_malloc(s->buffer_size);
71
3
    if (!s->y_buffer)
72
        return AVERROR(ENOMEM);
73
3
    s->scratch_buffer = av_malloc(s->buffer_size + 130);
74
3
    if (!s->scratch_buffer)
75
        return AVERROR(ENOMEM);
76
77
3
    s->pic = av_frame_alloc();
78
3
    if (!s->pic)
79
        return AVERROR(ENOMEM);
80
81
3
    return 0;
82
}
83
84
21
static int xan_unpack_luma(XanContext *s,
85
                           uint8_t *dst, const int dst_size)
86
{
87
    int tree_size, eof;
88
    int bits, mask;
89
    int tree_root, node;
90
21
    const uint8_t *dst_end = dst + dst_size;
91
21
    GetByteContext tree = s->gb;
92
21
    int start_off = bytestream2_tell(&tree);
93
94
21
    tree_size = bytestream2_get_byte(&s->gb);
95
21
    eof       = bytestream2_get_byte(&s->gb);
96
21
    tree_root = eof + tree_size;
97
21
    bytestream2_skip(&s->gb, tree_size * 2);
98
99
21
    node = tree_root;
100
21
    bits = bytestream2_get_byte(&s->gb);
101
21
    mask = 0x80;
102
691350
    for (;;) {
103
691371
        int bit = !!(bits & mask);
104
691371
        mask >>= 1;
105
691371
        bytestream2_seek(&tree, start_off + node*2 + bit - eof * 2, SEEK_SET);
106
691371
        node = bytestream2_get_byte(&tree);
107
691371
        if (node == eof)
108
21
            break;
109
691350
        if (node < eof) {
110
554400
            *dst++ = node;
111
554400
            if (dst > dst_end)
112
                break;
113
554400
            node = tree_root;
114
        }
115
691350
        if (!mask) {
116
86409
            if (bytestream2_get_bytes_left(&s->gb) <= 0)
117
                break;
118
86409
            bits = bytestream2_get_byteu(&s->gb);
119
86409
            mask = 0x80;
120
        }
121
    }
122
21
    return dst != dst_end ? AVERROR_INVALIDDATA : 0;
123
}
124
125
/* almost the same as in xan_wc3 decoder */
126
26
static int xan_unpack(XanContext *s,
127
                      uint8_t *dest, const int dest_len)
128
{
129
    uint8_t opcode;
130
    int size;
131
26
    uint8_t *orig_dest = dest;
132
26
    const uint8_t *dest_end = dest + dest_len;
133
134
11861
    while (dest < dest_end) {
135
11856
        if (bytestream2_get_bytes_left(&s->gb) <= 0)
136
            return AVERROR_INVALIDDATA;
137
138
11856
        opcode = bytestream2_get_byteu(&s->gb);
139
140
11856
        if (opcode < 0xe0) {
141
            int size2, back;
142
11348
            if ((opcode & 0x80) == 0) {
143
7882
                size  = opcode & 3;
144
7882
                back  = ((opcode & 0x60) << 3) + bytestream2_get_byte(&s->gb) + 1;
145
7882
                size2 = ((opcode & 0x1c) >> 2) + 3;
146
3466
            } else if ((opcode & 0x40) == 0) {
147
3066
                size  = bytestream2_peek_byte(&s->gb) >> 6;
148
3066
                back  = (bytestream2_get_be16(&s->gb) & 0x3fff) + 1;
149
3066
                size2 = (opcode & 0x3f) + 4;
150
            } else {
151
400
                size  = opcode & 3;
152
400
                back  = ((opcode & 0x10) << 12) + bytestream2_get_be16(&s->gb) + 1;
153
400
                size2 = ((opcode & 0x0c) <<  6) + bytestream2_get_byte(&s->gb) + 5;
154
400
                if (size + size2 > dest_end - dest)
155
                    break;
156
            }
157
11348
            if (dest + size + size2 > dest_end ||
158
11348
                dest - orig_dest + size < back)
159
                return AVERROR_INVALIDDATA;
160
11348
            bytestream2_get_buffer(&s->gb, dest, size);
161
11348
            dest += size;
162
11348
            av_memcpy_backptr(dest, back, size2);
163
11348
            dest += size2;
164
        } else {
165
508
            int finish = opcode >= 0xfc;
166
167
508
            size = finish ? opcode & 3 : ((opcode & 0x1f) << 2) + 4;
168
508
            if (dest_end - dest < size)
169
                return AVERROR_INVALIDDATA;
170
508
            bytestream2_get_buffer(&s->gb, dest, size);
171
508
            dest += size;
172
508
            if (finish)
173
21
                break;
174
        }
175
    }
176
26
    return dest - orig_dest;
177
}
178
179
21
static int xan_decode_chroma(AVCodecContext *avctx, unsigned chroma_off)
180
{
181
21
    XanContext *s = avctx->priv_data;
182
    uint8_t *U, *V;
183
    int val, uval, vval;
184
    int i, j;
185
    const uint8_t *src, *src_end;
186
    const uint8_t *table;
187
    int mode, offset, dec_size, table_size;
188
189
21
    if (!chroma_off)
190
        return 0;
191
21
    if (chroma_off + 4 >= bytestream2_get_bytes_left(&s->gb)) {
192
        av_log(avctx, AV_LOG_ERROR, "Invalid chroma block position\n");
193
        return AVERROR_INVALIDDATA;
194
    }
195
21
    bytestream2_seek(&s->gb, chroma_off + 4, SEEK_SET);
196
21
    mode        = bytestream2_get_le16(&s->gb);
197
21
    table       = s->gb.buffer;
198
21
    table_size  = bytestream2_get_le16(&s->gb);
199
21
    offset      = table_size * 2;
200
21
    table_size += 1;
201
202
21
    if (offset >= bytestream2_get_bytes_left(&s->gb)) {
203
        av_log(avctx, AV_LOG_ERROR, "Invalid chroma block offset\n");
204
        return AVERROR_INVALIDDATA;
205
    }
206
207
21
    bytestream2_skip(&s->gb, offset);
208
21
    memset(s->scratch_buffer, 0, s->buffer_size);
209
21
    dec_size = xan_unpack(s, s->scratch_buffer, s->buffer_size);
210
21
    if (dec_size < 0) {
211
        av_log(avctx, AV_LOG_ERROR, "Chroma unpacking failed\n");
212
        return dec_size;
213
    }
214
215
21
    U = s->pic->data[1];
216
21
    V = s->pic->data[2];
217
21
    src     = s->scratch_buffer;
218
21
    src_end = src + dec_size;
219
21
    if (mode) {
220
332
        for (j = 0; j < avctx->height >> 1; j++) {
221
52808
            for (i = 0; i < avctx->width >> 1; i++) {
222
52480
                if (src_end - src < 1)
223
                    return 0;
224
52480
                val = *src++;
225
52480
                if (val) {
226
52480
                    if (val >= table_size)
227
                        return AVERROR_INVALIDDATA;
228
52480
                    val  = AV_RL16(table + (val << 1));
229
52480
                    uval = (val >> 3) & 0xF8;
230
52480
                    vval = (val >> 8) & 0xF8;
231
52480
                    U[i] = uval | (uval >> 5);
232
52480
                    V[i] = vval | (vval >> 5);
233
                }
234
            }
235
328
            U += s->pic->linesize[1];
236
328
            V += s->pic->linesize[2];
237
        }
238
4
        if (avctx->height & 1) {
239
4
            memcpy(U, U - s->pic->linesize[1], avctx->width >> 1);
240
4
            memcpy(V, V - s->pic->linesize[2], avctx->width >> 1);
241
        }
242
    } else {
243
17
        uint8_t *U2 = U + s->pic->linesize[1];
244
17
        uint8_t *V2 = V + s->pic->linesize[2];
245
246
714
        for (j = 0; j < avctx->height >> 2; j++) {
247
56457
            for (i = 0; i < avctx->width >> 1; i += 2) {
248
55760
                if (src_end - src < 1)
249
                    return 0;
250
55760
                val = *src++;
251
55760
                if (val) {
252
17613
                    if (val >= table_size)
253
                        return AVERROR_INVALIDDATA;
254
17613
                    val  = AV_RL16(table + (val << 1));
255
17613
                    uval = (val >> 3) & 0xF8;
256
17613
                    vval = (val >> 8) & 0xF8;
257
17613
                    U[i] = U[i+1] = U2[i] = U2[i+1] = uval | (uval >> 5);
258
17613
                    V[i] = V[i+1] = V2[i] = V2[i+1] = vval | (vval >> 5);
259
                }
260
            }
261
697
            U  += s->pic->linesize[1] * 2;
262
697
            V  += s->pic->linesize[2] * 2;
263
697
            U2 += s->pic->linesize[1] * 2;
264
697
            V2 += s->pic->linesize[2] * 2;
265
        }
266
17
        if (avctx->height & 3) {
267
17
            int lines = ((avctx->height + 1) >> 1) - (avctx->height >> 2) * 2;
268
269
17
            memcpy(U, U - lines * s->pic->linesize[1], lines * s->pic->linesize[1]);
270
17
            memcpy(V, V - lines * s->pic->linesize[2], lines * s->pic->linesize[2]);
271
        }
272
    }
273
274
21
    return 0;
275
}
276
277
5
static int xan_decode_frame_type0(AVCodecContext *avctx)
278
{
279
5
    XanContext *s = avctx->priv_data;
280
5
    uint8_t *ybuf, *prev_buf, *src = s->scratch_buffer;
281
    unsigned  chroma_off, corr_off;
282
    int cur, last;
283
    int i, j;
284
    int ret;
285
286
5
    chroma_off = bytestream2_get_le32(&s->gb);
287
5
    corr_off   = bytestream2_get_le32(&s->gb);
288
289
5
    if ((ret = xan_decode_chroma(avctx, chroma_off)) != 0)
290
        return ret;
291
292
5
    if (corr_off >= bytestream2_size(&s->gb)) {
293
        av_log(avctx, AV_LOG_WARNING, "Ignoring invalid correction block position\n");
294
        corr_off = 0;
295
    }
296
5
    bytestream2_seek(&s->gb, 12, SEEK_SET);
297
5
    ret = xan_unpack_luma(s, src, s->buffer_size >> 1);
298
5
    if (ret) {
299
        av_log(avctx, AV_LOG_ERROR, "Luma decoding failed\n");
300
        return ret;
301
    }
302
303
5
    ybuf = s->y_buffer;
304
5
    last = *src++;
305
5
    ybuf[0] = last << 1;
306
800
    for (j = 1; j < avctx->width - 1; j += 2) {
307
795
        cur = (last + *src++) & 0x1F;
308
795
        ybuf[j]   = last + cur;
309
795
        ybuf[j+1] = cur << 1;
310
795
        last = cur;
311
    }
312
5
    ybuf[j]  = last << 1;
313
5
    prev_buf = ybuf;
314
5
    ybuf += avctx->width;
315
316
825
    for (i = 1; i < avctx->height; i++) {
317
820
        last = ((prev_buf[0] >> 1) + *src++) & 0x1F;
318
820
        ybuf[0] = last << 1;
319
131200
        for (j = 1; j < avctx->width - 1; j += 2) {
320
130380
            cur = ((prev_buf[j + 1] >> 1) + *src++) & 0x1F;
321
130380
            ybuf[j]   = last + cur;
322
130380
            ybuf[j+1] = cur << 1;
323
130380
            last = cur;
324
        }
325
820
        ybuf[j] = last << 1;
326
820
        prev_buf = ybuf;
327
820
        ybuf += avctx->width;
328
    }
329
330
5
    if (corr_off) {
331
        int dec_size;
332
333
5
        bytestream2_seek(&s->gb, 8 + corr_off, SEEK_SET);
334
5
        dec_size = xan_unpack(s, s->scratch_buffer, s->buffer_size / 2);
335
5
        if (dec_size < 0)
336
            dec_size = 0;
337
        else
338
5
            dec_size = FFMIN(dec_size, s->buffer_size/2 - 1);
339
340
132000
        for (i = 0; i < dec_size; i++)
341
131995
            s->y_buffer[i*2+1] = (s->y_buffer[i*2+1] + (s->scratch_buffer[i] << 1)) & 0x3F;
342
    }
343
344
5
    src  = s->y_buffer;
345
5
    ybuf = s->pic->data[0];
346
830
    for (j = 0; j < avctx->height; j++) {
347
264825
        for (i = 0; i < avctx->width; i++)
348
264000
            ybuf[i] = (src[i] << 2) | (src[i] >> 3);
349
825
        src  += avctx->width;
350
825
        ybuf += s->pic->linesize[0];
351
    }
352
353
5
    return 0;
354
}
355
356
16
static int xan_decode_frame_type1(AVCodecContext *avctx)
357
{
358
16
    XanContext *s = avctx->priv_data;
359
16
    uint8_t *ybuf, *src = s->scratch_buffer;
360
    int cur, last;
361
    int i, j;
362
    int ret;
363
364
16
    if ((ret = xan_decode_chroma(avctx, bytestream2_get_le32(&s->gb))) != 0)
365
        return ret;
366
367
16
    bytestream2_seek(&s->gb, 16, SEEK_SET);
368
16
    ret = xan_unpack_luma(s, src,
369
16
                          s->buffer_size >> 1);
370
16
    if (ret) {
371
        av_log(avctx, AV_LOG_ERROR, "Luma decoding failed\n");
372
        return ret;
373
    }
374
375
16
    ybuf = s->y_buffer;
376
2656
    for (i = 0; i < avctx->height; i++) {
377
2640
        last = (ybuf[0] + (*src++ << 1)) & 0x3F;
378
2640
        ybuf[0] = last;
379
422400
        for (j = 1; j < avctx->width - 1; j += 2) {
380
419760
            cur = (ybuf[j + 1] + (*src++ << 1)) & 0x3F;
381
419760
            ybuf[j]   = (last + cur) >> 1;
382
419760
            ybuf[j+1] = cur;
383
419760
            last = cur;
384
        }
385
2640
        ybuf[j] = last;
386
2640
        ybuf += avctx->width;
387
    }
388
389
16
    src = s->y_buffer;
390
16
    ybuf = s->pic->data[0];
391
2656
    for (j = 0; j < avctx->height; j++) {
392
847440
        for (i = 0; i < avctx->width; i++)
393
844800
            ybuf[i] = (src[i] << 2) | (src[i] >> 3);
394
2640
        src  += avctx->width;
395
2640
        ybuf += s->pic->linesize[0];
396
    }
397
398
16
    return 0;
399
}
400
401
21
static int xan_decode_frame(AVCodecContext *avctx,
402
                            void *data, int *got_frame,
403
                            AVPacket *avpkt)
404
{
405
21
    XanContext *s = avctx->priv_data;
406
    int ftype;
407
    int ret;
408
409
21
    if ((ret = ff_reget_buffer(avctx, s->pic, 0)) < 0)
410
        return ret;
411
412
21
    bytestream2_init(&s->gb, avpkt->data, avpkt->size);
413
21
    ftype = bytestream2_get_le32(&s->gb);
414
21
    switch (ftype) {
415
5
    case 0:
416
5
        ret = xan_decode_frame_type0(avctx);
417
5
        break;
418
16
    case 1:
419
16
        ret = xan_decode_frame_type1(avctx);
420
16
        break;
421
    default:
422
        av_log(avctx, AV_LOG_ERROR, "Unknown frame type %d\n", ftype);
423
        return AVERROR_INVALIDDATA;
424
    }
425
21
    if (ret)
426
        return ret;
427
428
21
    if ((ret = av_frame_ref(data, s->pic)) < 0)
429
        return ret;
430
431
21
    *got_frame = 1;
432
433
21
    return avpkt->size;
434
}
435
436
AVCodec ff_xan_wc4_decoder = {
437
    .name           = "xan_wc4",
438
    .long_name      = NULL_IF_CONFIG_SMALL("Wing Commander IV / Xxan"),
439
    .type           = AVMEDIA_TYPE_VIDEO,
440
    .id             = AV_CODEC_ID_XAN_WC4,
441
    .priv_data_size = sizeof(XanContext),
442
    .init           = xan_decode_init,
443
    .close          = xan_decode_end,
444
    .decode         = xan_decode_frame,
445
    .capabilities   = AV_CODEC_CAP_DR1,
446
    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE,
447
};