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
37
40
44
48
56
60 #if FF_API_REORDERED_OPAQUE
61 int64_t reordered_opaque;
62 #endif
63
67
69 {
74 return RA_PIXEL_RANGE_FULL;
75 }
76
77 switch (range) {
79 return RA_PIXEL_RANGE_FULL;
81 default:
82 return RA_PIXEL_RANGE_LIMITED;
83 }
84 }
85
87 {
93 return RA_CHROMA_SAMPLING_CS420;
98 return RA_CHROMA_SAMPLING_CS422;
103 return RA_CHROMA_SAMPLING_CS444;
104 default:
106 }
107 }
108
110 {
111 switch (chroma_loc) {
113 return RA_CHROMA_SAMPLE_POSITION_VERTICAL;
115 return RA_CHROMA_SAMPLE_POSITION_COLOCATED;
116 default:
117 return RA_CHROMA_SAMPLE_POSITION_UNKNOWN;
118 }
119 }
120
122 {
124 RaData* buf = rav1e_twopass_out(
ctx->ctx);
125 if (!buf)
126 return 0;
127
128 if (!eos) {
130 ctx->pass_pos + buf->len);
132 rav1e_data_unref(buf);
134 }
135
137 memcpy(
ctx->pass_data +
ctx->pass_pos, buf->data, buf->len);
138 ctx->pass_pos += buf->len;
139 } else {
141
142 memcpy(
ctx->pass_data, buf->data, buf->len);
143
146 rav1e_data_unref(buf);
148 }
149
151
153 }
154
155 rav1e_data_unref(buf);
156
157 return 0;
158 }
159
161 {
164
165 while (
ret > 0 &&
ctx->pass_size -
ctx->pass_pos > 0) {
166 ret = rav1e_twopass_in(
ctx->ctx,
ctx->pass_data +
ctx->pass_pos,
ctx->pass_size);
170 }
171
172 return 0;
173 }
174
176 {
178
180 rav1e_context_unref(
ctx->ctx);
182 }
184 rav1e_frame_unref(
ctx->rframe);
186 }
187
190
191 return 0;
192 }
193
195 {
198 RaConfig *cfg =
NULL;
199 int rret;
201
205
206 cfg = rav1e_config_default();
207 if (!cfg) {
210 }
211
212 /*
213 * Rav1e currently uses the time base given to it only for ratecontrol... where
214 * the inverse is taken and used as a framerate. So, do what we do in other wrappers
215 * and use the framerate if we can.
216 */
218 rav1e_config_set_time_base(cfg, (RaRational) {
220 });
221 } else {
222 rav1e_config_set_time_base(cfg, (RaRational) {
225 });
226 }
227
231 goto end;
232 }
233
238 goto end;
239 }
240
241 ctx->pass_size = (strlen(avctx->
stats_in) * 3) / 4;
243 if (!
ctx->pass_data) {
246 goto end;
247 }
248
250 if (
ctx->pass_size < 0) {
253 goto end;
254 }
255 }
256
257 {
260 if (rav1e_config_parse(cfg, en->
key, en->
value) < 0)
262 }
263 }
264
265 rret = rav1e_config_parse_int(cfg,
"width", avctx->
width);
266 if (rret < 0) {
269 goto end;
270 }
271
272 rret = rav1e_config_parse_int(cfg,
"height", avctx->
height);
273 if (rret < 0) {
276 goto end;
277 }
278
280 rav1e_config_set_sample_aspect_ratio(cfg, (RaRational) {
283 });
284
285 rret = rav1e_config_parse_int(cfg,
"threads", avctx->
thread_count);
286 if (rret < 0)
288
289 if (
ctx->speed >= 0) {
290 rret = rav1e_config_parse_int(cfg,
"speed",
ctx->speed);
291 if (rret < 0) {
294 goto end;
295 }
296 }
297
298 /* rav1e handles precedence between 'tiles' and cols/rows for us. */
299 if (
ctx->tiles > 0) {
300 rret = rav1e_config_parse_int(cfg,
"tiles",
ctx->tiles);
301 if (rret < 0) {
304 goto end;
305 }
306 }
307 if (
ctx->tile_rows > 0) {
308 rret = rav1e_config_parse_int(cfg,
"tile_rows",
ctx->tile_rows);
309 if (rret < 0) {
312 goto end;
313 }
314 }
315 if (
ctx->tile_cols > 0) {
316 rret = rav1e_config_parse_int(cfg,
"tile_cols",
ctx->tile_cols);
317 if (rret < 0) {
320 goto end;
321 }
322 }
323
325 rret = rav1e_config_parse_int(cfg,
"key_frame_interval", avctx->
gop_size);
326 if (rret < 0) {
329 goto end;
330 }
331 }
332
334 rret = rav1e_config_parse_int(cfg,
"min_key_frame_interval", avctx->
keyint_min);
335 if (rret < 0) {
338 goto end;
339 }
340 }
341
343 int max_quantizer = avctx->
qmax >= 0 ? avctx->
qmax : 255;
344
345 rret = rav1e_config_parse_int(cfg, "quantizer", max_quantizer);
346 if (rret < 0) {
349 goto end;
350 }
351
352 if (avctx->
qmin >= 0) {
353 rret = rav1e_config_parse_int(cfg,
"min_quantizer", avctx->
qmin);
354 if (rret < 0) {
357 goto end;
358 }
359 }
360
361 rret = rav1e_config_parse_int(cfg,
"bitrate", avctx->
bit_rate);
362 if (rret < 0) {
365 goto end;
366 }
367 }
else if (
ctx->quantizer >= 0) {
370
371 rret = rav1e_config_parse_int(cfg,
"quantizer",
ctx->quantizer);
372 if (rret < 0) {
375 goto end;
376 }
377 }
378
379 rret = rav1e_config_set_pixel_format(cfg,
desc->comp[0].depth,
383 if (rret < 0) {
386 goto end;
387 }
388
389 /* rav1e's colorspace enums match standard values. */
390 rret = rav1e_config_set_color_description(cfg, (RaMatrixCoefficients) avctx->
colorspace,
392 (RaTransferCharacteristics) avctx->
color_trc);
393 if (rret < 0) {
397 goto end;
398 }
399 }
400
401 ctx->ctx = rav1e_context_new(cfg);
405 goto end;
406 }
407
409 RaData *seq_hdr = rav1e_container_sequence_header(
ctx->ctx);
410
411 if (seq_hdr)
414 rav1e_data_unref(seq_hdr);
417 goto end;
418 }
419
420 memcpy(avctx->
extradata, seq_hdr->data, seq_hdr->len);
422 rav1e_data_unref(seq_hdr);
423 }
424
426
427 end:
428
429 rav1e_config_unref(cfg);
430
432 }
433
435 {
437
438 if (!fd)
439 return;
440
443 }
444
446 {
448 RaFrame *rframe =
ctx->rframe;
449 RaPacket *rpkt =
NULL;
452
453 if (!rframe) {
455
459
462
464 if (!fd) {
467 }
470 #if FF_API_REORDERED_OPAQUE
472 fd->reordered_opaque =
frame->reordered_opaque;
474 #endif
475
483 }
484 }
485
486 rframe = rav1e_frame_new(
ctx->ctx);
487 if (!rframe) {
492 }
493
494 for (
int i = 0;
i <
desc->nb_components;
i++) {
496 int bytes =
desc->comp[0].depth == 8 ? 1 : 2;
497 rav1e_frame_fill_plane(rframe,
i,
frame->data[
i],
499 frame->linesize[
i], bytes);
500 }
503 }
504 }
505
506 ret = rav1e_send_frame(
ctx->ctx, rframe);
507 if (rframe)
508 if (
ret == RA_ENCODER_STATUS_ENOUGH_DATA) {
509 ctx->rframe = rframe;
/* Queue is full. Store the RaFrame to retry next call */
510 } else {
511 rav1e_frame_unref(rframe); /* No need to unref if flushing. */
513 }
514
516 case RA_ENCODER_STATUS_SUCCESS:
517 case RA_ENCODER_STATUS_ENOUGH_DATA:
518 break;
519 case RA_ENCODER_STATUS_FAILURE:
522 default:
525 }
526
527 retry:
528
531 if (sret < 0)
532 return sret;
535 if (sret < 0)
536 return sret;
537 }
538
539 ret = rav1e_receive_packet(
ctx->ctx, &rpkt);
541 case RA_ENCODER_STATUS_SUCCESS:
542 break;
543 case RA_ENCODER_STATUS_LIMIT_REACHED:
546 if (sret < 0)
547 return sret;
548 }
550 case RA_ENCODER_STATUS_ENCODED:
551 goto retry;
552 case RA_ENCODER_STATUS_NEED_MORE_DATA:
556 }
558 case RA_ENCODER_STATUS_FAILURE:
561 default:
562 av_log(avctx,
AV_LOG_ERROR,
"Unknown return code %d from rav1e_receive_packet: %s\n",
ret, rav1e_status_to_str(
ret));
564 }
565
569 rav1e_packet_unref(rpkt);
571 }
572
573 memcpy(
pkt->
data, rpkt->data, rpkt->len);
574
575 if (rpkt->frame_type == RA_FRAME_TYPE_KEY)
577
578 fd = rpkt->opaque;
581 #if FF_API_REORDERED_OPAQUE
583 avctx->reordered_opaque = fd->reordered_opaque;
585 #endif
586
591 }
592
594
599
601
605
608 rav1e_packet_unref(rpkt);
610 }
611
612 for (
int i = 0;
i <
desc->nb_components;
i++) {
614 rav1e_frame_extract_plane(rpkt->rec,
i,
frame->data[
i],
617 }
618 }
619
620 rav1e_packet_unref(rpkt);
621
622 return 0;
623 }
624
625 #define OFFSET(x) offsetof(librav1eContext, x)
626 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
627
634 {
"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 },
636 };
637
639 { "b", "0" },
640 { "g", "0" },
641 { "keyint_min", "0" },
642 { "qmax", "-1" },
643 { "qmin", "-1" },
645 };
646
661 };
662
668 };
669
671 .
p.
name =
"librav1e",
679 .p.priv_class = &class,
687 .p.wrapper_name = "librav1e",
688 };