GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/magicyuv.c Lines: 242 438 55.3 %
Date: 2021-04-20 15:25:36 Branches: 104 207 50.2 %

Line Branch Exec Source
1
/*
2
 * MagicYUV decoder
3
 * Copyright (c) 2016 Paul B Mahol
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
#include <stdlib.h>
23
#include <string.h>
24
25
#define CACHED_BITSTREAM_READER !ARCH_X86_32
26
27
#include "libavutil/pixdesc.h"
28
29
#include "avcodec.h"
30
#include "bytestream.h"
31
#include "get_bits.h"
32
#include "huffyuvdsp.h"
33
#include "internal.h"
34
#include "lossless_videodsp.h"
35
#include "thread.h"
36
37
typedef struct Slice {
38
    uint32_t start;
39
    uint32_t size;
40
} Slice;
41
42
typedef enum Prediction {
43
    LEFT = 1,
44
    GRADIENT,
45
    MEDIAN,
46
} Prediction;
47
48
typedef struct HuffEntry {
49
    uint8_t  len;
50
    uint16_t sym;
51
} HuffEntry;
52
53
typedef struct MagicYUVContext {
54
    AVFrame          *p;
55
    int               max;
56
    int               bps;
57
    int               slice_height;
58
    int               nb_slices;
59
    int               planes;         // number of encoded planes in bitstream
60
    int               decorrelate;    // postprocessing work
61
    int               color_matrix;   // video color matrix
62
    int               flags;
63
    int               interlaced;     // video is interlaced
64
    const uint8_t    *buf;            // pointer to AVPacket->data
65
    int               hshift[4];
66
    int               vshift[4];
67
    Slice            *slices[4];      // slice bitstream positions for each plane
68
    unsigned int      slices_size[4]; // slice sizes for each plane
69
    VLC               vlc[4];         // VLC for each plane
70
    int (*magy_decode_slice)(AVCodecContext *avctx, void *tdata,
71
                             int j, int threadnr);
72
    LLVidDSPContext   llviddsp;
73
} MagicYUVContext;
74
75
42
static int huff_build(const uint8_t len[], uint16_t codes_pos[33],
76
                      VLC *vlc, int nb_elems, void *logctx)
77
{
78
    HuffEntry he[4096];
79
80
1344
    for (int i = 31; i > 0; i--)
81
1302
        codes_pos[i] += codes_pos[i + 1];
82
83
10794
    for (unsigned i = nb_elems; i-- > 0;)
84
10752
        he[--codes_pos[len[i]]] = (HuffEntry){ len[i], i };
85
86
42
    ff_free_vlc(vlc);
87
42
    return ff_init_vlc_from_lengths(vlc, FFMIN(he[0].len, 12), nb_elems,
88
                                    &he[0].len, sizeof(he[0]),
89
                                    &he[0].sym, sizeof(he[0]), sizeof(he[0].sym),
90
                                    0, 0, logctx);
91
}
92
93
static void magicyuv_median_pred16(uint16_t *dst, const uint16_t *src1,
94
                                   const uint16_t *diff, intptr_t w,
95
                                   int *left, int *left_top, int max)
96
{
97
    int i;
98
    uint16_t l, lt;
99
100
    l  = *left;
101
    lt = *left_top;
102
103
    for (i = 0; i < w; i++) {
104
        l      = mid_pred(l, src1[i], (l + src1[i] - lt)) + diff[i];
105
        l     &= max;
106
        lt     = src1[i];
107
        dst[i] = l;
108
    }
109
110
    *left     = l;
111
    *left_top = lt;
112
}
113
114
static int magy_decode_slice10(AVCodecContext *avctx, void *tdata,
115
                               int j, int threadnr)
116
{
117
    MagicYUVContext *s = avctx->priv_data;
118
    int interlaced = s->interlaced;
119
    const int bps = s->bps;
120
    const int max = s->max - 1;
121
    AVFrame *p = s->p;
122
    int i, k, x;
123
    GetBitContext gb;
124
    uint16_t *dst;
125
126
    for (i = 0; i < s->planes; i++) {
127
        int left, lefttop, top;
128
        int height = AV_CEIL_RSHIFT(FFMIN(s->slice_height, avctx->coded_height - j * s->slice_height), s->vshift[i]);
129
        int width = AV_CEIL_RSHIFT(avctx->coded_width, s->hshift[i]);
130
        int sheight = AV_CEIL_RSHIFT(s->slice_height, s->vshift[i]);
131
        ptrdiff_t fake_stride = (p->linesize[i] / 2) * (1 + interlaced);
132
        ptrdiff_t stride = p->linesize[i] / 2;
133
        int flags, pred;
134
        int ret = init_get_bits8(&gb, s->buf + s->slices[i][j].start,
135
                                 s->slices[i][j].size);
136
137
        if (ret < 0)
138
            return ret;
139
140
        flags = get_bits(&gb, 8);
141
        pred  = get_bits(&gb, 8);
142
143
        dst = (uint16_t *)p->data[i] + j * sheight * stride;
144
        if (flags & 1) {
145
            if (get_bits_left(&gb) < bps * width * height)
146
                return AVERROR_INVALIDDATA;
147
            for (k = 0; k < height; k++) {
148
                for (x = 0; x < width; x++)
149
                    dst[x] = get_bits(&gb, bps);
150
151
                dst += stride;
152
            }
153
        } else {
154
            for (k = 0; k < height; k++) {
155
                for (x = 0; x < width; x++) {
156
                    int pix;
157
                    if (get_bits_left(&gb) <= 0)
158
                        return AVERROR_INVALIDDATA;
159
160
                    pix = get_vlc2(&gb, s->vlc[i].table, s->vlc[i].bits, 3);
161
                    if (pix < 0)
162
                        return AVERROR_INVALIDDATA;
163
164
                    dst[x] = pix;
165
                }
166
                dst += stride;
167
            }
168
        }
169
170
        switch (pred) {
171
        case LEFT:
172
            dst = (uint16_t *)p->data[i] + j * sheight * stride;
173
            s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0);
174
            dst += stride;
175
            if (interlaced) {
176
                s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0);
177
                dst += stride;
178
            }
179
            for (k = 1 + interlaced; k < height; k++) {
180
                s->llviddsp.add_left_pred_int16(dst, dst, max, width, dst[-fake_stride]);
181
                dst += stride;
182
            }
183
            break;
184
        case GRADIENT:
185
            dst = (uint16_t *)p->data[i] + j * sheight * stride;
186
            s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0);
187
            dst += stride;
188
            if (interlaced) {
189
                s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0);
190
                dst += stride;
191
            }
192
            for (k = 1 + interlaced; k < height; k++) {
193
                top = dst[-fake_stride];
194
                left = top + dst[0];
195
                dst[0] = left & max;
196
                for (x = 1; x < width; x++) {
197
                    top = dst[x - fake_stride];
198
                    lefttop = dst[x - (fake_stride + 1)];
199
                    left += top - lefttop + dst[x];
200
                    dst[x] = left & max;
201
                }
202
                dst += stride;
203
            }
204
            break;
205
        case MEDIAN:
206
            dst = (uint16_t *)p->data[i] + j * sheight * stride;
207
            s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0);
208
            dst += stride;
209
            if (interlaced) {
210
                s->llviddsp.add_left_pred_int16(dst, dst, max, width, 0);
211
                dst += stride;
212
            }
213
            lefttop = left = dst[0];
214
            for (k = 1 + interlaced; k < height; k++) {
215
                magicyuv_median_pred16(dst, dst - fake_stride, dst, width, &left, &lefttop, max);
216
                lefttop = left = dst[0];
217
                dst += stride;
218
            }
219
            break;
220
        default:
221
            avpriv_request_sample(avctx, "Unknown prediction: %d", pred);
222
        }
223
    }
224
225
    if (s->decorrelate) {
226
        int height = FFMIN(s->slice_height, avctx->coded_height - j * s->slice_height);
227
        int width = avctx->coded_width;
228
        uint16_t *r = (uint16_t *)p->data[0] + j * s->slice_height * p->linesize[0] / 2;
229
        uint16_t *g = (uint16_t *)p->data[1] + j * s->slice_height * p->linesize[1] / 2;
230
        uint16_t *b = (uint16_t *)p->data[2] + j * s->slice_height * p->linesize[2] / 2;
231
232
        for (i = 0; i < height; i++) {
233
            for (k = 0; k < width; k++) {
234
                b[k] = (b[k] + g[k]) & max;
235
                r[k] = (r[k] + g[k]) & max;
236
            }
237
            b += p->linesize[0] / 2;
238
            g += p->linesize[1] / 2;
239
            r += p->linesize[2] / 2;
240
        }
241
    }
242
243
    return 0;
244
}
245
246
126
static int magy_decode_slice(AVCodecContext *avctx, void *tdata,
247
                             int j, int threadnr)
248
{
249
126
    MagicYUVContext *s = avctx->priv_data;
250
126
    int interlaced = s->interlaced;
251
126
    AVFrame *p = s->p;
252
    int i, k, x, min_width;
253
    GetBitContext gb;
254
    uint8_t *dst;
255
256
504
    for (i = 0; i < s->planes; i++) {
257
        int left, lefttop, top;
258
378
        int height = AV_CEIL_RSHIFT(FFMIN(s->slice_height, avctx->coded_height - j * s->slice_height), s->vshift[i]);
259
378
        int width = AV_CEIL_RSHIFT(avctx->coded_width, s->hshift[i]);
260
378
        int sheight = AV_CEIL_RSHIFT(s->slice_height, s->vshift[i]);
261
378
        ptrdiff_t fake_stride = p->linesize[i] * (1 + interlaced);
262
378
        ptrdiff_t stride = p->linesize[i];
263
378
        const uint8_t *slice = s->buf + s->slices[i][j].start;
264
        int flags, pred;
265
266
378
        flags = bytestream_get_byte(&slice);
267
378
        pred  = bytestream_get_byte(&slice);
268
269
378
        dst = p->data[i] + j * sheight * stride;
270
378
        if (flags & 1) {
271
            if (s->slices[i][j].size - 2 < width * height)
272
                return AVERROR_INVALIDDATA;
273
            for (k = 0; k < height; k++) {
274
                bytestream_get_buffer(&slice, dst, width);
275
                dst += stride;
276
            }
277
        } else {
278
378
            int ret = init_get_bits8(&gb, slice, s->slices[i][j].size - 2);
279
280
378
            if (ret < 0)
281
                return ret;
282
283
9658
            for (k = 0; k < height; k++) {
284
1794752
                for (x = 0; x < width; x++) {
285
                    int pix;
286
1785472
                    if (get_bits_left(&gb) <= 0)
287
                        return AVERROR_INVALIDDATA;
288
289
1785472
                    pix = get_vlc2(&gb, s->vlc[i].table, s->vlc[i].bits, 3);
290
1785472
                    if (pix < 0)
291
                        return AVERROR_INVALIDDATA;
292
293
1785472
                    dst[x] = pix;
294
                }
295
9280
                dst += stride;
296
            }
297
        }
298
299

378
        switch (pred) {
300
126
        case LEFT:
301
126
            dst = p->data[i] + j * sheight * stride;
302
126
            s->llviddsp.add_left_pred(dst, dst, width, 0);
303
126
            dst += stride;
304
126
            if (interlaced) {
305
72
                s->llviddsp.add_left_pred(dst, dst, width, 0);
306
72
                dst += stride;
307
            }
308
3176
            for (k = 1 + interlaced; k < height; k++) {
309
3050
                s->llviddsp.add_left_pred(dst, dst, width, dst[-fake_stride]);
310
3050
                dst += stride;
311
            }
312
126
            break;
313
90
        case GRADIENT:
314
90
            dst = p->data[i] + j * sheight * stride;
315
90
            s->llviddsp.add_left_pred(dst, dst, width, 0);
316
90
            dst += stride;
317
90
            if (interlaced) {
318
18
                s->llviddsp.add_left_pred(dst, dst, width, 0);
319
18
                dst += stride;
320
            }
321
90
            min_width = FFMIN(width, 32);
322
2302
            for (k = 1 + interlaced; k < height; k++) {
323
2212
                top = dst[-fake_stride];
324
2212
                left = top + dst[0];
325
2212
                dst[0] = left;
326
70784
                for (x = 1; x < min_width; x++) { /* dsp need aligned 32 */
