FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/prores_raw.c
Date: 2025-08-19 23:55:23
Exec Total Coverage
Lines: 0 263 0.0%
Functions: 0 9 0.0%
Branches: 0 104 0.0%

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