/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 | | }; |