Coverage Report

Created: 2026-02-14 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavcodec/prores_raw.c
Line
Count
Source
1
/*
2
 * ProRes RAW decoder
3
 * Copyright (c) 2023-2025 Paul B Mahol
4
 * Copyright (c) 2025 Lynne
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_internal.h"
25
#include "libavutil/mem.h"
26
27
#define CACHED_BITSTREAM_READER !ARCH_X86_32
28
29
#include "config_components.h"
30
#include "avcodec.h"
31
#include "bytestream.h"
32
#include "codec_internal.h"
33
#include "decode.h"
34
#include "get_bits.h"
35
#include "idctdsp.h"
36
#include "proresdata.h"
37
#include "thread.h"
38
#include "hwconfig.h"
39
#include "hwaccel_internal.h"
40
41
#include "prores_raw.h"
42
43
static av_cold int decode_init(AVCodecContext *avctx)
44
2.06k
{
45
2.06k
    ProResRAWContext *s = avctx->priv_data;
46
47
2.06k
    avctx->bits_per_raw_sample = 12;
48
2.06k
    avctx->color_primaries = AVCOL_PRI_UNSPECIFIED;
49
2.06k
    avctx->color_trc = AVCOL_TRC_UNSPECIFIED;
50
2.06k
    avctx->colorspace = AVCOL_SPC_UNSPECIFIED;
51
52
2.06k
    s->pix_fmt = AV_PIX_FMT_NONE;
53
54
2.06k
    ff_blockdsp_init(&s->bdsp);
55
2.06k
    ff_proresdsp_init(&s->prodsp, avctx->bits_per_raw_sample);
56
57
2.06k
    ff_permute_scantable(s->scan, ff_prores_interlaced_scan, s->prodsp.idct_permutation);
58
59
2.06k
    return 0;
60
2.06k
}
61
62
static uint16_t get_value(GetBitContext *gb, int16_t codebook)
63
181k
{
64
181k
    const int16_t switch_bits = codebook >> 8;
65
181k
    const int16_t rice_order  = codebook & 0xf;
66
181k
    const int16_t exp_order   = (codebook >> 4) & 0xf;
67
181k
    int16_t q, bits;
68
69
181k
    uint32_t b = show_bits_long(gb, 32);
70
181k
    if (!b)
71
85.7k
        return 0;
72
96.1k
    q = ff_clz(b);
73
74
96.1k
    if (b & 0x80000000) {
75
12.3k
        skip_bits_long(gb, 1 + rice_order);
76
12.3k
        return (b & 0x7FFFFFFF) >> (31 - rice_order);
77
12.3k
    }
78
79
83.7k
    if (q <= switch_bits) {
80
2.77k
        skip_bits_long(gb, 1 + rice_order + q);
81
2.77k
        return (q << rice_order) +
82
2.77k
                (((b << (q + 1)) >> 1) >> (31 - rice_order));
83
2.77k
    }
84
85
80.9k
    bits = exp_order + (q << 1) - switch_bits;
86
80.9k
    if (bits > 32)
87
63.6k
        return 0; // we do not return a negative error code so that we dont produce out of range values on errors
88
17.3k
    skip_bits_long(gb, bits);
89
17.3k
    return (b >> (32 - bits)) +
90
17.3k
           ((switch_bits + 1) << rice_order) -
91
17.3k
           (1 << exp_order);
92
80.9k
}
93
94
7.85k
#define TODCCODEBOOK(x) ((x + 1) >> 1)
95
96
#define DC_CB_MAX 12
97
const uint8_t ff_prores_raw_dc_cb[DC_CB_MAX + 1] = {
98
    0x010, 0x021, 0x032, 0x033, 0x033, 0x033, 0x044, 0x044, 0x044, 0x044, 0x044, 0x044, 0x076,
99
};
100
101
#define AC_CB_MAX 94
102
const int16_t ff_prores_raw_ac_cb[AC_CB_MAX + 1] = {
103
    0x000, 0x211, 0x111, 0x111, 0x222, 0x222, 0x222, 0x122, 0x122, 0x122,
104
    0x233, 0x233, 0x233, 0x233, 0x233, 0x233, 0x233, 0x233, 0x133, 0x133,
105
    0x244, 0x244, 0x244, 0x244, 0x244, 0x244, 0x244, 0x244, 0x244, 0x244, 0x244,
106
    0x244, 0x244, 0x244, 0x244, 0x244, 0x244, 0x244, 0x244, 0x244, 0x244, 0x244,
107
    0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355,
108
    0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355,
109
    0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355,
110
    0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x355, 0x166,
111
};
112
113
#define RN_CB_MAX 27
114
const int16_t ff_prores_raw_rn_cb[RN_CB_MAX + 1] = {
115
    0x200, 0x100, 0x000, 0x000, 0x211, 0x211, 0x111, 0x111, 0x011, 0x011, 0x021, 0x021, 0x222, 0x022,
116
    0x022, 0x022, 0x022, 0x022, 0x022, 0x022, 0x022, 0x022, 0x022, 0x022, 0x022, 0x032, 0x032, 0x044
117
};
118
119
#define LN_CB_MAX 14
120
const int16_t ff_prores_raw_ln_cb[LN_CB_MAX + 1] = {
121
    0x100, 0x111, 0x222, 0x222, 0x122, 0x122, 0x433, 0x433, 0x233, 0x233, 0x233, 0x233, 0x233, 0x233, 0x033,
122
};
123
124
static int decode_comp(AVCodecContext *avctx, TileContext *tile,
125
                       AVFrame *frame, const uint8_t *data, int size,
126
                       int component, int16_t *qmat)
127
36.6k
{
128
36.6k
    int ret;
129
36.6k
    ProResRAWContext *s = avctx->priv_data;
130
36.6k
    const ptrdiff_t linesize = frame->linesize[0] >> 1;
131
36.6k
    uint16_t *dst = (uint16_t *)(frame->data[0] + tile->y*frame->linesize[0] + 2*tile->x);
132
133
36.6k
    int idx;
134
36.6k
    const int w = FFMIN(s->tw, avctx->width - tile->x) / 2;
135
36.6k
    const int nb_blocks = w / 8;
136
36.6k
    const int log2_nb_blocks = 31 - ff_clz(nb_blocks);
137
36.6k
    const int block_mask = (1 << log2_nb_blocks) - 1;
138
36.6k
    const int nb_codes = 64 * nb_blocks;
139
140
36.6k
    LOCAL_ALIGNED_32(int16_t, block, [64*16]);
141
142
36.6k
    int16_t sign = 0;
143
36.6k
    int16_t dc_add = 0;
144
36.6k
    int16_t dc_codebook;
145
146
36.6k
    uint16_t ac, rn, ln;
147
36.6k
    int16_t ac_codebook = 49;
148
36.6k
    int16_t rn_codebook = 0;
149
36.6k
    int16_t ln_codebook = 66;
150
151
36.6k
    const uint8_t *scan = s->scan;
152
36.6k
    GetBitContext gb;
153
154
36.6k
    if (component > 1)
155
18.3k
        dst += linesize;
156
36.6k
    dst += component & 1;
157
158
36.6k
    if ((ret = init_get_bits8(&gb, data, size)) < 0)
159
0
        return ret;
160
161
100k
    for (int n = 0; n < nb_blocks; n++)
162
63.7k
        s->bdsp.clear_block(block + n*64);
163
164
    /* Special handling for first block */
