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