FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/proresenc_anatoliy.c
Date: 2026-09-28 11:37:26
Exec Total Coverage
Lines: 347 450 77.1%
Functions: 17 21 81.0%
Branches: 142 204 69.6%

Line Branch Exec Source
1 /*
2 * Apple ProRes encoder
3 *
4 * Copyright (c) 2011 Anatoliy Wasserman
5 * Copyright (c) 2012 Konstantin Shishkov
6 *
7 * This file is part of FFmpeg.
8 *
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 /**
25 * @file
26 * Apple ProRes encoder (Anatoliy Wasserman version)
27 * Known FOURCCs: 'ap4h' (444), 'apch' (HQ), 'apcn' (422), 'apcs' (LT), 'acpo' (Proxy)
28 */
29
30 #include "libavutil/avassert.h"
31 #include "libavutil/mem.h"
32 #include "libavutil/mem_internal.h"
33 #include "libavutil/opt.h"
34 #include "avcodec.h"
35 #include "codec_internal.h"
36 #include "encode.h"
37 #include "profiles.h"
38 #include "proresdata.h"
39 #include "put_bits.h"
40 #include "bytestream.h"
41 #include "fdctdsp.h"
42
43 #define DEFAULT_SLICE_MB_WIDTH 8
44
45 static const AVProfile profiles[] = {
46 { AV_PROFILE_PRORES_PROXY, "apco"},
47 { AV_PROFILE_PRORES_LT, "apcs"},
48 { AV_PROFILE_PRORES_STANDARD, "apcn"},
49 { AV_PROFILE_PRORES_HQ, "apch"},
50 { AV_PROFILE_PRORES_4444, "ap4h"},
51 { AV_PROFILE_PRORES_XQ, "ap4x"},
52 { AV_PROFILE_UNKNOWN }
53 };
54
55 static const int qp_start_table[] = { 8, 3, 2, 1, 1, 1};
56 static const int qp_end_table[] = { 13, 9, 6, 6, 5, 4};
57 static const int bitrate_table[] = { 1000, 2100, 3500, 5400, 7000, 10000};
58
59 static const int valid_primaries[] = { AVCOL_PRI_RESERVED0, AVCOL_PRI_BT709, AVCOL_PRI_UNSPECIFIED, AVCOL_PRI_BT470BG,
60 AVCOL_PRI_SMPTE170M, AVCOL_PRI_BT2020, AVCOL_PRI_SMPTE431, AVCOL_PRI_SMPTE432, INT_MAX };
61 static const int valid_trc[] = { AVCOL_TRC_RESERVED0, AVCOL_TRC_BT709, AVCOL_TRC_UNSPECIFIED, AVCOL_TRC_SMPTE2084,
62 AVCOL_TRC_ARIB_STD_B67, INT_MAX };
63 static const int valid_colorspace[] = { AVCOL_SPC_BT709, AVCOL_SPC_UNSPECIFIED, AVCOL_SPC_SMPTE170M,
64 AVCOL_SPC_BT2020_NCL, INT_MAX };
65
66 static const uint8_t QMAT_LUMA[6][64] = {
67 {
68 4, 7, 9, 11, 13, 14, 15, 63,
69 7, 7, 11, 12, 14, 15, 63, 63,
70 9, 11, 13, 14, 15, 63, 63, 63,
71 11, 11, 13, 14, 63, 63, 63, 63,
72 11, 13, 14, 63, 63, 63, 63, 63,
73 13, 14, 63, 63, 63, 63, 63, 63,
74 13, 63, 63, 63, 63, 63, 63, 63,
75 63, 63, 63, 63, 63, 63, 63, 63
76 }, {
77 4, 5, 6, 7, 9, 11, 13, 15,
78 5, 5, 7, 8, 11, 13, 15, 17,
79 6, 7, 9, 11, 13, 15, 15, 17,
80 7, 7, 9, 11, 13, 15, 17, 19,
81 7, 9, 11, 13, 14, 16, 19, 23,
82 9, 11, 13, 14, 16, 19, 23, 29,
83 9, 11, 13, 15, 17, 21, 28, 35,
84 11, 13, 16, 17, 21, 28, 35, 41
85 }, {
86 4, 4, 5, 5, 6, 7, 7, 9,
87 4, 4, 5, 6, 7, 7, 9, 9,
88 5, 5, 6, 7, 7, 9, 9, 10,
89 5, 5, 6, 7, 7, 9, 9, 10,
90 5, 6, 7, 7, 8, 9, 10, 12,
91 6, 7, 7, 8, 9, 10, 12, 15,
92 6, 7, 7, 9, 10, 11, 14, 17,
93 7, 7, 9, 10, 11, 14, 17, 21
94 }, {
95 4, 4, 4, 4, 4, 4, 4, 4,
96 4, 4, 4, 4, 4, 4, 4, 4,
97 4, 4, 4, 4, 4, 4, 4, 4,
98 4, 4, 4, 4, 4, 4, 4, 5,
99 4, 4, 4, 4, 4, 4, 5, 5,
100 4, 4, 4, 4, 4, 5, 5, 6,
101 4, 4, 4, 4, 5, 5, 6, 7,
102 4, 4, 4, 4, 5, 6, 7, 7
103 }, { /* 444 */
104 4, 4, 4, 4, 4, 4, 4, 4,
105 4, 4, 4, 4, 4, 4, 4, 4,
106 4, 4, 4, 4, 4, 4, 4, 4,
107 4, 4, 4, 4, 4, 4, 4, 5,
108 4, 4, 4, 4, 4, 4, 5, 5,
109 4, 4, 4, 4, 4, 5, 5, 6,
110 4, 4, 4, 4, 5, 5, 6, 7,
111 4, 4, 4, 4, 5, 6, 7, 7
112 }, { /* 444 XQ */
113 2, 2, 2, 2, 2, 2, 2, 2,
114 2, 2, 2, 2, 2, 2, 2, 2,
115 2, 2, 2, 2, 2, 2, 2, 2,
116 2, 2, 2, 2, 2, 2, 2, 3,
117 2, 2, 2, 2, 2, 2, 3, 3,
118 2, 2, 2, 2, 2, 3, 3, 3,
119 2, 2, 2, 2, 3, 3, 3, 4,
120 2, 2, 2, 2, 3, 3, 4, 4,
121 }
122 };
123
124 static const uint8_t QMAT_CHROMA[6][64] = {
125 {
126 4, 7, 9, 11, 13, 14, 63, 63,
127 7, 7, 11, 12, 14, 63, 63, 63,
128 9, 11, 13, 14, 63, 63, 63, 63,
129 11, 11, 13, 14, 63, 63, 63, 63,
130 11, 13, 14, 63, 63, 63, 63, 63,
131 13, 14, 63, 63, 63, 63, 63, 63,
132 13, 63, 63, 63, 63, 63, 63, 63,
133 63, 63, 63, 63, 63, 63, 63, 63
134 }, {
135 4, 5, 6, 7, 9, 11, 13, 15,
136 5, 5, 7, 8, 11, 13, 15, 17,
137 6, 7, 9, 11, 13, 15, 15, 17,
138 7, 7, 9, 11, 13, 15, 17, 19,
139 7, 9, 11, 13, 14, 16, 19, 23,
140 9, 11, 13, 14, 16, 19, 23, 29,
141 9, 11, 13, 15, 17, 21, 28, 35,
142 11, 13, 16, 17, 21, 28, 35, 41
143 }, {
144 4, 4, 5, 5, 6, 7, 7, 9,
145 4, 4, 5, 6, 7, 7, 9, 9,
146 5, 5, 6, 7, 7, 9, 9, 10,
147 5, 5, 6, 7, 7, 9, 9, 10,
148 5, 6, 7, 7, 8, 9, 10, 12,
149 6, 7, 7, 8, 9, 10, 12, 15,
150 6, 7, 7, 9, 10, 11, 14, 17,
151 7, 7, 9, 10, 11, 14, 17, 21
152 }, {
153 4, 4, 4, 4, 4, 4, 4, 4,
154 4, 4, 4, 4, 4, 4, 4, 4,
155 4, 4, 4, 4, 4, 4, 4, 4,
156 4, 4, 4, 4, 4, 4, 4, 5,
157 4, 4, 4, 4, 4, 4, 5, 5,
158 4, 4, 4, 4, 4, 5, 5, 6,
159 4, 4, 4, 4, 5, 5, 6, 7,
160 4, 4, 4, 4, 5, 6, 7, 7
161 }, { /* 444 */
162 4, 4, 4, 4, 4, 4, 4, 4,
163 4, 4, 4, 4, 4, 4, 4, 4,
164 4, 4, 4, 4, 4, 4, 4, 4,
165 4, 4, 4, 4, 4, 4, 4, 5,
166 4, 4, 4, 4, 4, 4, 5, 5,
167 4, 4, 4, 4, 4, 5, 5, 6,
168 4, 4, 4, 4, 5, 5, 6, 7,
169 4, 4, 4, 4, 5, 6, 7, 7
170 }, { /* 444 xq */
171 4, 4, 4, 4, 4, 4, 4, 4,
172 4, 4, 4, 4, 4, 4, 4, 4,
173 4, 4, 4, 4, 4, 4, 4, 4,
174 4, 4, 4, 4, 4, 4, 4, 5,
175 4, 4, 4, 4, 4, 4, 5, 5,
176 4, 4, 4, 4, 4, 5, 5, 6,
177 4, 4, 4, 4, 5, 5, 6, 7,
178 4, 4, 4, 4, 5, 6, 7, 7
179 }
180 };
181
182
183 typedef struct {
184 AVClass *class;
185 FDCTDSPContext fdsp;
186 uint8_t* fill_y;
187 uint8_t* fill_u;
188 uint8_t* fill_v;
189 uint8_t* fill_a;
190
191 int qmat_luma[16][64];
192 int qmat_chroma[16][64];
193 const uint8_t *scantable;
194
195 int is_422;
196 int need_alpha;
197 int is_interlaced;
198
199 char *vendor;
200 } ProresContext;
201
202 /**
203 * Check if a value is in the list. If not, return the default value
204 *
205 * @param ctx Context for the log msg
206 * @param val_name Name of the checked value, for log msg
207 * @param array_valid_values Array of valid int, ended with INT_MAX
208 * @param default_value Value return if checked value is not in the array
209 * @return Value or default_value.
210 */
211 2400 static int int_from_list_or_default(void *ctx, const char *val_name, int val,
212 const int *array_valid_values, int default_value)
213 {
214 2400 int i = 0;
215
216 4000 while (1) {
217 6400 int ref_val = array_valid_values[i];
218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6400 times.
6400 if (ref_val == INT_MAX)
219 ✗ break;
220
2/2
✓ Branch 0 taken 2400 times.
✓ Branch 1 taken 4000 times.
6400 if (val == ref_val)
221 2400 return val;
222 4000 i++;
223 }
224 /* val is not a valid value */
225 ✗ av_log(ctx, AV_LOG_DEBUG,
226 "%s %d are not supported. Set to default value : %d\n",
227 val_name, val, default_value);
228 ✗ return default_value;
229 }
230
231 182338360 static void encode_vlc_codeword(PutBitContext *pb, unsigned codebook, int val)
232 {
233 unsigned int rice_order, exp_order, switch_bits, switch_val;
234 int exponent;
235
236 /* number of prefix bits to switch between Rice and expGolomb */
237 182338360 switch_bits = (codebook & 3) + 1;
238 182338360 rice_order = codebook >> 5; /* rice code order */
239 182338360 exp_order = (codebook >> 2) & 7; /* exp golomb code order */
240
241 182338360 switch_val = switch_bits << rice_order;
242
243
2/2
✓ Branch 0 taken 60600805 times.
✓ Branch 1 taken 121737555 times.
182338360 if (val >= switch_val) {
244 60600805 val -= switch_val - (1 << exp_order);
245 60600805 exponent = av_log2(val);
246
247 60600805 put_bits(pb, exponent - exp_order + switch_bits, 0);
248 60600805 put_bits(pb, exponent + 1, val);
249 } else {
250 121737555 exponent = val >> rice_order;
251
252
2/2
✓ Branch 0 taken 27389069 times.
✓ Branch 1 taken 94348486 times.
121737555 if (exponent)
253 27389069 put_bits(pb, exponent, 0);
254 121737555 put_bits(pb, 1, 1);
255
2/2
✓ Branch 0 taken 12633930 times.
✓ Branch 1 taken 109103625 times.
121737555 if (rice_order)
256 12633930 put_sbits(pb, rice_order, val);
257 }
258 182338360 }
259
260 #define GET_SIGN(x) ((x) >> 31)
261 #define MAKE_CODE(x) (((x) * 2) ^ GET_SIGN(x))
262
263 174174 static void encode_dcs(PutBitContext *pb, int16_t *blocks,
264 int blocks_per_slice, int scale)
265 {
266 int i;
267 174174 int codebook = 5, code, dc, prev_dc, delta, sign, new_sign;
268
269 174174 prev_dc = (blocks[0] - 0x4000) / scale;
270 174174 encode_vlc_codeword(pb, FIRST_DC_CB, MAKE_CODE(prev_dc));
271 174174 sign = 0;
272 174174 blocks += 64;
273
274
2/2
✓ Branch 0 taken 2975050 times.
✓ Branch 1 taken 174174 times.
3149224 for (i = 1; i < blocks_per_slice; i++, blocks += 64) {
275 2975050 dc = (blocks[0] - 0x4000) / scale;
276 2975050 delta = dc - prev_dc;
277 2975050 new_sign = GET_SIGN(delta);
278 2975050 delta = (delta ^ sign) - sign;
279 2975050 code = MAKE_CODE(delta);
280 2975050 encode_vlc_codeword(pb, ff_prores_dc_codebook[codebook], code);
281 2975050 codebook = FFMIN(code, 6);
282 2975050 sign = new_sign;
283 2975050 prev_dc = dc;
284 }
285 174174 }
286
287 174174 static void encode_acs(PutBitContext *pb, int16_t *blocks,
288 int blocks_per_slice,
289 int *qmat, const uint8_t *scan)
290 {
291 int idx, i;
292 174174 int prev_run = 4;
293 174174 int prev_level = 2;
294 174174 int run = 0, level;
295 int max_coeffs, abs_level;
296
297 174174 max_coeffs = blocks_per_slice << 6;
298
299
2/2
✓ Branch 0 taken 10972962 times.
✓ Branch 1 taken 174174 times.
11147136 for (i = 1; i < 64; i++) {
300
2/2
✓ Branch 0 taken 198401112 times.
✓ Branch 1 taken 10972962 times.
209374074 for (idx = scan[i]; idx < max_coeffs; idx += 64) {
301 198401112 level = blocks[idx] / qmat[scan[i]];
302
2/2
✓ Branch 0 taken 89594568 times.
✓ Branch 1 taken 108806544 times.
198401112 if (level) {
303 89594568 abs_level = FFABS(level);
304 89594568 encode_vlc_codeword(pb, ff_prores_run_to_cb[prev_run], run);
305 89594568 encode_vlc_codeword(pb, ff_prores_level_to_cb[prev_level], abs_level - 1);
306 89594568 put_sbits(pb, 1, GET_SIGN(level));
307
308 89594568 prev_run = FFMIN(run, 15);
309 89594568 prev_level = FFMIN(abs_level, 9);
310 89594568 run = 0;
311 } else {
312 108806544 run++;
313 }
314 }
315 }
316 174174 }
317
318 2397000 static void get(const uint8_t *pixels, int stride, int16_t* block)
319 {
320 int i;
321
322
2/2
✓ Branch 0 taken 19176000 times.
✓ Branch 1 taken 2397000 times.
21573000 for (i = 0; i < 8; i++) {
323 19176000 AV_WN64(block, AV_RN64(pixels));
324 19176000 AV_WN64(block+4, AV_RN64(pixels+8));
325 19176000 pixels += stride;
326 19176000 block += 8;
327 }
328 2397000 }
329
330 2397000 static void fdct_get(FDCTDSPContext *fdsp, const uint8_t *pixels, int stride, int16_t* block)
331 {
332 2397000 get(pixels, stride, block);
333 2397000 fdsp->fdct(block);
334 2397000 }
335
336 133800 static void calc_plane_dct(FDCTDSPContext *fdsp, const uint8_t *src, int16_t * blocks, int src_stride, int mb_count, int chroma, int is_422)
337 {
338 int16_t *block;
339 int i;
340
341 133800 block = blocks;
342
343
2/2
✓ Branch 0 taken 44600 times.
✓ Branch 1 taken 89200 times.
133800 if (!chroma) { /* Luma plane */
344
2/2
✓ Branch 0 taken 239700 times.
✓ Branch 1 taken 44600 times.
284300 for (i = 0; i < mb_count; i++) {
345 239700 fdct_get(fdsp, src, src_stride, block + (0 << 6));
346 239700 fdct_get(fdsp, src + 16, src_stride, block + (1 << 6));
347 239700 fdct_get(fdsp, src + 8 * src_stride, src_stride, block + (2 << 6));
348 239700 fdct_get(fdsp, src + 16 + 8 * src_stride, src_stride, block + (3 << 6));
349
350 239700 block += 256;
351 239700 src += 32;
352 }
353
3/4
✓ Branch 0 taken 89200 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 44600 times.
✓ Branch 3 taken 44600 times.
89200 } else if (chroma && is_422){ /* chroma plane 422 */
354
2/2
✓ Branch 0 taken 239700 times.
✓ Branch 1 taken 44600 times.
284300 for (i = 0; i < mb_count; i++) {
355 239700 fdct_get(fdsp, src, src_stride, block + (0 << 6));
356 239700 fdct_get(fdsp, src + 8 * src_stride, src_stride, block + (1 << 6));
357 239700 block += (256 >> 1);
358 239700 src += (32 >> 1);
359 }
360 } else { /* chroma plane 444 */
361
2/2
✓ Branch 0 taken 239700 times.
✓ Branch 1 taken 44600 times.
284300 for (i = 0; i < mb_count; i++) {
362 239700 fdct_get(fdsp, src, src_stride, block + (0 << 6));
363 239700 fdct_get(fdsp, src + 8 * src_stride, src_stride, block + (1 << 6));
364 239700 fdct_get(fdsp, src + 16, src_stride, block + (2 << 6));
365 239700 fdct_get(fdsp, src + 16 + 8 * src_stride, src_stride, block + (3 << 6));
366
367 239700 block += 256;
368 239700 src += 32;
369 }
370 }
371 133800 }
372
373 174174 static int encode_slice_plane(int16_t *blocks, int mb_count, uint8_t *buf, unsigned buf_size, int *qmat, int sub_sample_chroma,
374 const uint8_t *scan)
375 {
376 int blocks_per_slice;
377 PutBitContext pb;
378
379 174174 blocks_per_slice = mb_count << (2 - sub_sample_chroma);
380 174174 init_put_bits(&pb, buf, buf_size);
381
382 174174 encode_dcs(&pb, blocks, blocks_per_slice, qmat[0]);
383 174174 encode_acs(&pb, blocks, blocks_per_slice, qmat, scan);
384
385 174174 flush_put_bits(&pb);
386 174174 return put_bytes_output(&pb);
387 }
388
389 58058 static av_always_inline unsigned encode_slice_data(AVCodecContext *avctx,
390 int16_t * blocks_y, int16_t * blocks_u, int16_t * blocks_v,
391 unsigned mb_count, uint8_t *buf, unsigned data_size,
392 unsigned* y_data_size, unsigned* u_data_size, unsigned* v_data_size,
393 int qp)
394 {
395 58058 ProresContext* ctx = avctx->priv_data;
396
397 116116 *y_data_size = encode_slice_plane(blocks_y, mb_count,
398 58058 buf, data_size, ctx->qmat_luma[qp - 1], 0, ctx->scantable);
399
400 116116 *u_data_size = encode_slice_plane(blocks_u, mb_count, buf + *y_data_size, data_size - *y_data_size,
401 58058 ctx->qmat_chroma[qp - 1], ctx->is_422, ctx->scantable);
402
403 116116 *v_data_size = encode_slice_plane(blocks_v, mb_count, buf + *y_data_size + *u_data_size,
404 58058 data_size - *y_data_size - *u_data_size,
405 58058 ctx->qmat_chroma[qp - 1], ctx->is_422, ctx->scantable);
406
407 58058 return *y_data_size + *u_data_size + *v_data_size;
408 }
409
410 ✗ static void put_alpha_diff(PutBitContext *pb, int cur, int prev)
411 {
412 ✗ const int abits = 16;
413 ✗ const int dbits = 7;
414 ✗ const int dsize = 1 << dbits - 1;
415 ✗ int diff = cur - prev;
416
417 ✗ diff = av_zero_extend(diff, abits);
418 ✗ if (diff >= (1 << abits) - dsize)
419 ✗ diff -= 1 << abits;
420 ✗ if (diff < -dsize || diff > dsize || !diff) {
421 ✗ put_bits(pb, 1, 1);
422 ✗ put_bits(pb, abits, diff);
423 } else {
424 ✗ put_bits(pb, 1, 0);
425 ✗ put_bits(pb, dbits - 1, FFABS(diff) - 1);
426 ✗ put_bits(pb, 1, diff < 0);
427 }
428 ✗ }
429
430 ✗ static inline void put_alpha_run(PutBitContext *pb, int run)
431 {
432 ✗ if (run) {
433 ✗ put_bits(pb, 1, 0);
434 ✗ if (run < 0x10)
435 ✗ put_bits(pb, 4, run);
436 else
437 ✗ put_bits(pb, 15, run);
438 } else {
439 ✗ put_bits(pb, 1, 1);
440 }
441 ✗ }
442
443 ✗ static av_always_inline int encode_alpha_slice_data(AVCodecContext *avctx, int8_t * src_a,
444 unsigned mb_count, uint8_t *buf, unsigned data_size, unsigned* a_data_size)
445 {
446 ✗ const int abits = 16;
447 ✗ const int mask = (1 << abits) - 1;
448 ✗ const int num_coeffs = mb_count * 256;
449 ✗ int prev = mask, cur;
450 ✗ int idx = 0;
451 ✗ int run = 0;
452 ✗ int16_t * blocks = (int16_t *)src_a;
453 PutBitContext pb;
454 ✗ init_put_bits(&pb, buf, data_size);
455
456 ✗ cur = blocks[idx++];
457 ✗ put_alpha_diff(&pb, cur, prev);
458 ✗ prev = cur;
459 do {
460 ✗ cur = blocks[idx++];
461 ✗ if (cur != prev) {
462 ✗ put_alpha_run (&pb, run);
463 ✗ put_alpha_diff(&pb, cur, prev);
464 ✗ prev = cur;
465 ✗ run = 0;
466 } else {
467 ✗ run++;
468 }
469 ✗ } while (idx < num_coeffs);
470 ✗ put_alpha_run(&pb, run);
471 ✗ flush_put_bits(&pb);
472 ✗ *a_data_size = put_bytes_output(&pb);
473
474 ✗ if (put_bits_left(&pb) < 0) {
475 ✗ av_log(avctx, AV_LOG_ERROR,
476 "Underestimated required buffer size.\n");
477 ✗ return AVERROR_BUG;
478 } else {
479 ✗ return 0;
480 }
481 }
482
483 3000 static inline void subimage_with_fill_template(const uint16_t *src, unsigned x, unsigned y,
484 unsigned stride, unsigned width, unsigned height, uint16_t *dst,
485 unsigned dst_width, unsigned dst_height, int is_alpha_plane,
486 int is_interlaced, int is_top_field)
487 {
488 3000 int box_width = FFMIN(width - x, dst_width);
489 int i, j, src_stride, box_height;
490 uint16_t last_pix, *last_line;
491
492
2/2
✓ Branch 0 taken 1200 times.
✓ Branch 1 taken 1800 times.
3000 if (!is_interlaced) {
493 1200 src_stride = stride >> 1;
494 1200 src += y * src_stride + x;
495 1200 box_height = FFMIN(height - y, dst_height);
496 } else {
497 1800 src_stride = stride; /* 2 lines stride */
498 1800 src += y * src_stride + x;
499 1800 box_height = FFMIN((height + is_top_field) / 2 - y, dst_height);
500
2/2
✓ Branch 0 taken 900 times.
✓ Branch 1 taken 900 times.
1800 if (!is_top_field)
501 900 src += stride >> 1;
502 }
503
504
2/2
✓ Branch 0 taken 21600 times.
✓ Branch 1 taken 3000 times.
24600 for (i = 0; i < box_height; ++i) {
505
2/2
✓ Branch 0 taken 66000 times.
✓ Branch 1 taken 21600 times.
87600 for (j = 0; j < box_width; ++j) {
506
1/2
✓ Branch 0 taken 66000 times.
✗ Branch 1 not taken.
66000 if (!is_alpha_plane) {
507 66000 dst[j] = src[j];
508 } else {
509 ✗ dst[j] = src[j] << 6; /* alpha 10b to 16b */
510 }
511 }
512
1/2
✓ Branch 0 taken 21600 times.
✗ Branch 1 not taken.
21600 if (!is_alpha_plane) {
513 21600 last_pix = dst[j - 1];
514 } else {
515 ✗ last_pix = dst[j - 1] << 6; /* alpha 10b to 16b */
516 }
517
2/2
✓ Branch 0 taken 238000 times.
✓ Branch 1 taken 21600 times.
259600 for (; j < dst_width; j++)
518 238000 dst[j] = last_pix;
519 21600 src += src_stride;
520 21600 dst += dst_width;
521 }
522 3000 last_line = dst - dst_width;
523
2/2
✓ Branch 0 taken 26400 times.
✓ Branch 1 taken 3000 times.
29400 for (; i < dst_height; i++) {
524
2/2
✓ Branch 0 taken 528000 times.
✓ Branch 1 taken 26400 times.
554400 for (j = 0; j < dst_width; ++j) {
525 528000 dst[j] = last_line[j];
526 }
527 26400 dst += dst_width;
528 }
529 3000 }
530
531 3000 static void subimage_with_fill(const uint16_t *src, unsigned x, unsigned y,
532 unsigned stride, unsigned width, unsigned height, uint16_t *dst,
533 unsigned dst_width, unsigned dst_height, int is_interlaced, int is_top_field)
534 {
535 3000 subimage_with_fill_template(src, x, y, stride, width, height, dst, dst_width, dst_height, 0, is_interlaced, is_top_field);
536 3000 }
537
538 /* reorganize alpha data and convert 10b -> 16b */
539 ✗ static void subimage_alpha_with_fill(const uint16_t *src, unsigned x, unsigned y,
540 unsigned stride, unsigned width, unsigned height, uint16_t *dst,
541 unsigned dst_width, unsigned dst_height, int is_interlaced, int is_top_field)
542 {
543 ✗ subimage_with_fill_template(src, x, y, stride, width, height, dst, dst_width, dst_height, 1, is_interlaced, is_top_field);
544 ✗ }
545
546 44600 static int encode_slice(AVCodecContext *avctx, const AVFrame *pic, int mb_x,
547 int mb_y, unsigned mb_count, uint8_t *buf, unsigned data_size,
548 int unsafe, int *qp, int is_interlaced, int is_top_field)
549 {
550 44600 int luma_stride, chroma_stride, alpha_stride = 0;
551 44600 ProresContext* ctx = avctx->priv_data;
552 44600 int hdr_size = 6 + (ctx->need_alpha * 2); /* v data size is write when there is alpha */
553 44600 int ret = 0, slice_size;
554 const uint8_t *dest_y, *dest_u, *dest_v;
555 44600 unsigned y_data_size = 0, u_data_size = 0, v_data_size = 0, a_data_size = 0;
556 44600 FDCTDSPContext *fdsp = &ctx->fdsp;
557 44600 int tgt_bits = (mb_count * bitrate_table[avctx->profile]) >> 2;
558 44600 int low_bytes = (tgt_bits - (tgt_bits >> 3)) >> 3; // 12% bitrate fluctuation
559 44600 int high_bytes = (tgt_bits + (tgt_bits >> 3)) >> 3;
560
561 44600 LOCAL_ALIGNED(16, int16_t, blocks_y, [DEFAULT_SLICE_MB_WIDTH << 8]);
562 44600 LOCAL_ALIGNED(16, int16_t, blocks_u, [DEFAULT_SLICE_MB_WIDTH << 8]);
563 44600 LOCAL_ALIGNED(16, int16_t, blocks_v, [DEFAULT_SLICE_MB_WIDTH << 8]);
564
565 44600 luma_stride = pic->linesize[0];
566 44600 chroma_stride = pic->linesize[1];
567
568
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44600 times.
44600 if (ctx->need_alpha)
569 ✗ alpha_stride = pic->linesize[3];
570
571
2/2
✓ Branch 0 taken 22200 times.
✓ Branch 1 taken 22400 times.
44600 if (!is_interlaced) {
572 22200 dest_y = pic->data[0] + (mb_y << 4) * luma_stride + (mb_x << 5);
573 22200 dest_u = pic->data[1] + (mb_y << 4) * chroma_stride + (mb_x << (5 - ctx->is_422));
574 22200 dest_v = pic->data[2] + (mb_y << 4) * chroma_stride + (mb_x << (5 - ctx->is_422));
575 } else {
576 22400 dest_y = pic->data[0] + (mb_y << 4) * luma_stride * 2 + (mb_x << 5);
577 22400 dest_u = pic->data[1] + (mb_y << 4) * chroma_stride * 2 + (mb_x << (5 - ctx->is_422));
578 22400 dest_v = pic->data[2] + (mb_y << 4) * chroma_stride * 2 + (mb_x << (5 - ctx->is_422));
579
2/2
✓ Branch 0 taken 11200 times.
✓ Branch 1 taken 11200 times.
22400 if (!is_top_field){ /* bottom field, offset dest */
580 11200 dest_y += luma_stride;
581 11200 dest_u += chroma_stride;
582 11200 dest_v += chroma_stride;
583 }
584 }
585
586
2/2
✓ Branch 0 taken 1000 times.
✓ Branch 1 taken 43600 times.
44600 if (unsafe) {
587 1000 subimage_with_fill((const uint16_t *) pic->data[0], mb_x << 4, mb_y << 4,
588 1000 luma_stride, avctx->width, avctx->height,
589 1000 (uint16_t *) ctx->fill_y, mb_count << 4, 16, is_interlaced, is_top_field);
590 1000 subimage_with_fill((const uint16_t *) pic->data[1], mb_x << (4 - ctx->is_422), mb_y << 4,
591 1000 chroma_stride, avctx->width >> ctx->is_422, avctx->height,
592 1000 (uint16_t *) ctx->fill_u, mb_count << (4 - ctx->is_422), 16, is_interlaced, is_top_field);
593 1000 subimage_with_fill((const uint16_t *) pic->data[2], mb_x << (4 - ctx->is_422), mb_y << 4,
594 1000 chroma_stride, avctx->width >> ctx->is_422, avctx->height,
595 1000 (uint16_t *) ctx->fill_v, mb_count << (4 - ctx->is_422), 16, is_interlaced, is_top_field);
596
597 /* no need for interlaced special case, data already reorganized in subimage_with_fill */
598 1000 calc_plane_dct(fdsp, ctx->fill_y, blocks_y, mb_count << 5, mb_count, 0, 0);
599 1000 calc_plane_dct(fdsp, ctx->fill_u, blocks_u, mb_count << (5 - ctx->is_422), mb_count, 1, ctx->is_422);
600 1000 calc_plane_dct(fdsp, ctx->fill_v, blocks_v, mb_count << (5 - ctx->is_422), mb_count, 1, ctx->is_422);
601
602 1000 slice_size = encode_slice_data(avctx, blocks_y, blocks_u, blocks_v,
603 mb_count, buf + hdr_size, data_size - hdr_size,
604 &y_data_size, &u_data_size, &v_data_size,
605 *qp);
606 } else {
607
2/2
✓ Branch 0 taken 21800 times.
✓ Branch 1 taken 21800 times.
43600 if (!is_interlaced) {
608 21800 calc_plane_dct(fdsp, dest_y, blocks_y, luma_stride, mb_count, 0, 0);
609 21800 calc_plane_dct(fdsp, dest_u, blocks_u, chroma_stride, mb_count, 1, ctx->is_422);
610 21800 calc_plane_dct(fdsp, dest_v, blocks_v, chroma_stride, mb_count, 1, ctx->is_422);
611 } else {
612 21800 calc_plane_dct(fdsp, dest_y, blocks_y, luma_stride * 2, mb_count, 0, 0);
613 21800 calc_plane_dct(fdsp, dest_u, blocks_u, chroma_stride * 2, mb_count, 1, ctx->is_422);
614 21800 calc_plane_dct(fdsp, dest_v, blocks_v, chroma_stride * 2, mb_count, 1, ctx->is_422);
615 }
616
617 43600 slice_size = encode_slice_data(avctx, blocks_y, blocks_u, blocks_v,
618 mb_count, buf + hdr_size, data_size - hdr_size,
619 &y_data_size, &u_data_size, &v_data_size,
620 *qp);
621
622
4/4
✓ Branch 0 taken 37072 times.
✓ Branch 1 taken 6528 times.
✓ Branch 2 taken 3652 times.
✓ Branch 3 taken 33420 times.
43600 if (slice_size > high_bytes && *qp < qp_end_table[avctx->profile]) {
623 do {
624 8982 *qp += 1;
625 8982 slice_size = encode_slice_data(avctx, blocks_y, blocks_u, blocks_v,
626 mb_count, buf + hdr_size, data_size - hdr_size,
627 &y_data_size, &u_data_size, &v_data_size,
628 *qp);
629
4/4
✓ Branch 0 taken 7793 times.
✓ Branch 1 taken 1189 times.
✓ Branch 2 taken 5330 times.
✓ Branch 3 taken 2463 times.
8982 } while (slice_size > high_bytes && *qp < qp_end_table[avctx->profile]);
630
2/2
✓ Branch 0 taken 2317 times.
✓ Branch 1 taken 37631 times.
39948 } else if (slice_size < low_bytes && *qp
631
2/2
✓ Branch 0 taken 2312 times.
✓ Branch 1 taken 5 times.
2317 > qp_start_table[avctx->profile]) {
632 do {
633 4476 *qp -= 1;
634 4476 slice_size = encode_slice_data(avctx, blocks_y, blocks_u, blocks_v,
635 mb_count, buf + hdr_size, data_size - hdr_size,
636 &y_data_size, &u_data_size, &v_data_size,
637 *qp);
638
4/4
✓ Branch 0 taken 2195 times.
✓ Branch 1 taken 2281 times.
✓ Branch 2 taken 2164 times.
✓ Branch 3 taken 31 times.
4476 } while (slice_size < low_bytes && *qp > qp_start_table[avctx->profile]);
639 }
640 }
641
642 44600 buf[0] = hdr_size << 3;
643 44600 buf[1] = *qp;
644 44600 AV_WB16(buf + 2, y_data_size);
645 44600 AV_WB16(buf + 4, u_data_size);
646
647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44600 times.
44600 if (ctx->need_alpha) {
648 ✗ AV_WB16(buf + 6, v_data_size); /* write v data size only if there is alpha */
649
650 ✗ subimage_alpha_with_fill((const uint16_t *) pic->data[3], mb_x << 4, mb_y << 4,
651 ✗ alpha_stride, avctx->width, avctx->height,
652 ✗ (uint16_t *) ctx->fill_a, mb_count << 4, 16, is_interlaced, is_top_field);
653 ✗ ret = encode_alpha_slice_data(avctx, ctx->fill_a, mb_count,
654 ✗ buf + hdr_size + slice_size,
655 ✗ data_size - hdr_size - slice_size, &a_data_size);
656 }
657
658
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44600 times.
44600 if (ret != 0) {
659 ✗ return ret;
660 }
661 44600 return hdr_size + y_data_size + u_data_size + v_data_size + a_data_size;
662 }
663
664 1200 static int prores_encode_picture(AVCodecContext *avctx, const AVFrame *pic,
665 uint8_t *buf, const int buf_size, const int picture_index, const int is_top_field)
666 {
667 1200 ProresContext *ctx = avctx->priv_data;
668 1200 int mb_width = (avctx->width + 15) >> 4;
669 int hdr_size, sl_size, i;
670 int mb_y, sl_data_size, qp, mb_height, picture_height, unsafe_mb_height_limit;
671 int unsafe_bot, unsafe_right;
672 uint8_t *sl_data, *sl_data_sizes;
673 1200 int slice_per_line = 0, rem = mb_width;
674
675
2/2
✓ Branch 0 taken 400 times.
✓ Branch 1 taken 800 times.
1200 if (!ctx->is_interlaced) { /* progressive encoding */
676 400 picture_height = avctx->height;
677 400 mb_height = (avctx->height + 15) >> 4;
678 400 unsafe_mb_height_limit = mb_height;
679 } else {
680
2/2
✓ Branch 0 taken 400 times.
✓ Branch 1 taken 400 times.
800 if (is_top_field) {
681 400 picture_height = (avctx->height + 1) / 2;
682 } else {
683 400 picture_height = avctx->height / 2;
684 }
685 800 mb_height = (picture_height + 15) >> 4;
686 800 unsafe_mb_height_limit = mb_height;
687 }
688
689
2/2
✓ Branch 0 taken 4800 times.
✓ Branch 1 taken 1200 times.
6000 for (i = av_log2(DEFAULT_SLICE_MB_WIDTH); i >= 0; --i) {
690 4800 slice_per_line += rem >> i;
691 4800 rem &= (1 << i) - 1;
692 }
693
694 1200 qp = qp_start_table[avctx->profile];
695 1200 hdr_size = 8; sl_data_size = buf_size - hdr_size;
696 1200 sl_data_sizes = buf + hdr_size;
697 1200 sl_data = sl_data_sizes + (slice_per_line * mb_height * 2);
698
2/2
✓ Branch 0 taken 11500 times.
✓ Branch 1 taken 1200 times.
12700 for (mb_y = 0; mb_y < mb_height; mb_y++) {
699 11500 int mb_x = 0;
700 11500 int slice_mb_count = DEFAULT_SLICE_MB_WIDTH;
701
2/2
✓ Branch 0 taken 44600 times.
✓ Branch 1 taken 11500 times.
56100 while (mb_x < mb_width) {
702
2/2
✓ Branch 0 taken 23700 times.
✓ Branch 1 taken 44600 times.
68300 while (mb_width - mb_x < slice_mb_count)
703 23700 slice_mb_count >>= 1;
704
705
4/4
✓ Branch 0 taken 1400 times.
✓ Branch 1 taken 43200 times.
✓ Branch 2 taken 600 times.
✓ Branch 3 taken 800 times.
44600 unsafe_bot = (picture_height & 0xf) && (mb_y == unsafe_mb_height_limit - 1);
706
4/4
✓ Branch 0 taken 1400 times.
✓ Branch 1 taken 43200 times.
✓ Branch 2 taken 700 times.
✓ Branch 3 taken 700 times.
44600 unsafe_right = (avctx->width & 0xf) && (mb_x + slice_mb_count == mb_width);
707
708
4/4
✓ Branch 0 taken 44000 times.
✓ Branch 1 taken 600 times.
✓ Branch 2 taken 400 times.
✓ Branch 3 taken 43600 times.
44600 sl_size = encode_slice(avctx, pic, mb_x, mb_y, slice_mb_count,
709 sl_data, sl_data_size, unsafe_bot || unsafe_right, &qp, ctx->is_interlaced, is_top_field);
710
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44600 times.
44600 if (sl_size < 0){
711 ✗ return sl_size;
712 }
713
714 44600 bytestream_put_be16(&sl_data_sizes, sl_size);
715 44600 sl_data += sl_size;
716 44600 sl_data_size -= sl_size;
717 44600 mb_x += slice_mb_count;
718 }
719 }
720
721 1200 buf[0] = hdr_size << 3;
722 1200 AV_WB32(buf + 1, sl_data - buf);
723 1200 AV_WB16(buf + 5, slice_per_line * mb_height); /* picture size */
724 1200 buf[7] = av_log2(DEFAULT_SLICE_MB_WIDTH) << 4; /* number of slices */
725
726 1200 return sl_data - buf;
727 }
728
729 800 static int prores_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
730 const AVFrame *pict, int *got_packet)
731 {
732 800 ProresContext *ctx = avctx->priv_data;
733 800 int header_size = 148;
734 uint8_t *buf;
735 800 int compress_frame_size, pic_size, ret, is_top_field_first = 0;
736 uint8_t frame_flags;
737 800 int frame_size = FFALIGN(avctx->width, 16) * FFALIGN(avctx->height, 16)*16 + 500 + FF_INPUT_BUFFER_MIN_SIZE; //FIXME choose tighter limit
738
739
740
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 800 times.
800 if ((ret = ff_alloc_packet(avctx, pkt, frame_size + FF_INPUT_BUFFER_MIN_SIZE)) < 0)
741 ✗ return ret;
742
743 800 buf = pkt->data;
744 800 compress_frame_size = 8 + header_size;
745
746 800 bytestream_put_be32(&buf, compress_frame_size);/* frame size will be update after picture(s) encoding */
747 800 bytestream_put_be32(&buf, FRAME_ID);
748
749 800 bytestream_put_be16(&buf, header_size);
750
3/4
✓ Branch 0 taken 400 times.
✓ Branch 1 taken 400 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 400 times.
800 bytestream_put_be16(&buf, avctx->pix_fmt != AV_PIX_FMT_YUV422P10 || ctx->need_alpha ? 1 : 0); /* version */
751 800 bytestream_put_buffer(&buf, ctx->vendor, 4);
752 800 bytestream_put_be16(&buf, avctx->width);
753 800 bytestream_put_be16(&buf, avctx->height);
754 800 frame_flags = 0x80; /* 422 not interlaced */
755
2/2
✓ Branch 0 taken 400 times.
✓ Branch 1 taken 400 times.
800 if (avctx->profile >= AV_PROFILE_PRORES_4444) /* 4444 or 4444 Xq */
756 400 frame_flags |= 0x40; /* 444 chroma */
757
2/2
✓ Branch 0 taken 400 times.
✓ Branch 1 taken 400 times.
800 if (ctx->is_interlaced) {
758
2/4
✓ Branch 0 taken 400 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 400 times.
✗ Branch 3 not taken.
400 if ((pict->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) || !(pict->flags & AV_FRAME_FLAG_INTERLACED)) {
759 /* tff frame or progressive frame interpret as tff */
760 400 av_log(avctx, AV_LOG_DEBUG, "use interlaced encoding, top field first\n");
761 400 frame_flags |= 0x04; /* interlaced tff */
762 400 is_top_field_first = 1;
763 } else {
764 ✗ av_log(avctx, AV_LOG_DEBUG, "use interlaced encoding, bottom field first\n");
765 ✗ frame_flags |= 0x08; /* interlaced bff */
766 }
767 } else {
768 400 av_log(avctx, AV_LOG_DEBUG, "use progressive encoding\n");
769 }
770 800 *buf++ = frame_flags;
771 800 *buf++ = 0; /* reserved */
772 /* only write color properties, if valid value. set to unspecified otherwise */
773 1600 *buf++ = int_from_list_or_default(avctx, "frame color primaries",
774 800 pict->color_primaries, valid_primaries, 0);
775 1600 *buf++ = int_from_list_or_default(avctx, "frame color trc",
776 800 pict->color_trc, valid_trc, 0);
777 1600 *buf++ = int_from_list_or_default(avctx, "frame colorspace",
778 800 pict->colorspace, valid_colorspace, 0);
779
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 800 times.
800 *buf++ = ctx->need_alpha ? 0x2 /* 16-bit alpha */ : 0;
780 800 *buf++ = 0; /* reserved */
781 800 *buf++ = 3; /* luma and chroma matrix present */
782
783 800 bytestream_put_buffer(&buf, QMAT_LUMA[avctx->profile], 64);
784 800 bytestream_put_buffer(&buf, QMAT_CHROMA[avctx->profile], 64);
785
786 800 pic_size = prores_encode_picture(avctx, pict, buf,
787 800 pkt->size - compress_frame_size, 0, is_top_field_first);/* encode progressive or first field */
788
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 800 times.
800 if (pic_size < 0) {
789 ✗ return pic_size;
790 }
791 800 compress_frame_size += pic_size;
792
793
2/2
✓ Branch 0 taken 400 times.
✓ Branch 1 taken 400 times.
800 if (ctx->is_interlaced) { /* encode second field */
794 400 pic_size = prores_encode_picture(avctx, pict, pkt->data + compress_frame_size,
795 400 pkt->size - compress_frame_size, 1, !is_top_field_first);
796
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 400 times.
400 if (pic_size < 0) {
797 ✗ return pic_size;
798 }
799 400 compress_frame_size += pic_size;
800 }
801
802 800 AV_WB32(pkt->data, compress_frame_size);/* update frame size */
803 800 pkt->size = compress_frame_size;
804 800 *got_packet = 1;
805
806 800 return 0;
807 }
808
809 512 static void scale_mat(const uint8_t* src, int* dst, int scale)
810 {
811 int i;
812
2/2
✓ Branch 0 taken 32768 times.
✓ Branch 1 taken 512 times.
33280 for (i = 0; i < 64; i++)
813 32768 dst[i] = src[i] * scale;
814 512 }
815
816 16 static av_cold int prores_encode_init(AVCodecContext *avctx)
817 {
818 int i;
819 16 ProresContext* ctx = avctx->priv_data;
820
821 16 avctx->bits_per_raw_sample = 10;
822 16 ctx->need_alpha = 0;
823 16 ctx->is_interlaced = !!(avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT);
824
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 if (ctx->is_interlaced) {
825 8 ctx->scantable = ff_prores_interlaced_scan;
826 } else {
827 8 ctx->scantable = ff_prores_progressive_scan;
828 }
829
830
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (avctx->width & 0x1) {
831 ✗ av_log(avctx, AV_LOG_ERROR,
832 "frame width needs to be multiple of 2\n");
833 ✗ return AVERROR(EINVAL);
834 }
835
836
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
16 if (avctx->width > 65534 || avctx->height > 65535) {
837 ✗ av_log(avctx, AV_LOG_ERROR,
838 "The maximum dimensions are 65534x65535\n");
839 ✗ return AVERROR(EINVAL);
840 }
841
842
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (strlen(ctx->vendor) != 4) {
843 ✗ av_log(avctx, AV_LOG_ERROR, "vendor ID should be 4 bytes\n");
844 ✗ return AVERROR(EINVAL);
845 }
846
847
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (avctx->profile == AV_PROFILE_UNKNOWN) {
848
2/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
16 switch (avctx->pix_fmt) {
849 8 case AV_PIX_FMT_YUV422P10:
850 8 avctx->profile = AV_PROFILE_PRORES_STANDARD;
851 8 av_log(avctx, AV_LOG_INFO,
852 "encoding with ProRes standard (apcn) profile\n");
853 8 break;
854 8 case AV_PIX_FMT_YUV444P10:
855 8 avctx->profile = AV_PROFILE_PRORES_4444;
856 8 av_log(avctx, AV_LOG_INFO,
857 "encoding with ProRes 4444 (ap4h) profile\n");
858 8 break;
859 ✗ case AV_PIX_FMT_YUVA444P10:
860 ✗ avctx->profile = AV_PROFILE_PRORES_4444;
861 ✗ av_log(avctx, AV_LOG_INFO,
862 "encoding with ProRes 4444+ (ap4h) profile\n");
863 ✗ break;
864 ✗ default:
865 ✗ av_unreachable("Already checked via CODEC_PIXFMTS");
866 }
867 ✗ } else if (avctx->profile < AV_PROFILE_PRORES_PROXY
868 ✗ || avctx->profile > AV_PROFILE_PRORES_XQ) {
869 ✗ av_log(
870 avctx,
871 AV_LOG_ERROR,
872 "unknown profile %d, use [0 - apco, 1 - apcs, 2 - apcn (default), 3 - apch, 4 - ap4h, 5 - ap4x]\n",
873 avctx->profile);
874 ✗ return AVERROR(EINVAL);
875 ✗ } else if ((avctx->pix_fmt == AV_PIX_FMT_YUV422P10) && (avctx->profile > AV_PROFILE_PRORES_HQ)){
876 ✗ av_log(avctx, AV_LOG_ERROR,
877 "encoding with ProRes 444/Xq (ap4h/ap4x) profile, need YUV444P10 input\n");
878 ✗ return AVERROR(EINVAL);
879 ✗ } else if ((avctx->pix_fmt == AV_PIX_FMT_YUV444P10 || avctx->pix_fmt == AV_PIX_FMT_YUVA444P10)
880 ✗ && (avctx->profile < AV_PROFILE_PRORES_4444)){
881 ✗ av_log(avctx, AV_LOG_ERROR,
882 "encoding with ProRes Proxy/LT/422/422 HQ (apco, apcs, apcn, ap4h) profile, need YUV422P10 input\n");
883 ✗ return AVERROR(EINVAL);
884 }
885
886
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 if (avctx->profile < AV_PROFILE_PRORES_4444) { /* 422 versions */
887 8 ctx->is_422 = 1;
888
5/6
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
8 if ((avctx->height & (ctx->is_interlaced ? 0x1f : 0xf)) || (avctx->width & 0xf)) {
889 2 ctx->fill_y = av_malloc(4 * (DEFAULT_SLICE_MB_WIDTH << 8));
890
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!ctx->fill_y)
891 ✗ return AVERROR(ENOMEM);
892 2 ctx->fill_u = ctx->fill_y + (DEFAULT_SLICE_MB_WIDTH << 9);
893 2 ctx->fill_v = ctx->fill_u + (DEFAULT_SLICE_MB_WIDTH << 8);
894 }
895 } else { /* 444 */
896 8 ctx->is_422 = 0;
897
5/6
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
8 if ((avctx->height & (ctx->is_interlaced ? 0x1f : 0xf)) || (avctx->width & 0xf)) {
898 2 ctx->fill_y = av_malloc(3 * (DEFAULT_SLICE_MB_WIDTH << 9));
899
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!ctx->fill_y)
900 ✗ return AVERROR(ENOMEM);
901 2 ctx->fill_u = ctx->fill_y + (DEFAULT_SLICE_MB_WIDTH << 9);
902 2 ctx->fill_v = ctx->fill_u + (DEFAULT_SLICE_MB_WIDTH << 9);
903 }
904
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (avctx->pix_fmt == AV_PIX_FMT_YUVA444P10) {
905 ✗ ctx->need_alpha = 1;
906 ✗ ctx->fill_a = av_malloc(DEFAULT_SLICE_MB_WIDTH << 9); /* 8 blocks x 16px x 16px x sizeof (uint16) */
907 ✗ if (!ctx->fill_a)
908 ✗ return AVERROR(ENOMEM);
909 }
910 }
911
912
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (ctx->need_alpha)
913 ✗ avctx->bits_per_coded_sample = 32;
914
915 16 ff_fdctdsp_init(&ctx->fdsp, avctx);
916
917 16 avctx->codec_tag = AV_RL32((const uint8_t*)profiles[avctx->profile].name);
918
919
2/2
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 16 times.
272 for (i = 1; i <= 16; i++) {
920 256 scale_mat(QMAT_LUMA[avctx->profile] , ctx->qmat_luma[i - 1] , i);
921 256 scale_mat(QMAT_CHROMA[avctx->profile], ctx->qmat_chroma[i - 1], i);
922 }
923
924 16 return 0;
925 }
926
927 16 static av_cold int prores_encode_close(AVCodecContext *avctx)
928 {
929 16 ProresContext* ctx = avctx->priv_data;
930 16 av_freep(&ctx->fill_y);
931 16 av_freep(&ctx->fill_a);
932
933 16 return 0;
934 }
935
936 #define OFFSET(x) offsetof(ProresContext, x)
937 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
938
939 static const AVOption options[] = {
940 { "vendor", "vendor ID", OFFSET(vendor), AV_OPT_TYPE_STRING, { .str = "fmpg" }, 0, 0, VE },
941 { NULL }
942 };
943
944 static const AVClass prores_enc_class = {
945 .class_name = "ProRes encoder",
946 .item_name = av_default_item_name,
947 .option = options,
948 .version = LIBAVUTIL_VERSION_INT,
949 };
950
951 static const enum AVPixelFormat pix_fmts[] = {
952 AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10,
953 AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_NONE
954 };
955
956 const FFCodec ff_prores_aw_encoder = {
957 .p.name = "prores_aw",
958 CODEC_LONG_NAME("Apple ProRes"),
959 .p.type = AVMEDIA_TYPE_VIDEO,
960 .p.id = AV_CODEC_ID_PRORES,
961 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
962 AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
963 CODEC_PIXFMTS_ARRAY(pix_fmts),
964 .color_ranges = AVCOL_RANGE_MPEG,
965 .priv_data_size = sizeof(ProresContext),
966 .init = prores_encode_init,
967 .close = prores_encode_close,
968 FF_CODEC_ENCODE_CB(prores_encode_frame),
969 .p.priv_class = &prores_enc_class,
970 .p.profiles = NULL_IF_CONFIG_SMALL(ff_prores_profiles),
971 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
972 };
973
974 const FFCodec ff_prores_encoder = {
975 .p.name = "prores",
976 CODEC_LONG_NAME("Apple ProRes"),
977 .p.type = AVMEDIA_TYPE_VIDEO,
978 .p.id = AV_CODEC_ID_PRORES,
979 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
980 AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
981 CODEC_PIXFMTS_ARRAY(pix_fmts),
982 .color_ranges = AVCOL_RANGE_MPEG,
983 .priv_data_size = sizeof(ProresContext),
984 .init = prores_encode_init,
985 .close = prores_encode_close,
986 FF_CODEC_ENCODE_CB(prores_encode_frame),
987 .p.priv_class = &prores_enc_class,
988 .p.profiles = NULL_IF_CONFIG_SMALL(ff_prores_profiles),
989 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
990 };
991