165
36.6k
    int dc = get_value(&gb, 700);
166
36.6k
    int prev_dc = (dc >> 1) ^ -(dc & 1);
167
36.6k
    block[0] = (((dc&1) + (dc>>1) ^ -(int)(dc & 1)) + (dc & 1)) + 1;
168
169
44.4k
    for (int n = 1; n < nb_blocks; n++) {
170
27.2k
        if (get_bits_left(&gb) <= 0)
171
19.3k
            break;
172
173
7.85k
        if ((n & 15) == 1)
174
7.40k
            dc_codebook = 100;
175
451
        else
176
451
            dc_codebook = ff_prores_raw_dc_cb[FFMIN(TODCCODEBOOK(dc), DC_CB_MAX)];
177
178
7.85k
        dc = get_value(&gb, dc_codebook);
179
180
7.85k
        sign = sign ^ dc & 1;
181
7.85k
        dc_add = (-sign ^ TODCCODEBOOK(dc)) + sign;
182
7.85k
        sign = dc_add < 0;
183
7.85k
        prev_dc += dc_add;
184
185
7.85k
        block[n*64] = prev_dc + 1;
186
7.85k
    }
187
188
76.7k
    for (int n = nb_blocks; n <= nb_codes;) {
189
76.7k
        if (get_bits_left(&gb) <= 0)
190
30.7k
            break;
191
192
45.9k
        ln = get_value(&gb, ln_codebook);
193
194
53.5k
        for (int i = 0; i < ln; i++) {
195
10.5k
            if (get_bits_left(&gb) <= 0)
196
2.65k
                break;
197
198
7.93k
            if ((n + i) >= nb_codes)
199
289
                break;
200
201
7.64k
            ac = get_value(&gb, ac_codebook);
202
7.64k
            ac_codebook = ff_prores_raw_ac_cb[FFMIN(ac, AC_CB_MAX)];
203
7.64k
            sign = -get_bits1(&gb);
204
205
7.64k
            idx = scan[(n + i) >> log2_nb_blocks] + (((n + i) & block_mask) << 6);
206
7.64k
            block[idx] = ((ac + 1) ^ sign) - sign;
207
7.64k
        }
208
209
45.9k
        n += ln;
210
45.9k
        if (n >= nb_codes)
211
2.23k
            break;
212
213
43.7k
        rn = get_value(&gb, rn_codebook);
214
43.7k
        rn_codebook = ff_prores_raw_rn_cb[FFMIN(rn, RN_CB_MAX)];
215
216
43.7k
        n += rn + 1;
217
43.7k
        if (n >= nb_codes)
218
2.42k
            break;
219
220
41.2k
        if (get_bits_left(&gb) <= 0)
221
1.15k
            break;
222
223
40.1k
        ac = get_value(&gb, ac_codebook);
224
40.1k
        sign = -get_bits1(&gb);
225
226
40.1k
        idx = scan[n >> log2_nb_blocks] + ((n & block_mask) << 6);
227
40.1k
        block[idx] = ((ac + 1) ^ sign) - sign;
228
229
40.1k
        ac_codebook = ff_prores_raw_ac_cb[FFMIN(ac, AC_CB_MAX)];
230
40.1k
        ln_codebook = ff_prores_raw_ln_cb[FFMIN(ac, LN_CB_MAX)];
231
232
40.1k
        n++;
233
40.1k
    }