327
68572
                    top = dst[x - fake_stride];
328
68572
                    lefttop = dst[x - (fake_stride + 1)];
329
68572
                    left += top - lefttop + dst[x];
330
68572
                    dst[x] = left;
331
                }
332
2212
                if (width > 32)
333
2212
                    s->llviddsp.add_gradient_pred(dst + 32, fake_stride, width - 32);
334
2212
                dst += stride;
335
            }
336
90
            break;
337
162
        case MEDIAN:
338
162
            dst = p->data[i] + j * sheight * stride;
339
162
            s->llviddsp.add_left_pred(dst, dst, width, 0);
340
162
            dst += stride;
341
162
            if (interlaced) {
342
54
                s->llviddsp.add_left_pred(dst, dst, width, 0);
343
54
                dst += stride;
344
            }
345
162
            lefttop = left = dst[0];
346
3658
            for (k = 1 + interlaced; k < height; k++) {
347
3496
                s->llviddsp.add_median_pred(dst, dst - fake_stride,
348
                                             dst, width, &left, &lefttop);
349
3496
                lefttop = left = dst[0];
350
3496
                dst += stride;
351
            }
352
162
            break;
353
        default:
354
            avpriv_request_sample(avctx, "Unknown prediction: %d", pred);
355
        }
356
    }
