xref: /third_party/ffmpeg/libavcodec/librav1e.c (revision cabdff1a)
1/*
2 * librav1e encoder
3 *
4 * Copyright (c) 2019 Derek Buitenhuis
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include <rav1e.h>
24
25#include "libavutil/internal.h"
26#include "libavutil/avassert.h"
27#include "libavutil/base64.h"
28#include "libavutil/common.h"
29#include "libavutil/mathematics.h"
30#include "libavutil/opt.h"
31#include "libavutil/pixdesc.h"
32#include "avcodec.h"
33#include "bsf.h"
34#include "codec_internal.h"
35#include "encode.h"
36#include "internal.h"
37
38typedef struct librav1eContext {
39    const AVClass *class;
40
41    RaContext *ctx;
42    AVFrame *frame;
43    RaFrame *rframe;
44    AVBSFContext *bsf;
45
46    uint8_t *pass_data;
47    size_t pass_pos;
48    int pass_size;
49
50    AVDictionary *rav1e_opts;
51    int quantizer;
52    int speed;
53    int tiles;
54    int tile_rows;
55    int tile_cols;
56} librav1eContext;
57
58static inline RaPixelRange range_map(enum AVPixelFormat pix_fmt, enum AVColorRange range)
59{
60    switch (pix_fmt) {
61    case AV_PIX_FMT_YUVJ420P:
62    case AV_PIX_FMT_YUVJ422P:
63    case AV_PIX_FMT_YUVJ444P:
64        return RA_PIXEL_RANGE_FULL;
65    }
66
67    switch (range) {
68    case AVCOL_RANGE_JPEG:
69        return RA_PIXEL_RANGE_FULL;
70    case AVCOL_RANGE_MPEG:
71    default:
72        return RA_PIXEL_RANGE_LIMITED;
73    }
74}
75
76static inline RaChromaSampling pix_fmt_map(enum AVPixelFormat pix_fmt)
77{
78    switch (pix_fmt) {
79    case AV_PIX_FMT_YUV420P:
80    case AV_PIX_FMT_YUVJ420P:
81    case AV_PIX_FMT_YUV420P10:
82    case AV_PIX_FMT_YUV420P12:
83        return RA_CHROMA_SAMPLING_CS420;
84    case AV_PIX_FMT_YUV422P:
85    case AV_PIX_FMT_YUVJ422P:
86    case AV_PIX_FMT_YUV422P10:
87    case AV_PIX_FMT_YUV422P12:
88        return RA_CHROMA_SAMPLING_CS422;
89    case AV_PIX_FMT_YUV444P:
90    case AV_PIX_FMT_YUVJ444P:
91    case AV_PIX_FMT_YUV444P10:
92    case AV_PIX_FMT_YUV444P12:
93        return RA_CHROMA_SAMPLING_CS444;
94    default:
95        av_assert0(0);
96    }
97}
98
99static inline RaChromaSamplePosition chroma_loc_map(enum AVChromaLocation chroma_loc)
100{
101    switch (chroma_loc) {
102    case AVCHROMA_LOC_LEFT:
103        return RA_CHROMA_SAMPLE_POSITION_VERTICAL;
104    case AVCHROMA_LOC_TOPLEFT:
105        return RA_CHROMA_SAMPLE_POSITION_COLOCATED;
106    default:
107        return RA_CHROMA_SAMPLE_POSITION_UNKNOWN;
108    }
109}
110
111static int get_stats(AVCodecContext *avctx, int eos)
112{
113    librav1eContext *ctx = avctx->priv_data;
114    RaData* buf = rav1e_twopass_out(ctx->ctx);
115    if (!buf)
116        return 0;
117
118    if (!eos) {
119        uint8_t *tmp = av_fast_realloc(ctx->pass_data, &ctx->pass_size,
120                                      ctx->pass_pos + buf->len);
121        if (!tmp) {
122            rav1e_data_unref(buf);
123            return AVERROR(ENOMEM);
124        }
125
126        ctx->pass_data = tmp;
127        memcpy(ctx->pass_data + ctx->pass_pos, buf->data, buf->len);
128        ctx->pass_pos += buf->len;
129    } else {
130        size_t b64_size = AV_BASE64_SIZE(ctx->pass_pos);
131
132        memcpy(ctx->pass_data, buf->data, buf->len);
133
134        avctx->stats_out = av_malloc(b64_size);
135        if (!avctx->stats_out) {
136            rav1e_data_unref(buf);
137            return AVERROR(ENOMEM);
138        }
139
140        av_base64_encode(avctx->stats_out, b64_size, ctx->pass_data, ctx->pass_pos);
141
142        av_freep(&ctx->pass_data);
143    }
144
145    rav1e_data_unref(buf);
146
147    return 0;
148}
149
150static int set_stats(AVCodecContext *avctx)
151{
152    librav1eContext *ctx = avctx->priv_data;
153    int ret = 1;
154
155    while (ret > 0 && ctx->pass_size - ctx->pass_pos > 0) {
156        ret = rav1e_twopass_in(ctx->ctx, ctx->pass_data + ctx->pass_pos, ctx->pass_size);
157        if (ret < 0)
158            return AVERROR_EXTERNAL;
159        ctx->pass_pos += ret;
160    }
161
162    return 0;
163}
164
165static av_cold int librav1e_encode_close(AVCodecContext *avctx)
166{
167    librav1eContext *ctx = avctx->priv_data;
168
169    if (ctx->ctx) {
170        rav1e_context_unref(ctx->ctx);
171        ctx->ctx = NULL;
172    }
173    if (ctx->rframe) {
174        rav1e_frame_unref(ctx->rframe);
175        ctx->rframe = NULL;
176    }
177
178    av_frame_free(&ctx->frame);
179    av_bsf_free(&ctx->bsf);
180    av_freep(&ctx->pass_data);
181
182    return 0;
183}
184
185static av_cold int librav1e_encode_init(AVCodecContext *avctx)
186{
187    librav1eContext *ctx = avctx->priv_data;
188    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
189    RaConfig *cfg = NULL;
190    int rret;
191    int ret = 0;
192
193    ctx->frame = av_frame_alloc();
194    if (!ctx->frame)
195        return AVERROR(ENOMEM);
196
197    cfg = rav1e_config_default();
198    if (!cfg) {
199        av_log(avctx, AV_LOG_ERROR, "Could not allocate rav1e config.\n");
200        return AVERROR_EXTERNAL;
201    }
202
203    /*
204     * Rav1e currently uses the time base given to it only for ratecontrol... where
205     * the inverse is taken and used as a framerate. So, do what we do in other wrappers
206     * and use the framerate if we can.
207     */
208    if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
209        rav1e_config_set_time_base(cfg, (RaRational) {
210                                   avctx->framerate.den, avctx->framerate.num
211                                   });
212    } else {
213        rav1e_config_set_time_base(cfg, (RaRational) {
214                                   avctx->time_base.num * avctx->ticks_per_frame,
215                                   avctx->time_base.den
216                                   });
217    }
218
219    if ((avctx->flags & AV_CODEC_FLAG_PASS1 || avctx->flags & AV_CODEC_FLAG_PASS2) && !avctx->bit_rate) {
220        av_log(avctx, AV_LOG_ERROR, "A bitrate must be set to use two pass mode.\n");
221        ret = AVERROR_INVALIDDATA;
222        goto end;
223    }
224
225    if (avctx->flags & AV_CODEC_FLAG_PASS2) {
226        if (!avctx->stats_in) {
227            av_log(avctx, AV_LOG_ERROR, "No stats file provided for second pass.\n");
228            ret = AVERROR(EINVAL);
229            goto end;
230        }
231
232        ctx->pass_size = (strlen(avctx->stats_in) * 3) / 4;
233        ctx->pass_data = av_malloc(ctx->pass_size);
234        if (!ctx->pass_data) {
235            av_log(avctx, AV_LOG_ERROR, "Could not allocate stats buffer.\n");
236            ret = AVERROR(ENOMEM);
237            goto end;
238        }
239
240        ctx->pass_size = av_base64_decode(ctx->pass_data, avctx->stats_in, ctx->pass_size);
241        if (ctx->pass_size < 0) {
242            av_log(avctx, AV_LOG_ERROR, "Invalid pass file.\n");
243            ret = AVERROR(EINVAL);
244            goto end;
245        }
246    }
247
248    if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
249         const AVBitStreamFilter *filter = av_bsf_get_by_name("extract_extradata");
250         int bret;
251
252         if (!filter) {
253            av_log(avctx, AV_LOG_ERROR, "extract_extradata bitstream filter "
254                   "not found. This is a bug, please report it.\n");
255            ret = AVERROR_BUG;
256            goto end;
257         }
258
259         bret = av_bsf_alloc(filter, &ctx->bsf);
260         if (bret < 0) {
261             ret = bret;
262             goto end;
263         }
264
265         bret = avcodec_parameters_from_context(ctx->bsf->par_in, avctx);
266         if (bret < 0) {
267             ret = bret;
268             goto end;
269         }
270
271         bret = av_bsf_init(ctx->bsf);
272         if (bret < 0) {
273             ret = bret;
274             goto end;
275         }
276    }
277
278    {
279        AVDictionaryEntry *en = NULL;
280        while ((en = av_dict_get(ctx->rav1e_opts, "", en, AV_DICT_IGNORE_SUFFIX))) {
281            int parse_ret = rav1e_config_parse(cfg, en->key, en->value);
282            if (parse_ret < 0)
283                av_log(avctx, AV_LOG_WARNING, "Invalid value for %s: %s.\n", en->key, en->value);
284        }
285    }
286
287    rret = rav1e_config_parse_int(cfg, "width", avctx->width);
288    if (rret < 0) {
289        av_log(avctx, AV_LOG_ERROR, "Invalid width passed to rav1e.\n");
290        ret = AVERROR_INVALIDDATA;
291        goto end;
292    }
293
294    rret = rav1e_config_parse_int(cfg, "height", avctx->height);
295    if (rret < 0) {
296        av_log(avctx, AV_LOG_ERROR, "Invalid height passed to rav1e.\n");
297        ret = AVERROR_INVALIDDATA;
298        goto end;
299    }
300
301    rret = rav1e_config_parse_int(cfg, "threads", avctx->thread_count);
302    if (rret < 0)
303        av_log(avctx, AV_LOG_WARNING, "Invalid number of threads, defaulting to auto.\n");
304
305    if (ctx->speed >= 0) {
306        rret = rav1e_config_parse_int(cfg, "speed", ctx->speed);
307        if (rret < 0) {
308            av_log(avctx, AV_LOG_ERROR, "Could not set speed preset.\n");
309            ret = AVERROR_EXTERNAL;
310            goto end;
311        }
312    }
313
314    /* rav1e handles precedence between 'tiles' and cols/rows for us. */
315    if (ctx->tiles > 0) {
316        rret = rav1e_config_parse_int(cfg, "tiles", ctx->tiles);
317        if (rret < 0) {
318            av_log(avctx, AV_LOG_ERROR, "Could not set number of tiles to encode with.\n");
319            ret = AVERROR_EXTERNAL;
320            goto end;
321        }
322    }
323    if (ctx->tile_rows > 0) {
324        rret = rav1e_config_parse_int(cfg, "tile_rows", ctx->tile_rows);
325        if (rret < 0) {
326            av_log(avctx, AV_LOG_ERROR, "Could not set number of tile rows to encode with.\n");
327            ret = AVERROR_EXTERNAL;
328            goto end;
329        }
330    }
331    if (ctx->tile_cols > 0) {
332        rret = rav1e_config_parse_int(cfg, "tile_cols", ctx->tile_cols);
333        if (rret < 0) {
334            av_log(avctx, AV_LOG_ERROR, "Could not set number of tile cols to encode with.\n");
335            ret = AVERROR_EXTERNAL;
336            goto end;
337        }
338    }
339
340    if (avctx->gop_size > 0) {
341        rret = rav1e_config_parse_int(cfg, "key_frame_interval", avctx->gop_size);
342        if (rret < 0) {
343            av_log(avctx, AV_LOG_ERROR, "Could not set max keyint.\n");
344            ret = AVERROR_EXTERNAL;
345            goto end;
346        }
347    }
348
349    if (avctx->keyint_min > 0) {
350        rret = rav1e_config_parse_int(cfg, "min_key_frame_interval", avctx->keyint_min);
351        if (rret < 0) {
352            av_log(avctx, AV_LOG_ERROR, "Could not set min keyint.\n");
353            ret = AVERROR_EXTERNAL;
354            goto end;
355        }
356    }
357
358    if (avctx->bit_rate && ctx->quantizer < 0) {
359        int max_quantizer = avctx->qmax >= 0 ? avctx->qmax : 255;
360
361        rret = rav1e_config_parse_int(cfg, "quantizer", max_quantizer);
362        if (rret < 0) {
363            av_log(avctx, AV_LOG_ERROR, "Could not set max quantizer.\n");
364            ret = AVERROR_EXTERNAL;
365            goto end;
366        }
367
368        if (avctx->qmin >= 0) {
369            rret = rav1e_config_parse_int(cfg, "min_quantizer", avctx->qmin);
370            if (rret < 0) {
371                av_log(avctx, AV_LOG_ERROR, "Could not set min quantizer.\n");
372                ret = AVERROR_EXTERNAL;
373                goto end;
374            }
375        }
376
377        rret = rav1e_config_parse_int(cfg, "bitrate", avctx->bit_rate);
378        if (rret < 0) {
379            av_log(avctx, AV_LOG_ERROR, "Could not set bitrate.\n");
380            ret = AVERROR_INVALIDDATA;
381            goto end;
382        }
383    } else if (ctx->quantizer >= 0) {
384        if (avctx->bit_rate)
385            av_log(avctx, AV_LOG_WARNING, "Both bitrate and quantizer specified. Using quantizer mode.");
386
387        rret = rav1e_config_parse_int(cfg, "quantizer", ctx->quantizer);
388        if (rret < 0) {
389            av_log(avctx, AV_LOG_ERROR, "Could not set quantizer.\n");
390            ret = AVERROR_EXTERNAL;
391            goto end;
392        }
393    }
394
395    rret = rav1e_config_set_pixel_format(cfg, desc->comp[0].depth,
396                                         pix_fmt_map(avctx->pix_fmt),
397                                         chroma_loc_map(avctx->chroma_sample_location),
398                                         range_map(avctx->pix_fmt, avctx->color_range));
399    if (rret < 0) {
400        av_log(avctx, AV_LOG_ERROR, "Failed to set pixel format properties.\n");
401        ret = AVERROR_INVALIDDATA;
402        goto end;
403    }
404
405    /* rav1e's colorspace enums match standard values. */
406    rret = rav1e_config_set_color_description(cfg, (RaMatrixCoefficients) avctx->colorspace,
407                                              (RaColorPrimaries) avctx->color_primaries,
408                                              (RaTransferCharacteristics) avctx->color_trc);
409    if (rret < 0) {
410        av_log(avctx, AV_LOG_WARNING, "Failed to set color properties.\n");
411        if (avctx->err_recognition & AV_EF_EXPLODE) {
412            ret = AVERROR_INVALIDDATA;
413            goto end;
414        }
415    }
416
417    ctx->ctx = rav1e_context_new(cfg);
418    if (!ctx->ctx) {
419        av_log(avctx, AV_LOG_ERROR, "Failed to create rav1e encode context.\n");
420        ret = AVERROR_EXTERNAL;
421        goto end;
422    }
423
424    ret = 0;
425
426end:
427
428    rav1e_config_unref(cfg);
429
430    return ret;
431}
432
433static int librav1e_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
434{
435    librav1eContext *ctx = avctx->priv_data;
436    RaFrame *rframe = ctx->rframe;
437    RaPacket *rpkt = NULL;
438    int ret;
439
440    if (!rframe) {
441        AVFrame *frame = ctx->frame;
442
443        ret = ff_encode_get_frame(avctx, frame);
444        if (ret < 0 && ret != AVERROR_EOF)
445            return ret;
446
447        if (frame->buf[0]) {
448            const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
449
450            int64_t *pts = av_malloc(sizeof(int64_t));
451            if (!pts) {
452                av_log(avctx, AV_LOG_ERROR, "Could not allocate PTS buffer.\n");
453                return AVERROR(ENOMEM);
454            }
455            *pts = frame->pts;
456
457            rframe = rav1e_frame_new(ctx->ctx);
458            if (!rframe) {
459                av_log(avctx, AV_LOG_ERROR, "Could not allocate new rav1e frame.\n");
460                av_frame_unref(frame);
461                av_freep(&pts);
462                return AVERROR(ENOMEM);
463            }
464
465            for (int i = 0; i < desc->nb_components; i++) {
466                int shift = i ? desc->log2_chroma_h : 0;
467                int bytes = desc->comp[0].depth == 8 ? 1 : 2;
468                rav1e_frame_fill_plane(rframe, i, frame->data[i],
469                                       (frame->height >> shift) * frame->linesize[i],
470                                       frame->linesize[i], bytes);
471            }
472            av_frame_unref(frame);
473            rav1e_frame_set_opaque(rframe, pts, av_free);
474        }
475    }
476
477    ret = rav1e_send_frame(ctx->ctx, rframe);
478    if (rframe)
479        if (ret == RA_ENCODER_STATUS_ENOUGH_DATA) {
480            ctx->rframe = rframe; /* Queue is full. Store the RaFrame to retry next call */
481        } else {
482            rav1e_frame_unref(rframe); /* No need to unref if flushing. */
483            ctx->rframe = NULL;
484        }
485
486    switch (ret) {
487    case RA_ENCODER_STATUS_SUCCESS:
488    case RA_ENCODER_STATUS_ENOUGH_DATA:
489        break;
490    case RA_ENCODER_STATUS_FAILURE:
491        av_log(avctx, AV_LOG_ERROR, "Could not send frame: %s\n", rav1e_status_to_str(ret));
492        return AVERROR_EXTERNAL;
493    default:
494        av_log(avctx, AV_LOG_ERROR, "Unknown return code %d from rav1e_send_frame: %s\n", ret, rav1e_status_to_str(ret));
495        return AVERROR_UNKNOWN;
496    }
497
498retry:
499
500    if (avctx->flags & AV_CODEC_FLAG_PASS1) {
501        int sret = get_stats(avctx, 0);
502        if (sret < 0)
503            return sret;
504    } else if (avctx->flags & AV_CODEC_FLAG_PASS2) {
505        int sret = set_stats(avctx);
506        if (sret < 0)
507            return sret;
508    }
509
510    ret = rav1e_receive_packet(ctx->ctx, &rpkt);
511    switch (ret) {
512    case RA_ENCODER_STATUS_SUCCESS:
513        break;
514    case RA_ENCODER_STATUS_LIMIT_REACHED:
515        if (avctx->flags & AV_CODEC_FLAG_PASS1) {
516            int sret = get_stats(avctx, 1);
517            if (sret < 0)
518                return sret;
519        }
520        return AVERROR_EOF;
521    case RA_ENCODER_STATUS_ENCODED:
522        goto retry;
523    case RA_ENCODER_STATUS_NEED_MORE_DATA:
524        if (avctx->internal->draining) {
525            av_log(avctx, AV_LOG_ERROR, "Unexpected error when receiving packet after EOF.\n");
526            return AVERROR_EXTERNAL;
527        }
528        return AVERROR(EAGAIN);
529    case RA_ENCODER_STATUS_FAILURE:
530        av_log(avctx, AV_LOG_ERROR, "Could not encode frame: %s\n", rav1e_status_to_str(ret));
531        return AVERROR_EXTERNAL;
532    default:
533        av_log(avctx, AV_LOG_ERROR, "Unknown return code %d from rav1e_receive_packet: %s\n", ret, rav1e_status_to_str(ret));
534        return AVERROR_UNKNOWN;
535    }
536
537    ret = ff_get_encode_buffer(avctx, pkt, rpkt->len, 0);
538    if (ret < 0) {
539        av_log(avctx, AV_LOG_ERROR, "Could not allocate packet.\n");
540        rav1e_packet_unref(rpkt);
541        return ret;
542    }
543
544    memcpy(pkt->data, rpkt->data, rpkt->len);
545
546    if (rpkt->frame_type == RA_FRAME_TYPE_KEY)
547        pkt->flags |= AV_PKT_FLAG_KEY;
548
549    pkt->pts = pkt->dts = *((int64_t *) rpkt->opaque);
550    av_free(rpkt->opaque);
551    rav1e_packet_unref(rpkt);
552
553    if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
554        int ret = av_bsf_send_packet(ctx->bsf, pkt);
555        if (ret < 0) {
556            av_log(avctx, AV_LOG_ERROR, "extradata extraction send failed.\n");
557            av_packet_unref(pkt);
558            return ret;
559        }
560
561        ret = av_bsf_receive_packet(ctx->bsf, pkt);
562        if (ret < 0) {
563            av_log(avctx, AV_LOG_ERROR, "extradata extraction receive failed.\n");
564            av_packet_unref(pkt);
565            return ret;
566        }
567    }
568
569    return 0;
570}
571
572#define OFFSET(x) offsetof(librav1eContext, x)
573#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
574
575static const AVOption options[] = {
576    { "qp", "use constant quantizer mode", OFFSET(quantizer), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 255, VE },
577    { "speed", "what speed preset to use", OFFSET(speed), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 10, VE },
578    { "tiles", "number of tiles encode with", OFFSET(tiles), AV_OPT_TYPE_INT, { .i64 = 0 }, -1, INT64_MAX, VE },
579    { "tile-rows", "number of tiles rows to encode with", OFFSET(tile_rows), AV_OPT_TYPE_INT, { .i64 = 0 }, -1, INT64_MAX, VE },
580    { "tile-columns", "number of tiles columns to encode with", OFFSET(tile_cols), AV_OPT_TYPE_INT, { .i64 = 0 }, -1, INT64_MAX, VE },
581    { "rav1e-params", "set the rav1e configuration using a :-separated list of key=value parameters", OFFSET(rav1e_opts), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE },
582    { NULL }
583};
584
585static const FFCodecDefault librav1e_defaults[] = {
586    { "b",           "0" },
587    { "g",           "0" },
588    { "keyint_min",  "0" },
589    { "qmax",       "-1" },
590    { "qmin",       "-1" },
591    { NULL }
592};
593
594const enum AVPixelFormat librav1e_pix_fmts[] = {
595    AV_PIX_FMT_YUV420P,
596    AV_PIX_FMT_YUVJ420P,
597    AV_PIX_FMT_YUV420P10,
598    AV_PIX_FMT_YUV420P12,
599    AV_PIX_FMT_YUV422P,
600    AV_PIX_FMT_YUVJ422P,
601    AV_PIX_FMT_YUV422P10,
602    AV_PIX_FMT_YUV422P12,
603    AV_PIX_FMT_YUV444P,
604    AV_PIX_FMT_YUVJ444P,
605    AV_PIX_FMT_YUV444P10,
606    AV_PIX_FMT_YUV444P12,
607    AV_PIX_FMT_NONE
608};
609
610static const AVClass class = {
611    .class_name = "librav1e",
612    .item_name  = av_default_item_name,
613    .option     = options,
614    .version    = LIBAVUTIL_VERSION_INT,
615};
616
617const FFCodec ff_librav1e_encoder = {
618    .p.name         = "librav1e",
619    .p.long_name    = NULL_IF_CONFIG_SMALL("librav1e AV1"),
620    .p.type         = AVMEDIA_TYPE_VIDEO,
621    .p.id           = AV_CODEC_ID_AV1,
622    .init           = librav1e_encode_init,
623    FF_CODEC_RECEIVE_PACKET_CB(librav1e_receive_packet),
624    .close          = librav1e_encode_close,
625    .priv_data_size = sizeof(librav1eContext),
626    .p.priv_class   = &class,
627    .defaults       = librav1e_defaults,
628    .p.pix_fmts     = librav1e_pix_fmts,
629    .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS |
630                      AV_CODEC_CAP_DR1,
631    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_AUTO_THREADS,
632    .p.wrapper_name = "librav1e",
633};
634