234
235
100k
    for (int n = 0; n < nb_blocks; n++) {
236
63.7k
        uint16_t *ptr = dst + n*16;
237
63.7k
        s->prodsp.idct_put_bayer(ptr, linesize, block + n*64, qmat);
238
63.7k
    }
239
240
36.6k
    return 0;
241
36.6k
}
242
243
static int decode_tile(AVCodecContext *avctx, TileContext *tile,
244
                       AVFrame *frame)
245
20.0k
{
246
20.0k
    int ret;
247
20.0k
    ProResRAWContext *s = avctx->priv_data;
248
249
20.0k
    GetByteContext *gb = &tile->gb;
250
20.0k
    LOCAL_ALIGNED_32(int16_t, qmat, [64]);
251
252
20.0k
    if (tile->x >= avctx->width)
253
10.1k
        return 0;
254
255
    /* Tile header */
256
9.87k
    int header_len = bytestream2_get_byteu(gb) >> 3;
257
9.87k
    int16_t scale = bytestream2_get_byteu(gb);
258
259
9.87k
    int size[4];
260
9.87k
    size[0] = bytestream2_get_be16(gb);
261
9.87k
    size[1] = bytestream2_get_be16(gb);
262
9.87k
    size[2] = bytestream2_get_be16(gb);
263
9.87k
    size[3] = bytestream2_size(gb) - size[0] - size[1] - size[2] - header_len;
264
9.87k
    if (size[3] < 0)
265
723
        return AVERROR_INVALIDDATA;
266
267
595k
    for (int i = 0; i < 64; i++)
268
585k
        qmat[i] = s->qmat[i] * scale >> 1;
269
270
9.15k
    const uint8_t *comp_start = gb->buffer_start + header_len;
271
272
9.15k
    ret = decode_comp(avctx, tile, frame, comp_start,
273
9.15k
                      size[0], 2, qmat);
274
9.15k
    if (ret < 0)
275
0
        goto fail;
276
277
9.15k
    ret = decode_comp(avctx, tile, frame, comp_start + size[0],
278
9.15k
                      size[1], 1, qmat);
279
9.15k
    if (ret < 0)
280
0
        goto fail;
281
282
9.15k
    ret = decode_comp(avctx, tile, frame, comp_start + size[0] + size[1],
283
9.15k
                      size[2], 3, qmat);
284
9.15k
    if (ret < 0)
285
0
        goto fail;
286
287
9.15k
    ret = decode_comp(avctx, tile, frame, comp_start + size[0] + size[1] + size[2],
288
9.15k
                      size[3], 0, qmat);
289
9.15k
    if (ret < 0)
290
0
        goto fail;
291
292
9.15k
    return 0;
293
0
fail:
294
0
    av_log(avctx, AV_LOG_ERROR, "tile %d/%d decoding error\n", tile->x, tile->y);
295
0
    return ret;
296
9.15k
}
297
298
static int decode_tiles(AVCodecContext *avctx, void *arg,
299
                        int n, int thread_nb)
