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