]> git.sesse.net Git - ffmpeg/blob - libavcodec/proresdec_gpl.c
Merge remote-tracking branch 'qatar/master'
[ffmpeg] / libavcodec / proresdec_gpl.c
1 /*
2  * Copyright (c) 2010-2011 Maxim Poliakovski
3  * Copyright (c) 2010-2011 Elvis Presley
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public
9  * License as published by the Free Software Foundation;
10  * version 2 of the License.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 /**
23  * @file libavcodec/proresdec.c
24  * Known FOURCCs: 'apch' (HQ), 'apcn' (SD), 'apcs' (LT), 'acpo' (Proxy), 'ap4c' (4444)
25  */
26
27 //#define DEBUG
28
29 #define A32_BITSTREAM_READER
30
31 #include "avcodec.h"
32 #include "get_bits.h"
33 #include "dsputil.h"
34 #include "simple_idct.h"
35
36 typedef struct {
37     const uint8_t *data;
38     unsigned mb_x;
39     unsigned mb_y;
40     unsigned mb_count;
41     unsigned data_size;
42 } SliceContext;
43
44 typedef struct {
45     AVFrame frame;
46     DSPContext dsp;
47     int frame_type;              ///< 0 = progressive, 1 = tff, 2 = bff
48     uint8_t qmat_luma[64];
49     uint8_t qmat_chroma[64];
50     SliceContext *slices;
51     int slice_count;             ///< number of slices in the current picture
52     unsigned mb_width;           ///< width of the current picture in mb
53     unsigned mb_height;          ///< height of the current picture in mb
54     uint8_t progressive_scan[64];
55     uint8_t interlaced_scan[64];
56     const uint8_t *scan;
57     int first_field;
58     void (*idct_put)(DCTELEM *, uint8_t *restrict, int);
59 } ProresContext;
60
61 static void permute(uint8_t *dst, const uint8_t *src, const uint8_t permutation[64])
62 {
63     int i;
64     for (i = 0; i < 64; i++)
65         dst[i] = permutation[src[i]];
66 }
67
68 static av_always_inline void put_pixels(const DCTELEM *block, uint8_t *restrict pixels, int stride)
69 {
70     int16_t *p = (int16_t*)pixels;
71     int i, j;
72
73     stride >>= 1;
74     for(i = 0; i < 8; i++) {
75         for (j = 0; j < 8; j++) {
76             p[j] = av_clip(block[j], 4, 1019);
77         }
78         p += stride;
79         block += 8;
80     }
81 }
82
83 static void idct_put(DCTELEM *block, uint8_t *restrict pixels, int stride)
84 {
85     ff_simple_idct_10(block);
86     put_pixels(block, pixels, stride);
87 }
88
89 static const uint8_t progressive_scan[64] = {
90      0,  1,  8,  9,  2,  3, 10, 11,
91     16, 17, 24, 25, 18, 19, 26, 27,
92      4,  5, 12, 20, 13,  6,  7, 14,
93     21, 28, 29, 22, 15, 23, 30, 31,
94     32, 33, 40, 48, 41, 34, 35, 42,
95     49, 56, 57, 50, 43, 36, 37, 44,
96     51, 58, 59, 52, 45, 38, 39, 46,
97     53, 60, 61, 54, 47, 55, 62, 63
98 };
99
100 static const uint8_t interlaced_scan[64] = {
101      0,  8,  1,  9, 16, 24, 17, 25,
102      2, 10,  3, 11, 18, 26, 19, 27,
103     32, 40, 33, 34, 41, 48, 56, 49,
104     42, 35, 43, 50, 57, 58, 51, 59,
105      4, 12,  5,  6, 13, 20, 28, 21,
106     14,  7, 15, 22, 29, 36, 44, 37,
107     30, 23, 31, 38, 45, 52, 60, 53,
108     46, 39, 47, 54, 61, 62, 55, 63,
109 };
110
111 static av_cold int decode_init(AVCodecContext *avctx)
112 {
113     ProresContext *ctx = avctx->priv_data;
114
115     avctx->bits_per_raw_sample = 10;
116
117     dsputil_init(&ctx->dsp, avctx);
118
119     avctx->coded_frame = &ctx->frame;
120     ctx->frame.type = FF_I_TYPE;
121     ctx->frame.key_frame = 1;
122
123     ctx->idct_put = idct_put;
124     memcpy(ctx->progressive_scan, progressive_scan, sizeof(progressive_scan));
125     memcpy(ctx->interlaced_scan, interlaced_scan, sizeof(interlaced_scan));
126
127     return 0;
128 }
129
130 static int decode_frame_header(ProresContext *ctx, const uint8_t *buf,
131                                const int data_size, AVCodecContext *avctx)
132 {
133     int hdr_size, width, height, flags;
134     int version;
135     const uint8_t *ptr;
136     const uint8_t *scan;
137
138     hdr_size = AV_RB16(buf);
139     av_dlog(avctx, "header size %d\n", hdr_size);
140     if (hdr_size > data_size) {
141         av_log(avctx, AV_LOG_ERROR, "error, wrong header size\n");
142         return -1;
143     }
144
145     version = AV_RB16(buf + 2);
146     av_dlog(avctx, "%.4s version %d\n", buf+4, version);
147     if (version > 1) {
148         av_log(avctx, AV_LOG_ERROR, "unsupported version: %d\n", version);
149         return -1;
150     }
151
152     width  = AV_RB16(buf + 8);
153     height = AV_RB16(buf + 10);
154     if (width != avctx->width || height != avctx->height) {
155         av_log(avctx, AV_LOG_ERROR, "picture resolution change: %dx%d -> %dx%d\n",
156                avctx->width, avctx->height, width, height);
157         return -1;
158     }
159
160     ctx->frame_type = (buf[12] >> 2) & 3;
161
162     av_dlog(avctx, "frame type %d\n", ctx->frame_type);
163
164     if (ctx->frame_type == 0) {
165         scan = progressive_scan;
166         ctx->scan = ctx->progressive_scan; // permuted
167     } else {
168         scan = interlaced_scan;
169         ctx->scan = ctx->interlaced_scan; // permuted
170         ctx->frame.interlaced_frame = 1;
171         ctx->frame.top_field_first = ctx->frame_type == 1;
172     }
173
174     avctx->pix_fmt = ((buf[12] & 0xC0) == 0xC0) ? PIX_FMT_YUV444P10 : PIX_FMT_YUV422P10;
175
176     ptr   = buf + 20;
177     flags = buf[19];
178     av_dlog(avctx, "flags %x\n", flags);
179
180     if (flags & 2) {
181         permute(ctx->qmat_luma, scan, ptr);
182         ptr += 64;
183     } else {
184         memset(ctx->qmat_luma, 4, 64);
185     }
186
187     if (flags & 1) {
188         permute(ctx->qmat_chroma, scan, ptr);
189     } else {
190         memset(ctx->qmat_chroma, 4, 64);
191     }
192
193     return hdr_size;
194 }
195
196 static int decode_picture_header(AVCodecContext *avctx, const uint8_t *buf, const int buf_size)
197 {
198     ProresContext *ctx = avctx->priv_data;
199     int i, hdr_size, slice_count;
200     unsigned pic_data_size;
201     int log2_slice_mb_width, log2_slice_mb_height;
202     int slice_mb_count, mb_x, mb_y;
203     const uint8_t *data_ptr, *index_ptr;
204
205     hdr_size = buf[0] >> 3;
206     if (hdr_size < 8 || hdr_size > buf_size) {
207         av_log(avctx, AV_LOG_ERROR, "error, wrong picture header size\n");
208         return -1;
209     }
210
211     pic_data_size = AV_RB32(buf + 1);
212     if (pic_data_size > buf_size) {
213         av_log(avctx, AV_LOG_ERROR, "error, wrong picture data size\n");
214         return -1;
215     }
216
217     log2_slice_mb_width  = buf[7] >> 4;
218     log2_slice_mb_height = buf[7] & 0xF;
219     if (log2_slice_mb_width > 3 || log2_slice_mb_height) {
220         av_log(avctx, AV_LOG_ERROR, "unsupported slice resolution: %dx%d\n",
221                1 << log2_slice_mb_width, 1 << log2_slice_mb_height);
222         return -1;
223     }
224
225     ctx->mb_width  = (avctx->width  + 15) >> 4;
226     ctx->mb_height = (avctx->height + 15) >> 4;
227
228     slice_count = AV_RB16(buf + 5);
229
230     if (ctx->slice_count != slice_count || !ctx->slices) {
231         av_freep(&ctx->slices);
232         ctx->slices = av_mallocz(slice_count * sizeof(*ctx->slices));
233         if (!ctx->slices)
234             return AVERROR(ENOMEM);
235         ctx->slice_count = slice_count;
236     }
237
238     if (!slice_count)
239         return AVERROR(EINVAL);
240
241     if (hdr_size + slice_count*2 > buf_size) {
242         av_log(avctx, AV_LOG_ERROR, "error, wrong slice count\n");
243         return -1;
244     }
245
246     // parse slice information
247     index_ptr = buf + hdr_size;
248     data_ptr  = index_ptr + slice_count*2;
249
250     slice_mb_count = 1 << log2_slice_mb_width;
251     mb_x = 0;
252     mb_y = 0;
253
254     for (i = 0; i < slice_count; i++) {
255         SliceContext *slice = &ctx->slices[i];
256
257         slice->data = data_ptr;
258         data_ptr += AV_RB16(index_ptr + i*2);
259
260         while (ctx->mb_width - mb_x < slice_mb_count)
261             slice_mb_count >>= 1;
262
263         slice->mb_x = mb_x;
264         slice->mb_y = mb_y;
265         slice->mb_count = slice_mb_count;
266         slice->data_size = data_ptr - slice->data;
267
268         if (slice->data_size < 6) {
269             av_log(avctx, AV_LOG_ERROR, "error, wrong slice data size\n");
270             return -1;
271         }
272
273         mb_x += slice_mb_count;
274         if (mb_x == ctx->mb_width) {
275             slice_mb_count = 1 << log2_slice_mb_width;
276             mb_x = 0;
277             mb_y++;
278         }
279         if (data_ptr > buf + buf_size) {
280             av_log(avctx, AV_LOG_ERROR, "error, slice out of bounds\n");
281             return -1;
282         }
283     }
284
285     return pic_data_size;
286 }
287
288 #define DECODE_CODEWORD(val, codebook)                                  \
289     do {                                                                \
290         unsigned int rice_order, exp_order, switch_bits;                \
291         unsigned int q, buf, bits;                                      \
292                                                                         \
293         UPDATE_CACHE(re, gb);                                           \
294         buf = GET_CACHE(re, gb);                                        \
295                                                                         \
296         /* number of bits to switch between rice and exp golomb */      \
297         switch_bits =  codebook & 3;                                    \
298         rice_order  =  codebook >> 5;                                   \
299         exp_order   = (codebook >> 2) & 7;                              \
300                                                                         \
301         q = 31-av_log2(buf);                                         \
302                                                                         \
303         if (q > switch_bits) { /* exp golomb */                         \
304             bits = exp_order - switch_bits + (q<<1);                    \
305             val = SHOW_UBITS(re, gb, bits) - (1 << exp_order) +         \
306                 ((switch_bits + 1) << rice_order);                      \
307             SKIP_BITS(re, gb, bits);                                    \
308         } else if (rice_order) {                                        \
309             SKIP_BITS(re, gb, q+1);                                     \
310             val = (q << rice_order) + SHOW_UBITS(re, gb, rice_order);   \
311             SKIP_BITS(re, gb, rice_order);                              \
312         } else {                                                        \
313             val = q;                                                    \
314             SKIP_BITS(re, gb, q+1);                                     \
315         }                                                               \
316     } while (0);                                                        \
317
318 #define TOSIGNED(x) (((x) >> 1) ^ (-((x) & 1)))
319
320 #define FIRST_DC_CB 0xB8
321
322 static const uint8_t dc_codebook[7] = { 0x04, 0x28, 0x28, 0x4D, 0x4D, 0x70, 0x70};
323
324 static av_always_inline void decode_dc_coeffs(GetBitContext *gb, DCTELEM *out,
325                                               int blocks_per_slice, const int *qmat)
326 {
327     DCTELEM prev_dc;
328     int code, i, sign;
329
330     OPEN_READER(re, gb);
331
332     DECODE_CODEWORD(code, FIRST_DC_CB);
333     prev_dc = TOSIGNED(code);
334     out[0] = 4096 + ((prev_dc * qmat[0]) >> 2);
335
336     out += 64; // dc coeff for the next block
337
338     code = 5;
339     sign = 0;
340     for (i = 1; i < blocks_per_slice; i++, out += 64) {
341         DECODE_CODEWORD(code, dc_codebook[FFMIN(code, 6)]);
342         if(code) sign ^= -(code & 1);
343         else     sign  = 0;
344         prev_dc += (((code + 1) >> 1) ^ sign) - sign;
345         out[0] = 4096 + ((prev_dc * qmat[0]) >> 2);
346     }
347     CLOSE_READER(re, gb);
348 }
349
350 // adaptive codebook switching lut according to previous run/level values
351 static const uint8_t run_to_cb[16] = { 0x06, 0x06, 0x05, 0x05, 0x04, 0x29, 0x29, 0x29, 0x29, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x4C };
352 static const uint8_t lev_to_cb[10] = { 0x04, 0x0A, 0x05, 0x06, 0x04, 0x28, 0x28, 0x28, 0x28, 0x4C };
353
354 static av_always_inline void decode_ac_coeffs(AVCodecContext *avctx, GetBitContext *gb,
355                                               DCTELEM *out, int blocks_per_slice,
356                                               const int *qmat)
357 {
358     ProresContext *ctx = avctx->priv_data;
359     int block_mask, sign;
360     unsigned pos, run, level;
361     int max_coeffs, i, bits_left;
362     int log2_block_count = av_log2(blocks_per_slice);
363
364     OPEN_READER(re, gb);
365
366     run   = 4;
367     level = 2;
368
369     max_coeffs = 64 << log2_block_count;
370     block_mask = blocks_per_slice - 1;
371
372     for (pos = block_mask;;) {
373         bits_left = gb->size_in_bits - (((uint8_t*)re_buffer_ptr - gb->buffer)*8 - 32 + re_bit_count);
374         if (!bits_left || (bits_left < 32 && !SHOW_UBITS(re, gb, bits_left)))
375             break;
376
377         DECODE_CODEWORD(run, run_to_cb[FFMIN(run,  15)]);
378         pos += run + 1;
379         if (pos >= max_coeffs) {
380             av_log(avctx, AV_LOG_ERROR, "ac tex damaged %d, %d\n", pos, max_coeffs);
381             return;
382         }
383
384         DECODE_CODEWORD(level, lev_to_cb[FFMIN(level, 9)]);
385         level += 1;
386
387         i = pos >> log2_block_count;
388
389         sign = SHOW_SBITS(re, gb, 1);
390         SKIP_BITS(re, gb, 1);
391         out[((pos & block_mask) << 6) + ctx->scan[i]] = (((level ^ sign) - sign) * qmat[i]) >> 2;
392     }
393
394     CLOSE_READER(re, gb);
395 }
396
397 static void decode_slice_luma(AVCodecContext *avctx, SliceContext *slice,
398                               uint8_t *dst, int dst_stride,
399                               const uint8_t *buf, unsigned buf_size,
400                               const int *qmat)
401 {
402     ProresContext *ctx = avctx->priv_data;
403     LOCAL_ALIGNED_16(DCTELEM, blocks, [8*4*64]);
404     DCTELEM *block;
405     GetBitContext gb;
406     int i, blocks_per_slice = slice->mb_count<<2;
407
408     for (i = 0; i < blocks_per_slice; i++)
409         ctx->dsp.clear_block(blocks+(i<<6));
410
411     init_get_bits(&gb, buf, buf_size << 3);
412
413     decode_dc_coeffs(&gb, blocks, blocks_per_slice, qmat);
414     decode_ac_coeffs(avctx, &gb, blocks, blocks_per_slice, qmat);
415
416     block = blocks;
417
418     for (i = 0; i < slice->mb_count; i++) {
419         ctx->idct_put(block+(0<<6), dst, dst_stride);
420         ctx->idct_put(block+(1<<6), dst+16, dst_stride);
421         ctx->idct_put(block+(2<<6), dst+8*dst_stride, dst_stride);
422         ctx->idct_put(block+(3<<6), dst+8*dst_stride+16, dst_stride);
423         block += 4*64;
424         dst += 32;
425     }
426
427 }
428
429 static void decode_slice_chroma(AVCodecContext *avctx, SliceContext *slice,
430                                 uint8_t *dst, int dst_stride,
431                                 const uint8_t *buf, unsigned buf_size,
432                                 const int *qmat, int log2_blocks_per_mb)
433 {
434     ProresContext *ctx = avctx->priv_data;
435     LOCAL_ALIGNED_16(DCTELEM, blocks, [8*4*64]);
436     DCTELEM *block;
437     GetBitContext gb;
438     int i, j, blocks_per_slice = slice->mb_count << log2_blocks_per_mb;
439
440     for (i = 0; i < blocks_per_slice; i++)
441         ctx->dsp.clear_block(blocks+(i<<6));
442
443     init_get_bits(&gb, buf, buf_size << 3);
444
445     decode_dc_coeffs(&gb, blocks, blocks_per_slice, qmat);
446     decode_ac_coeffs(avctx, &gb, blocks, blocks_per_slice, qmat);
447
448     block = blocks;
449     for (i = 0; i < slice->mb_count; i++) {
450         for (j = 0; j < log2_blocks_per_mb; j++) {
451             ctx->idct_put(block+(0<<6), dst,              dst_stride);
452             ctx->idct_put(block+(1<<6), dst+8*dst_stride, dst_stride);
453             block += 2*64;
454             dst += 16;
455         }
456     }
457 }
458
459 static int decode_slice_thread(AVCodecContext *avctx, void *arg, int jobnr, int threadnr)
460 {
461     ProresContext *ctx = avctx->priv_data;
462     SliceContext *slice = &ctx->slices[jobnr];
463     const uint8_t *buf = slice->data;
464     AVFrame *pic = avctx->coded_frame;
465     int i, hdr_size, qscale, log2_chroma_blocks_per_mb;
466     int luma_stride, chroma_stride;
467     int y_data_size, u_data_size, v_data_size;
468     uint8_t *dest_y, *dest_u, *dest_v;
469     int qmat_luma_scaled[64];
470     int qmat_chroma_scaled[64];
471     int mb_x_shift;
472
473     //av_log(avctx, AV_LOG_INFO, "slice %d mb width %d mb x %d y %d\n",
474     //       jobnr, slice->mb_count, slice->mb_x, slice->mb_y);
475
476     // slice header
477     hdr_size = buf[0] >> 3;
478     qscale = av_clip(buf[1], 1, 224);
479     qscale = qscale > 128 ? qscale - 96 << 2: qscale;
480     y_data_size = AV_RB16(buf + 2);
481     u_data_size = AV_RB16(buf + 4);
482     v_data_size = slice->data_size - y_data_size - u_data_size - hdr_size;
483     if (hdr_size > 7) v_data_size = AV_RB16(buf + 6);
484
485     if (y_data_size < 0 || u_data_size < 0 || v_data_size < 0) {
486         av_log(avctx, AV_LOG_ERROR, "invalid plane data size\n");
487         return -1;
488     }
489
490     buf += hdr_size;
491
492     for (i = 0; i < 64; i++) {
493         qmat_luma_scaled[i]   = ctx->qmat_luma[i] * qscale;
494         qmat_chroma_scaled[i] = ctx->qmat_chroma[i] * qscale;
495     }
496
497     if (ctx->frame_type == 0) {
498         luma_stride   = pic->linesize[0];
499         chroma_stride = pic->linesize[1];
500     } else {
501         luma_stride   = pic->linesize[0] << 1;
502         chroma_stride = pic->linesize[1] << 1;
503     }
504
505     if (avctx->pix_fmt == PIX_FMT_YUV444P10) {
506         mb_x_shift = 5;
507         log2_chroma_blocks_per_mb = 2;
508     } else {
509         mb_x_shift = 4;
510         log2_chroma_blocks_per_mb = 1;
511     }
512
513     dest_y = pic->data[0] + (slice->mb_y << 4) * luma_stride + (slice->mb_x << 5);
514     dest_u = pic->data[1] + (slice->mb_y << 4) * chroma_stride + (slice->mb_x << mb_x_shift);
515     dest_v = pic->data[2] + (slice->mb_y << 4) * chroma_stride + (slice->mb_x << mb_x_shift);
516
517     if (ctx->frame_type && ctx->first_field ^ ctx->frame.top_field_first) {
518         dest_y += pic->linesize[0];
519         dest_u += pic->linesize[1];
520         dest_v += pic->linesize[2];
521     }
522
523     decode_slice_luma(avctx, slice, dest_y, luma_stride,
524                       buf, y_data_size, qmat_luma_scaled);
525
526     if (!(avctx->flags & CODEC_FLAG_GRAY)) {
527         decode_slice_chroma(avctx, slice, dest_u, chroma_stride,
528                             buf + y_data_size, u_data_size,
529                             qmat_chroma_scaled, log2_chroma_blocks_per_mb);
530         decode_slice_chroma(avctx, slice, dest_v, chroma_stride,
531                             buf + y_data_size + u_data_size, v_data_size,
532                             qmat_chroma_scaled, log2_chroma_blocks_per_mb);
533     }
534
535     return 0;
536 }
537
538 static int decode_picture(AVCodecContext *avctx)
539 {
540     ProresContext *ctx = avctx->priv_data;
541     int i, threads_ret[ctx->slice_count];
542
543     avctx->execute2(avctx, decode_slice_thread, NULL, threads_ret, ctx->slice_count);
544
545     for (i = 0; i < ctx->slice_count; i++)
546         if (threads_ret[i] < 0)
547             return threads_ret[i];
548
549     return 0;
550 }
551
552 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size,
553                         AVPacket *avpkt)
554 {
555     ProresContext *ctx = avctx->priv_data;
556     AVFrame *frame = avctx->coded_frame;
557     const uint8_t *buf = avpkt->data;
558     int buf_size = avpkt->size;
559     int frame_hdr_size, pic_size;
560
561     if (buf_size < 28 || AV_RL32(buf +  4) != AV_RL32("icpf")) {
562         av_log(avctx, AV_LOG_ERROR, "invalid frame header\n");
563         return -1;
564     }
565
566     ctx->first_field = 1;
567
568     buf += 8;
569     buf_size -= 8;
570
571     frame_hdr_size = decode_frame_header(ctx, buf, buf_size, avctx);
572     if (frame_hdr_size < 0)
573         return -1;
574
575     buf += frame_hdr_size;
576     buf_size -= frame_hdr_size;
577
578  decode_picture:
579     pic_size = decode_picture_header(avctx, buf, buf_size);
580     if (pic_size < 0) {
581         av_log(avctx, AV_LOG_ERROR, "error decoding picture header\n");
582         return -1;
583     }
584
585     if (frame->data[0])
586         avctx->release_buffer(avctx, frame);
587
588     if (avctx->get_buffer(avctx, frame) < 0)
589         return -1;
590
591     if (decode_picture(avctx)) {
592         av_log(avctx, AV_LOG_ERROR, "error decoding picture\n");
593         return -1;
594     }
595
596     buf += pic_size;
597     buf_size -= pic_size;
598
599     if (ctx->frame_type && buf_size > 0 && ctx->first_field) {
600         ctx->first_field = 0;
601         goto decode_picture;
602     }
603
604     *data_size = sizeof(AVFrame);
605     *(AVFrame*)data = *frame;
606
607     return avpkt->size;
608 }
609
610 static av_cold int decode_close(AVCodecContext *avctx)
611 {
612     ProresContext *ctx = avctx->priv_data;
613
614     AVFrame *frame = avctx->coded_frame;
615     if (frame->data[0])
616         avctx->release_buffer(avctx, frame);
617     av_freep(&ctx->slices);
618
619     return 0;
620 }
621
622 AVCodec ff_prores_gpl_decoder = {
623     .name           = "prores_gpl",
624     .type           = AVMEDIA_TYPE_VIDEO,
625     .id             = CODEC_ID_PRORES,
626     .priv_data_size = sizeof(ProresContext),
627     .init           = decode_init,
628     .close          = decode_close,
629     .decode         = decode_frame,
630     .long_name      = NULL_IF_CONFIG_SMALL("ProRes"),
631     .capabilities   = CODEC_CAP_SLICE_THREADS,
632 };