300
20.0k
{
301
20.0k
    ProResRAWContext *s = avctx->priv_data;
302
20.0k
    TileContext *tile = &s->tiles[n];
303
20.0k
    AVFrame *frame = arg;
304
305
20.0k
    return decode_tile(avctx, tile, frame);
306
20.0k
}
307
308
static enum AVPixelFormat get_pixel_format(AVCodecContext *avctx,
309
                                           enum AVPixelFormat pix_fmt)
310
1.86k
{
311
1.86k
    enum AVPixelFormat pix_fmts[] = {
312
#if CONFIG_PRORES_RAW_VULKAN_HWACCEL
313
        AV_PIX_FMT_VULKAN,
314
#endif
315
1.86k
        pix_fmt,
316
1.86k
        AV_PIX_FMT_NONE,
317
1.86k
    };
318
319
1.86k
    return ff_get_format(avctx, pix_fmts);
320
1.86k
}
321
322
static int decode_frame(AVCodecContext *avctx,
323
                        AVFrame *frame, int *got_frame_ptr,
324
                        AVPacket *avpkt)
325
186k
{
326
186k
    ProResRAWContext *s = avctx->priv_data;
327
186k
    int ret, dimensions_changed = 0, old_version = s->version;
328
186k
    DECLARE_ALIGNED(32, uint8_t, qmat)[64];
329
186k
    memset(qmat, 1, 64);
330
331
186k
    if (avctx->skip_frame >= AVDISCARD_ALL)
332
103k
        return avpkt->size;
333
334
82.7k
    switch (avctx->codec_tag) {
335
35.6k
    case 0:
336
35.6k
        break;
337
231
    case MKTAG('a','p','r','n'):
338
231
        avctx->profile = AV_PROFILE_PRORES_RAW;
339
231
        break;
340
209
    case MKTAG('a','p','r','h'):
341
209
        avctx->profile = AV_PROFILE_PRORES_RAW_HQ;
342
209
        break;
343
46.7k
    default:
344
46.7k
        avpriv_request_sample(avctx, "Profile %d", avctx->codec_tag);
345
46.7k
        return AVERROR_PATCHWELCOME;
346
0
        break;
347
82.7k
    }
348
349
36.0k
    GetByteContext gb;
350
36.0k
    bytestream2_init(&gb, avpkt->data, avpkt->size);
351
36.0k
    if (bytestream2_get_be32(&gb) != avpkt->size)
352
18.6k
        return AVERROR_INVALIDDATA;
353
354
    /* ProRes RAW frame */
355
17.3k
    if (bytestream2_get_be32(&gb) != MKBETAG('p','r','r','f'))
356
2.59k
        return AVERROR_INVALIDDATA;
357
358
14.7k
    int header_len = bytestream2_get_be16(&gb);
359
14.7k
    if (header_len < 62 || bytestream2_get_bytes_left(&gb) < header_len - 2)
360
1.60k
        return AVERROR_INVALIDDATA;
361
362
13.1k
    GetByteContext gb_hdr;
363
13.1k
    bytestream2_init(&gb_hdr, gb.buffer, header_len - 2);
364
13.1k
    bytestream2_skip(&gb, header_len - 2);
365
366
13.1k
    bytestream2_skip(&gb_hdr, 1);
367
13.1k
    s->version = bytestream2_get_byte(&gb_hdr);
368
13.1k
    if (s->version > 1) {
369
240
        avpriv_request_sample(avctx, "Version %d", s->version);
370
240
        return AVERROR_PATCHWELCOME;
371
240
    }
372
373
    /* Vendor header (e.g. "peac" for Panasonic or "atm0" for Atmos) */
374
12.9k
    bytestream2_skip(&gb_hdr, 4);
375
376
    /* Width and height must always be even */
377
12.9k
    int w = bytestream2_get_be16(&gb_hdr);
378
12.9k
    int h = bytestream2_get_be16(&gb_hdr);
379
12.9k
    if ((w & 1) || (h & 1))
380
451
        return AVERROR_INVALIDDATA;
381
382
12.5k
    if (w != avctx->width || h != avctx->height) {
383
2.39k
        av_log(avctx, AV_LOG_WARNING, "picture resolution change: %ix%i -> %ix%i\n",
384
2.39k
               avctx->width, avctx->height, w, h);
385
2.39k
        if ((ret = ff_set_dimensions(avctx, w, h)) < 0)
386
741
            return ret;
387
1.65k
        dimensions_changed = 1;
388
1.65k
    }
389
390
11.7k
    avctx->coded_width  = FFALIGN(w, 16);
391
11.7k
    avctx->coded_height = FFALIGN(h, 16);
392
393
11.7k
    enum AVPixelFormat pix_fmt = AV_PIX_FMT_BAYER_RGGB16;
394
11.7k
    if (pix_fmt != s->pix_fmt || dimensions_changed ||
395
10.0k
        s->version != old_version) {
396
1.86k
        s->pix_fmt = pix_fmt;
397
398
1.86k
        ret = get_pixel_format(avctx, pix_fmt);
399
1.86k
        if (ret < 0)
400
0
            return ret;
401
402
1.86k
        avctx->pix_fmt = ret;
403
1.86k
    }
404
405
11.7k
    bytestream2_skip(&gb_hdr, 1 * 4);
406
11.7k
    bytestream2_skip(&gb_hdr, 2); /* & 0x3 */
407
11.7k
    bytestream2_skip(&gb_hdr, 2);
408
11.7k
    bytestream2_skip(&gb_hdr, 4);
409
11.7k
    bytestream2_skip(&gb_hdr, 4);
410
11.7k
    bytestream2_skip(&gb_hdr, 4 * 3 * 3);
411
11.7k
    bytestream2_skip(&gb_hdr, 4);
412
11.7k
    bytestream2_skip(&gb_hdr, 2);
413
414
    /* Flags */
415
11.7k
    int flags = bytestream2_get_be16(&gb_hdr);
416
11.7k
    int align = (flags >> 1) & 0x7;
417
418
    /* Quantization matrix */
419
11.7k
    if (flags & 1)
420
419
        bytestream2_get_buffer(&gb_hdr, qmat, 64);
421
422
11.7k
    if ((flags >> 4) & 1) {
423
383
        bytestream2_skip(&gb_hdr, 2);
424
383
        bytestream2_skip(&gb_hdr, 2 * 7);
425
383
    }
426
427
11.7k
    ff_permute_scantable(s->qmat, s->prodsp.idct_permutation, qmat);
428
429
11.7k
    s->nb_tw = (w + 15) >> 4;
430
11.7k
    s->nb_th = (h + 15) >> 4;
431
11.7k
    s->nb_tw = (s->nb_tw >> align) + av_popcount(~(-1 * (1 << align)) & s->nb_tw);
432
11.7k
    s->nb_tiles = s->nb_tw * s->nb_th;
433
11.7k
    av_log(avctx, AV_LOG_DEBUG, "%dx%d | nb_tiles: %d\n", s->nb_tw, s->nb_th, s->nb_tiles);
434
435
11.7k
    s->tw = s->version == 0 ? 128 : 256;
436
11.7k
    s->th = 16;
437
11.7k
    av_log(avctx, AV_LOG_DEBUG, "tile_size: %dx%d\n", s->tw, s->th);
438
439
11.7k
    av_fast_mallocz(&s->tiles, &s->tiles_size, s->nb_tiles * sizeof(*s->tiles));
440
11.7k
    if (!s->tiles)
441
371
        return AVERROR(ENOMEM);
442
443
11.3k
    if (bytestream2_get_bytes_left(&gb) < s->nb_tiles * 2)
444
497
        return AVERROR_INVALIDDATA;
445
446
    /* Read tile data offsets */
447
10.8k
    int offset = bytestream2_tell(&gb) + s->nb_tiles * 2;
448
31.2k
    for (int n = 0; n < s->nb_tiles; n++) {
449
21.4k
        TileContext *tile = &s->tiles[n];
450
451
21.4k
        int size = bytestream2_get_be16(&gb);
452
21.4k
        if (offset >= avpkt->size)
453
623
            return AVERROR_INVALIDDATA;
454
20.8k
        if (size >= avpkt->size)
455
299
            return AVERROR_INVALIDDATA;
456
20.5k
        if (offset > avpkt->size - size)
457
227
            return AVERROR_INVALIDDATA;
458
459
20.3k
        bytestream2_init(&tile->gb, avpkt->data + offset, size);
460
461
20.3k
        tile->y = (n / s->nb_tw) * s->th;
462
20.3k
        tile->x = (n % s->nb_tw) * s->tw;
463
464
20.3k
        offset += size;
465
20.3k
    }
466
467
9.74k
    ret = ff_thread_get_buffer(avctx, frame, 0);
468
9.74k
    if (ret < 0)
469
244
        return ret;
470
471
9.49k
    s->frame = frame;
472
473
    /* Start */
474
9.49k
    if (avctx->hwaccel) {
475
0
        const FFHWAccel *hwaccel = ffhwaccel(avctx->hwaccel);
476
477
0
        ret = ff_hwaccel_frame_priv_alloc(avctx, &s->hwaccel_picture_private);
478
0
        if (ret < 0)
479
0
            return ret;
480
481
0
        ret = hwaccel->start_frame(avctx, avpkt->buf, avpkt->data, avpkt->size);
482
0
        if (ret < 0)
483
0
            return ret;
484
485
0
        for (int n = 0; n < s->nb_tiles; n++) {
486
0
            TileContext *tile = &s->tiles[n];
487
0
            ret = hwaccel->decode_slice(avctx, tile->gb.buffer,
488
0
                                        tile->gb.buffer_end - tile->gb.buffer);
489
0
            if (ret < 0)
490
0
                return ret;
491
0
        }
492
493
0
        ret = hwaccel->end_frame(avctx);
494
0
        if (ret < 0)
495
0
            return ret;
496
497
0
        av_refstruct_unref(&s->hwaccel_picture_private);
498
9.49k
    } else {
499
9.49k
        avctx->execute2(avctx, decode_tiles, frame, NULL, s->nb_tiles);
500
9.49k
    }
501
502
9.49k
    frame->pict_type = AV_PICTURE_TYPE_I;
503
9.49k
    frame->flags    |= AV_FRAME_FLAG_KEY;
504
505
9.49k
    *got_frame_ptr = 1;
506
507
9.49k
    return avpkt->size;
508
9.49k
}
509
510
static av_cold int decode_end(AVCodecContext *avctx)
511
2.06k
{
512
2.06k
    ProResRAWContext *s = avctx->priv_data;
513
2.06k
    av_refstruct_unref(&s->hwaccel_picture_private);
514
2.06k
    av_freep(&s->tiles);
515
2.06k
    return 0;
516
2.06k
}
517
518
#if HAVE_THREADS
519
static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
520
0
{
521
0
    ProResRAWContext *rsrc = src->priv_data;
522
0
    ProResRAWContext *rdst = dst->priv_data;
523
524
0
    rdst->pix_fmt = rsrc->pix_fmt;
525
0
    rdst->version = rsrc->version;
526
527
0
    return 0;
528
0
}
529
#endif
530
531
const FFCodec ff_prores_raw_decoder = {
532
    .p.name           = "prores_raw",
533
    CODEC_LONG_NAME("Apple ProRes RAW"),
534
    .p.type           = AVMEDIA_TYPE_VIDEO,
535
    .p.id             = AV_CODEC_ID_PRORES_RAW,
536
    .priv_data_size   = sizeof(ProResRAWContext),
537
    .init             = decode_init,
538
    .close            = decode_end,
539
    FF_CODEC_DECODE_CB(decode_frame),
540
    UPDATE_THREAD_CONTEXT(update_thread_context),
541
    .p.capabilities   = AV_CODEC_CAP_DR1 |
542
                        AV_CODEC_CAP_FRAME_THREADS |
543
                        AV_CODEC_CAP_SLICE_THREADS,
544
    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP |
545
                      FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
546
    .hw_configs     = (const AVCodecHWConfigInternal *const []) {
547
#if CONFIG_PRORES_RAW_VULKAN_HWACCEL
548
        HWACCEL_VULKAN(prores_raw),
549
#endif
550
        NULL
551
    },
552
};