357
358
126
    if (s->decorrelate) {
359
36
        int height = FFMIN(s->slice_height, avctx->coded_height - j * s->slice_height);
360
36
        int width = avctx->coded_width;
361
36
        uint8_t *b = p->data[0] + j * s->slice_height * p->linesize[0];
362
36
        uint8_t *g = p->data[1] + j * s->slice_height * p->linesize[1];
363
36
        uint8_t *r = p->data[2] + j * s->slice_height * p->linesize[2];
364
365
964
        for (i = 0; i < height; i++) {
366
928
            s->llviddsp.add_bytes(b, g, width);
367
928
            s->llviddsp.add_bytes(r, g, width);
368
928
            b += p->linesize[0];
369
928
            g += p->linesize[1];
370
928
            r += p->linesize[2];
371
        }
372
    }
373
374
126
    return 0;
375
}
376
377
14
static int build_huffman(AVCodecContext *avctx, const uint8_t *table,
378
                         int table_size, int max)
379
{
380
14
    MagicYUVContext *s = avctx->priv_data;
381
    GetByteContext gb;
382
    uint8_t len[4096];
383
14
    uint16_t length_count[33] = { 0 };
384
14
    int i = 0, j = 0, k;
385
386
14
    bytestream2_init(&gb, table, table_size);
387
388
1036
    while (bytestream2_get_bytes_left(&gb) > 0) {
389
1036
        int b = bytestream2_peek_byteu(&gb) &  0x80;
390
1036
        int x = bytestream2_get_byteu(&gb)  & ~0x80;
391
1036
        int l = 1;
392
393
1036
        if (b) {
394
424
            if (bytestream2_get_bytes_left(&gb) <= 0)
395
                break;
396
424
            l += bytestream2_get_byteu(&gb);
397
        }
398
1036
        k = j + l;
399

1036
        if (k > max || x == 0 || x > 32) {
400
            av_log(avctx, AV_LOG_ERROR, "Invalid Huffman codes\n");
401
            return AVERROR_INVALIDDATA;
402
        }
403
404
1036
        length_count[x] += l;
405
11788
        for (; j < k; j++)
406
10752
            len[j] = x;
407
408
1036
        if (j == max) {
409
42
            j = 0;
410
42
            if (huff_build(len, length_count, &s->vlc[i], max, avctx)) {
411
                av_log(avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n");
412
                return AVERROR_INVALIDDATA;
413
            }
414
42
            i++;
415
42
            if (i == s->planes) {
416
14
                break;
417
            }
418
28
            memset(length_count, 0, sizeof(length_count));
419
        }
420
    }
421
422
14
    if (i != s->planes) {
423
        av_log(avctx, AV_LOG_ERROR, "Huffman tables too short\n");
424
        return AVERROR_INVALIDDATA;
425
    }
426
427
14
    return 0;
428
}
429
430
14
static int magy_decode_frame(AVCodecContext *avctx, void *data,
431
                             int *got_frame, AVPacket *avpkt)
432
{
433
14
    MagicYUVContext *s = avctx->priv_data;
434
14
    ThreadFrame frame = { .f = data };
435
14
    AVFrame *p = data;
436
    GetByteContext gb;
437
    uint32_t first_offset, offset, next_offset, header_size, slice_width;
438
    int width, height, format, version, table_size;
439
    int ret, i, j;
440
441
14
    if (avpkt->size < 36)
442
        return AVERROR_INVALIDDATA;
443
444
14
    bytestream2_init(&gb, avpkt->data, avpkt->size);
445
14
    if (bytestream2_get_le32u(&gb) != MKTAG('M', 'A', 'G', 'Y'))
446
        return AVERROR_INVALIDDATA;
447
448
14
    header_size = bytestream2_get_le32u(&gb);
449

14
    if (header_size < 32 || header_size >= avpkt->size) {
450
        av_log(avctx, AV_LOG_ERROR,
451
               "header or packet too small %"PRIu32"\n", header_size);
452
        return AVERROR_INVALIDDATA;
453
    }
454
455
14
    version = bytestream2_get_byteu(&gb);
456
14
    if (version != 7) {
457
        avpriv_request_sample(avctx, "Version %d", version);
458
        return AVERROR_PATCHWELCOME;
459
    }
460
461
14
    s->hshift[1] =
462
14
    s->vshift[1] =
463
14
    s->hshift[2] =
464
14
    s->vshift[2] = 0;
465
14
    s->decorrelate = 0;
466
14
    s->bps = 8;
467
468
14
    format = bytestream2_get_byteu(&gb);
469




14
    switch (format) {
470
2
    case 0x65:
471
2
        avctx->pix_fmt = AV_PIX_FMT_GBRP;
472
2
        s->decorrelate = 1;
473
2
        break;
474
2
    case 0x66:
475
2
        avctx->pix_fmt = AV_PIX_FMT_GBRAP;
476
2
        s->decorrelate = 1;
477
2
        break;
478
2
    case 0x67:
479
2
        avctx->pix_fmt = AV_PIX_FMT_YUV444P;
480
2
        break;
481
2
    case 0x68:
482
2
        avctx->pix_fmt = AV_PIX_FMT_YUV422P;
483
2
        s->hshift[1] =
484
2
        s->hshift[2] = 1;
485
2
        break;
486
2
    case 0x69:
487
2
        avctx->pix_fmt = AV_PIX_FMT_YUV420P;
488
2
        s->hshift[1] =
489
2
        s->vshift[1] =
490
2
        s->hshift[2] =
491
2
        s->vshift[2] = 1;
492
2
        break;
493
2
    case 0x6a:
494
2
        avctx->pix_fmt = AV_PIX_FMT_YUVA444P;
495
2
        break;
496
2
    case 0x6b:
497
2
        avctx->pix_fmt = AV_PIX_FMT_GRAY8;
498
2
        break;
499
    case 0x6c:
500
        avctx->pix_fmt = AV_PIX_FMT_YUV422P10;
501
        s->hshift[1] =
502
        s->hshift[2] = 1;
503
        s->bps = 10;
504
        break;
505
    case 0x76:
506
        avctx->pix_fmt = AV_PIX_FMT_YUV444P10;
507
        s->bps = 10;
508
        break;
509
    case 0x6d:
510
        avctx->pix_fmt = AV_PIX_FMT_GBRP10;
511
        s->decorrelate = 1;
512
        s->bps = 10;
513
        break;
514
    case 0x6e:
515
        avctx->pix_fmt = AV_PIX_FMT_GBRAP10;
516
        s->decorrelate = 1;
517
        s->bps = 10;
518
        break;
519
    case 0x6f:
520
        avctx->pix_fmt = AV_PIX_FMT_GBRP12;
521
        s->decorrelate = 1;
522
        s->bps = 12;
523
        break;
524
    case 0x70:
525
        avctx->pix_fmt = AV_PIX_FMT_GBRAP12;
526
        s->decorrelate = 1;
527
        s->bps = 12;
528
        break;
529
    case 0x73:
530
        avctx->pix_fmt = AV_PIX_FMT_GRAY10;
531
        s->bps = 10;
532
        break;
533
    case 0x7b:
534
        avctx->pix_fmt = AV_PIX_FMT_YUV420P10;
535
        s->hshift[1] =
536
        s->vshift[1] =
537
        s->hshift[2] =
538
        s->vshift[2] = 1;
539
        s->bps = 10;
540
        break;
541
    default:
542
        avpriv_request_sample(avctx, "Format 0x%X", format);
543
        return AVERROR_PATCHWELCOME;
544
    }
545
14
    s->max = 1 << s->bps;
546
14
    s->magy_decode_slice = s->bps == 8 ? magy_decode_slice : magy_decode_slice10;
547
14
    s->planes = av_pix_fmt_count_planes(avctx->pix_fmt);
548
549
14
    bytestream2_skipu(&gb, 1);
550
14
    s->color_matrix = bytestream2_get_byteu(&gb);
551
14
    s->flags        = bytestream2_get_byteu(&gb);
552
14
    s->interlaced   = !!(s->flags & 2);
553
14
    bytestream2_skipu(&gb, 3);
554
555
14
    width  = bytestream2_get_le32u(&gb);
556
14
    height = bytestream2_get_le32u(&gb);
557
14
    ret = ff_set_dimensions(avctx, width, height);
558
14
    if (ret < 0)
559
        return ret;
560
561
14
    slice_width = bytestream2_get_le32u(&gb);
562
14
    if (slice_width != avctx->coded_width) {
563
        avpriv_request_sample(avctx, "Slice width %"PRIu32, slice_width);
564
        return AVERROR_PATCHWELCOME;
565
    }
566
14
    s->slice_height = bytestream2_get_le32u(&gb);
567

14
    if (s->slice_height <= 0 || s->slice_height > INT_MAX - avctx->coded_height) {
568
        av_log(avctx, AV_LOG_ERROR,
569
               "invalid slice height: %d\n", s->slice_height);
570
        return AVERROR_INVALIDDATA;
571
    }
572
573
14
    bytestream2_skipu(&gb, 4);
574
575
14
    s->nb_slices = (avctx->coded_height + s->slice_height - 1) / s->slice_height;
576
14
    if (s->nb_slices > INT_MAX / FFMAX(sizeof(Slice), 4 * 5)) {
577
        av_log(avctx, AV_LOG_ERROR,
578
               "invalid number of slices: %d\n", s->nb_slices);
579
        return AVERROR_INVALIDDATA;
580
    }
581
582
14
    if (s->interlaced) {
583
6
        if ((s->slice_height >> s->vshift[1]) < 2) {
584
            av_log(avctx, AV_LOG_ERROR, "impossible slice height\n");
585
            return AVERROR_INVALIDDATA;
586
        }
587

6
        if ((avctx->coded_height % s->slice_height) && ((avctx->coded_height % s->slice_height) >> s->vshift[1]) < 2) {
588
            av_log(avctx, AV_LOG_ERROR, "impossible height\n");
589
            return AVERROR_INVALIDDATA;
590
        }
591
    }
592
593
14
    if (bytestream2_get_bytes_left(&gb) <= s->nb_slices * s->planes * 5)
594
        return AVERROR_INVALIDDATA;
595
56
    for (i = 0; i < s->planes; i++) {
596
42
        av_fast_malloc(&s->slices[i], &s->slices_size[i], s->nb_slices * sizeof(Slice));
597
42
        if (!s->slices[i])
598
            return AVERROR(ENOMEM);
599
600
42
        offset = bytestream2_get_le32u(&gb);
601
42
        if (offset >= avpkt->size - header_size)
602
            return AVERROR_INVALIDDATA;
603
604
42
        if (i == 0)
605
14
            first_offset = offset;
606
607
378
        for (j = 0; j < s->nb_slices - 1; j++) {
608
336
            s->slices[i][j].start = offset + header_size;
609
610
336
            next_offset = bytestream2_get_le32u(&gb);
611

336
            if (next_offset <= offset || next_offset >= avpkt->size - header_size)
612
                return AVERROR_INVALIDDATA;
613
614
336
            s->slices[i][j].size = next_offset - offset;
615
336
            if (s->slices[i][j].size < 2)
616
                return AVERROR_INVALIDDATA;
617
336
            offset = next_offset;
618
        }
619
620
42
        s->slices[i][j].start = offset + header_size;
621
42
        s->slices[i][j].size  = avpkt->size - s->slices[i][j].start;
622
623
42
        if (s->slices[i][j].size < 2)
624
            return AVERROR_INVALIDDATA;
625
    }
626
627
14
    if (bytestream2_get_byteu(&gb) != s->planes)
628
        return AVERROR_INVALIDDATA;
629
630
14
    bytestream2_skipu(&gb, s->nb_slices * s->planes);
631
632
14
    table_size = header_size + first_offset - bytestream2_tell(&gb);
633
14
    if (table_size < 2)
634
        return AVERROR_INVALIDDATA;
635
636
14
    ret = build_huffman(avctx, avpkt->data + bytestream2_tell(&gb),
637
                        table_size, s->max);
638
14
    if (ret < 0)
639
        return ret;
640
641
14
    p->pict_type = AV_PICTURE_TYPE_I;
642
14
    p->key_frame = 1;
643
644
14
    if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
645
        return ret;
646
647
14
    s->buf = avpkt->data;
648
14
    s->p = p;
649
14
    avctx->execute2(avctx, s->magy_decode_slice, NULL, NULL, s->nb_slices);
650
651
14
    if (avctx->pix_fmt == AV_PIX_FMT_GBRP   ||
652
12
        avctx->pix_fmt == AV_PIX_FMT_GBRAP  ||
653
10
        avctx->pix_fmt == AV_PIX_FMT_GBRP10 ||
654
10
        avctx->pix_fmt == AV_PIX_FMT_GBRAP10||
655
10
        avctx->pix_fmt == AV_PIX_FMT_GBRAP12||
656
10
        avctx->pix_fmt == AV_PIX_FMT_GBRP12) {
657
4
        FFSWAP(uint8_t*, p->data[0], p->data[1]);
658
4
        FFSWAP(int, p->linesize[0], p->linesize[1]);
659
    } else {
660
10
        switch (s->color_matrix) {
661
        case 1:
662
            p->colorspace = AVCOL_SPC_BT470BG;
663
            break;
664
10
        case 2:
665
10
            p->colorspace = AVCOL_SPC_BT709;
666
10
            break;
667
        }
668
10
        p->color_range = (s->flags & 4) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
669
    }
670
671
14
    *got_frame = 1;
672
673
14
    return avpkt->size;
674
}
675
676
14
static av_cold int magy_decode_init(AVCodecContext *avctx)
677
{
678
14
    MagicYUVContext *s = avctx->priv_data;
679
14
    ff_llviddsp_init(&s->llviddsp);
680
14
    return 0;
681
}
682
683
14
static av_cold int magy_decode_end(AVCodecContext *avctx)
684
{
685
14
    MagicYUVContext * const s = avctx->priv_data;
686
    int i;
687
688
70
    for (i = 0; i < FF_ARRAY_ELEMS(s->slices); i++) {
689
56
        av_freep(&s->slices[i]);
690
56
        s->slices_size[i] = 0;
691
56
        ff_free_vlc(&s->vlc[i]);
692
    }
693
694
14
    return 0;
695
}
696
697
AVCodec ff_magicyuv_decoder = {
698
    .name             = "magicyuv",
699
    .long_name        = NULL_IF_CONFIG_SMALL("MagicYUV video"),
700
    .type             = AVMEDIA_TYPE_VIDEO,
701
    .id               = AV_CODEC_ID_MAGICYUV,
702
    .priv_data_size   = sizeof(MagicYUVContext),
703
    .init             = magy_decode_init,
704
    .close            = magy_decode_end,
705
    .decode           = magy_decode_frame,
706
    .capabilities     = AV_CODEC_CAP_DR1 |
707
                        AV_CODEC_CAP_FRAME_THREADS |
708
                        AV_CODEC_CAP_SLICE_THREADS,
709
    .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE,
710
};