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 |
|
|
|