1 /*
2 * Copyright (c) 2010, Google, Inc.
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 /**
22 * @file
23 * AV1 encoder support via libaom
24 */
25
26 #define AOM_DISABLE_CTRL_TYPECHECKS 1
27 #include <aom/aom_encoder.h>
28 #include <aom/aomcx.h>
29
37
45
46 /*
47 * Portion of struct aom_codec_cx_pkt from aom_encoder.h.
48 * One encoded frame returned from the library.
49 */
51 void *
buf;
/**< compressed data buffer */
52 size_t sz;
/**< length of compressed data */
53 int64_t
pts;
/**< time stamp to show frame
54 (in timebase units) */
55 unsigned long duration;
/**< duration to show frame
56 (in timebase units) */
57 uint32_t
flags;
/**< flags for this frame */
59 int have_sse;
/**< true if we have pending sse[] */
62 };
63
84 int have_sse;
/**< true if we have pending sse[] */
131 } AOMContext;
132
134 [AOME_SET_CPUUSED] = "AOME_SET_CPUUSED",
135 [AOME_SET_CQ_LEVEL] = "AOME_SET_CQ_LEVEL",
136 [AOME_SET_ENABLEAUTOALTREF] = "AOME_SET_ENABLEAUTOALTREF",
137 [AOME_SET_ARNR_MAXFRAMES] = "AOME_SET_ARNR_MAXFRAMES",
138 [AOME_SET_ARNR_STRENGTH] = "AOME_SET_ARNR_STRENGTH",
139 [AOME_SET_STATIC_THRESHOLD] = "AOME_SET_STATIC_THRESHOLD",
140 [AV1E_SET_COLOR_RANGE] = "AV1E_SET_COLOR_RANGE",
141 [AV1E_SET_COLOR_PRIMARIES] = "AV1E_SET_COLOR_PRIMARIES",
142 [AV1E_SET_MATRIX_COEFFICIENTS] = "AV1E_SET_MATRIX_COEFFICIENTS",
143 [AV1E_SET_TRANSFER_CHARACTERISTICS] = "AV1E_SET_TRANSFER_CHARACTERISTICS",
144 [AV1E_SET_AQ_MODE] = "AV1E_SET_AQ_MODE",
145 [AV1E_SET_FRAME_PARALLEL_DECODING] = "AV1E_SET_FRAME_PARALLEL_DECODING",
146 [AV1E_SET_SUPERBLOCK_SIZE] = "AV1E_SET_SUPERBLOCK_SIZE",
147 [AV1E_SET_TILE_COLUMNS] = "AV1E_SET_TILE_COLUMNS",
148 [AV1E_SET_TILE_ROWS] = "AV1E_SET_TILE_ROWS",
149 [AV1E_SET_ENABLE_RESTORATION] = "AV1E_SET_ENABLE_RESTORATION",
150 #ifdef AOM_CTRL_AV1E_SET_ROW_MT
151 [AV1E_SET_ROW_MT] = "AV1E_SET_ROW_MT",
152 #endif
153 #ifdef AOM_CTRL_AV1E_SET_DENOISE_NOISE_LEVEL
154 [AV1E_SET_DENOISE_NOISE_LEVEL] = "AV1E_SET_DENOISE_NOISE_LEVEL",
155 #endif
156 #ifdef AOM_CTRL_AV1E_SET_DENOISE_BLOCK_SIZE
157 [AV1E_SET_DENOISE_BLOCK_SIZE] = "AV1E_SET_DENOISE_BLOCK_SIZE",
158 #endif
159 #ifdef AOM_CTRL_AV1E_SET_MAX_REFERENCE_FRAMES
160 [AV1E_SET_MAX_REFERENCE_FRAMES] = "AV1E_SET_MAX_REFERENCE_FRAMES",
161 #endif
162 #ifdef AOM_CTRL_AV1E_SET_ENABLE_GLOBAL_MOTION
163 [AV1E_SET_ENABLE_GLOBAL_MOTION] = "AV1E_SET_ENABLE_GLOBAL_MOTION",
164 #endif
165 #ifdef AOM_CTRL_AV1E_SET_ENABLE_INTRABC
166 [AV1E_SET_ENABLE_INTRABC] = "AV1E_SET_ENABLE_INTRABC",
167 #endif
168 [AV1E_SET_ENABLE_CDEF] = "AV1E_SET_ENABLE_CDEF",
169 [AOME_SET_TUNING] = "AOME_SET_TUNING",
170 #if AOM_ENCODER_ABI_VERSION >= 22
171 [AV1E_SET_ENABLE_1TO4_PARTITIONS] = "AV1E_SET_ENABLE_1TO4_PARTITIONS",
172 [AV1E_SET_ENABLE_AB_PARTITIONS] = "AV1E_SET_ENABLE_AB_PARTITIONS",
173 [AV1E_SET_ENABLE_RECT_PARTITIONS] = "AV1E_SET_ENABLE_RECT_PARTITIONS",
174 [AV1E_SET_ENABLE_ANGLE_DELTA] = "AV1E_SET_ENABLE_ANGLE_DELTA",
175 [AV1E_SET_ENABLE_CFL_INTRA] = "AV1E_SET_ENABLE_CFL_INTRA",
176 [AV1E_SET_ENABLE_FILTER_INTRA] = "AV1E_SET_ENABLE_FILTER_INTRA",
177 [AV1E_SET_ENABLE_INTRA_EDGE_FILTER] = "AV1E_SET_ENABLE_INTRA_EDGE_FILTER",
178 [AV1E_SET_ENABLE_PAETH_INTRA] = "AV1E_SET_ENABLE_PAETH_INTRA",
179 [AV1E_SET_ENABLE_SMOOTH_INTRA] = "AV1E_SET_ENABLE_SMOOTH_INTRA",
180 [AV1E_SET_ENABLE_PALETTE] = "AV1E_SET_ENABLE_PALETTE",
181 [AV1E_SET_ENABLE_FLIP_IDTX] = "AV1E_SET_ENABLE_FLIP_IDTX",
182 [AV1E_SET_ENABLE_TX64] = "AV1E_SET_ENABLE_TX64",
183 [AV1E_SET_INTRA_DCT_ONLY] = "AV1E_SET_INTRA_DCT_ONLY",
184 [AV1E_SET_INTER_DCT_ONLY] = "AV1E_SET_INTER_DCT_ONLY",
185 [AV1E_SET_INTRA_DEFAULT_TX_ONLY] = "AV1E_SET_INTRA_DEFAULT_TX_ONLY",
186 [AV1E_SET_REDUCED_TX_TYPE_SET] = "AV1E_SET_REDUCED_TX_TYPE_SET",
187 [AV1E_SET_ENABLE_DIFF_WTD_COMP] = "AV1E_SET_ENABLE_DIFF_WTD_COMP",
188 [AV1E_SET_ENABLE_DIST_WTD_COMP] = "AV1E_SET_ENABLE_DIST_WTD_COMP",
189 [AV1E_SET_ENABLE_DUAL_FILTER] = "AV1E_SET_ENABLE_DUAL_FILTER",
190 [AV1E_SET_ENABLE_INTERINTER_WEDGE] = "AV1E_SET_ENABLE_INTERINTER_WEDGE",
191 [AV1E_SET_ENABLE_INTERINTRA_WEDGE] = "AV1E_SET_ENABLE_INTERINTRA_WEDGE",
192 [AV1E_SET_ENABLE_MASKED_COMP] = "AV1E_SET_ENABLE_MASKED_COMP",
193 [AV1E_SET_ENABLE_INTERINTRA_COMP] = "AV1E_SET_ENABLE_INTERINTRA_COMP",
194 [AV1E_SET_ENABLE_OBMC] = "AV1E_SET_ENABLE_OBMC",
195 [AV1E_SET_ENABLE_ONESIDED_COMP] = "AV1E_SET_ENABLE_ONESIDED_COMP",
196 [AV1E_SET_REDUCED_REFERENCE_SET] = "AV1E_SET_REDUCED_REFERENCE_SET",
197 [AV1E_SET_ENABLE_SMOOTH_INTERINTRA] = "AV1E_SET_ENABLE_SMOOTH_INTERINTRA",
198 [AV1E_SET_ENABLE_REF_FRAME_MVS] = "AV1E_SET_ENABLE_REF_FRAME_MVS",
199 #endif
200 };
201
203 {
205 const char *
error = aom_codec_error(&
ctx->encoder);
206 const char *detail = aom_codec_error_detail(&
ctx->encoder);
207
209 if (detail)
211 }
212
214 const struct aom_codec_enc_cfg *cfg,
216 {
218
221 " %*s%u\n %*s%u\n %*s%u\n %*s%u\n %*s%u\n"
222 " %*s%u\n %*s%u\n"
223 " %*s{%u/%u}\n %*s%u\n %*s%d\n %*s%u\n",
224 width,
"g_usage:", cfg->g_usage,
225 width,
"g_threads:", cfg->g_threads,
226 width,
"g_profile:", cfg->g_profile,
227 width,
"g_w:", cfg->g_w,
228 width,
"g_h:", cfg->g_h,
229 width,
"g_bit_depth:", cfg->g_bit_depth,
230 width,
"g_input_bit_depth:", cfg->g_input_bit_depth,
231 width,
"g_timebase:", cfg->g_timebase.num, cfg->g_timebase.den,
232 width,
"g_error_resilient:", cfg->g_error_resilient,
233 width,
"g_pass:", cfg->g_pass,
234 width,
"g_lag_in_frames:", cfg->g_lag_in_frames);
237 width,
"rc_dropframe_thresh:", cfg->rc_dropframe_thresh,
238 width,
"rc_end_usage:", cfg->rc_end_usage,
239 width,
"rc_twopass_stats_in:", cfg->rc_twopass_stats_in.buf, cfg->rc_twopass_stats_in.sz,
240 width,
"rc_target_bitrate:", cfg->rc_target_bitrate);
242 " %*s%u\n %*s%u\n",
243 width,
"rc_min_quantizer:", cfg->rc_min_quantizer,
244 width,
"rc_max_quantizer:", cfg->rc_max_quantizer);
246 " %*s%u\n %*s%u\n",
247 width,
"rc_undershoot_pct:", cfg->rc_undershoot_pct,
248 width,
"rc_overshoot_pct:", cfg->rc_overshoot_pct);
250 " %*s%u\n %*s%u\n %*s%u\n",
251 width,
"rc_buf_sz:", cfg->rc_buf_sz,
252 width,
"rc_buf_initial_sz:", cfg->rc_buf_initial_sz,
253 width,
"rc_buf_optimal_sz:", cfg->rc_buf_optimal_sz);
254 av_log(avctx,
level,
"2 pass rate control settings\n"
255 " %*s%u\n %*s%u\n %*s%u\n",
256 width,
"rc_2pass_vbr_bias_pct:", cfg->rc_2pass_vbr_bias_pct,
257 width,
"rc_2pass_vbr_minsection_pct:", cfg->rc_2pass_vbr_minsection_pct,
258 width,
"rc_2pass_vbr_maxsection_pct:", cfg->rc_2pass_vbr_maxsection_pct);
260 " %*s%d\n %*s%u\n %*s%u\n",
261 width,
"kf_mode:", cfg->kf_mode,
262 width,
"kf_min_dist:", cfg->kf_min_dist,
263 width,
"kf_max_dist:", cfg->kf_max_dist);
265 " %*s%d\n %*s%d\n",
266 width,
"tile_width_count:", cfg->tile_width_count,
267 width,
"tile_height_count:", cfg->tile_height_count);
269 }
270
272 {
274
275 while (*p)
277 *p = cx_frame;
279 }
280
282 {
285 }
286
288 {
290
291 while (p) {
295 }
296 }
297
299 #ifdef UENUM1BYTE
300 aome_enc_control_id id,
301 #else
302 enum aome_enc_control_id id,
303 #endif
305 {
309 int res;
310
313
314 res = aom_codec_control(&
ctx->encoder,
id,
val);
315 if (res != AOM_CODEC_OK) {
320 }
321
322 return 0;
323 }
324
326 {
328
329 aom_codec_destroy(&
ctx->encoder);
334 return 0;
335 }
336
338 struct aom_codec_enc_cfg *enccfg, aom_codec_flags_t *
flags,
339 aom_img_fmt_t *img_fmt)
340 {
343 enccfg->g_bit_depth = enccfg->g_input_bit_depth =
desc->comp[0].depth;
346 enccfg->monochrome = 1;
347 /* Fall-through */
350 *img_fmt = AOM_IMG_FMT_I420;
351 return 0;
354 *img_fmt = AOM_IMG_FMT_I422;
355 return 0;
359 *img_fmt = AOM_IMG_FMT_I444;
360 return 0;
363 enccfg->monochrome = 1;
364 /* Fall-through */
367 if (codec_caps & AOM_CODEC_CAP_HIGHBITDEPTH) {
368 enccfg->g_profile =
370 *img_fmt = AOM_IMG_FMT_I42016;
371 *
flags |= AOM_CODEC_USE_HIGHBITDEPTH;
372 return 0;
373 }
374 break;
377 if (codec_caps & AOM_CODEC_CAP_HIGHBITDEPTH) {
379 *img_fmt = AOM_IMG_FMT_I42216;
380 *
flags |= AOM_CODEC_USE_HIGHBITDEPTH;
381 return 0;
382 }
383 break;
388 if (codec_caps & AOM_CODEC_CAP_HIGHBITDEPTH) {
389 enccfg->g_profile =
391 *img_fmt = AOM_IMG_FMT_I44416;
392 *
flags |= AOM_CODEC_USE_HIGHBITDEPTH;
393 return 0;
394 }
395 break;
396 default:
397 break;
398 }
401 }
402
404 {
405 aom_color_range_t aom_cr;
410 default:
413 return;
414 }
415
417 }
418
420 {
421 int sb_dim = (
dim + sb_size - 1) / sb_size;
422 int tile_dim = (sb_dim + (1 << tiles_log2) - 1) >> tiles_log2;
424 return (sb_dim + tile_dim - 1) / tile_dim;
425 }
426
428 struct aom_codec_enc_cfg *enccfg)
429 {
431 int sb_128x128_possible, sb_size, sb_width, sb_height;
432 int uniform_rows, uniform_cols;
433 int uniform_64x64_possible, uniform_128x128_possible;
434 int tile_size, rounding,
i;
435
436 if (
ctx->tile_cols_log2 >= 0)
437 ctx->tile_cols = 1 <<
ctx->tile_cols_log2;
438 if (
ctx->tile_rows_log2 >= 0)
439 ctx->tile_rows = 1 <<
ctx->tile_rows_log2;
440
441 if (
ctx->tile_cols == 0) {
444 if (
ctx->tile_cols > 1) {
446 "columns to fill width.\n",
ctx->tile_cols);
447 }
448 }
450 if (
ctx->tile_rows == 0) {
451 int max_tile_width =
453 ctx->tile_cols - 1) /
ctx->tile_cols, 128);
457 if (
ctx->tile_rows > 1) {
459 "rows to fill area.\n",
ctx->tile_rows);
460 }
461 }
463
464 if ((avctx->
width + 63) / 64 <
ctx->tile_cols ||
465 (avctx->
height + 63) / 64 <
ctx->tile_rows) {
467 "large enough to fit specified tile arrangement.\n");
469 }
473 "not allow more than %dx%d tiles.\n",
476 }
479 "not allow tiles of width greater than %d.\n",
482 }
483
484 ctx->superblock_size = AOM_SUPERBLOCK_SIZE_DYNAMIC;
485
486 if (
ctx->tile_cols == 1 &&
ctx->tile_rows == 1) {
488 return 0;
489 }
490
491 sb_128x128_possible =
492 (avctx->
width + 127) / 128 >=
ctx->tile_cols &&
493 (avctx->
height + 127) / 128 >=
ctx->tile_rows;
494
495 ctx->tile_cols_log2 =
ctx->tile_cols == 1 ? 0 :
497 ctx->tile_rows_log2 =
ctx->tile_rows == 1 ? 0 :
499
501 64,
ctx->tile_cols_log2);
503 64,
ctx->tile_rows_log2);
505 "-> %dx%d tiles.\n", uniform_cols, uniform_rows);
506 uniform_64x64_possible = uniform_cols ==
ctx->tile_cols &&
507 uniform_rows ==
ctx->tile_rows;
508
509 if (sb_128x128_possible) {
511 128,
ctx->tile_cols_log2);
513 128,
ctx->tile_rows_log2);
515 "-> %dx%d tiles.\n", uniform_cols, uniform_rows);
516 uniform_128x128_possible = uniform_cols ==
ctx->tile_cols &&
517 uniform_rows ==
ctx->tile_rows;
518 } else {
520 uniform_128x128_possible = 0;
521 }
522
523 ctx->uniform_tiles = 1;
524 if (uniform_64x64_possible && uniform_128x128_possible) {
526 "superblocks (tile_cols_log2 = %d, tile_rows_log2 = %d).\n",
527 ctx->tile_cols_log2,
ctx->tile_rows_log2);
528 return 0;
529 }
530 if (uniform_64x64_possible && !sb_128x128_possible) {
532 "superblocks (tile_cols_log2 = %d, tile_rows_log2 = %d).\n",
533 ctx->tile_cols_log2,
ctx->tile_rows_log2);
534 ctx->superblock_size = AOM_SUPERBLOCK_SIZE_64X64;
535 return 0;
536 }
537 if (uniform_128x128_possible) {
539 "superblocks (tile_cols_log2 = %d, tile_rows_log2 = %d).\n",
540 ctx->tile_cols_log2,
ctx->tile_rows_log2);
541 ctx->superblock_size = AOM_SUPERBLOCK_SIZE_128X128;
542 return 0;
543 }
544 ctx->uniform_tiles = 0;
545
546 if (sb_128x128_possible) {
547 sb_size = 128;
548 ctx->superblock_size = AOM_SUPERBLOCK_SIZE_128X128;
549 } else {
550 sb_size = 64;
551 ctx->superblock_size = AOM_SUPERBLOCK_SIZE_64X64;
552 }
554 "superblocks (tile_cols = %d, tile_rows = %d).\n",
555 sb_size, sb_size,
ctx->tile_cols,
ctx->tile_rows);
556
557 enccfg->tile_width_count =
ctx->tile_cols;
558 enccfg->tile_height_count =
ctx->tile_rows;
559
560 sb_width = (avctx->
width + sb_size - 1) / sb_size;
561 sb_height = (avctx->
height + sb_size - 1) / sb_size;
562
563 tile_size = sb_width /
ctx->tile_cols;
564 rounding = sb_width %
ctx->tile_cols;
565 for (
i = 0;
i <
ctx->tile_cols;
i++) {
566 enccfg->tile_widths[
i] = tile_size +
568 i >
ctx->tile_cols - 1 - (rounding + 1) / 2);
569 }
570
571 tile_size = sb_height /
ctx->tile_rows;
572 rounding = sb_height %
ctx->tile_rows;
573 for (
i = 0;
i <
ctx->tile_rows;
i++) {
574 enccfg->tile_heights[
i] = tile_size +
576 i >
ctx->tile_rows - 1 - (rounding + 1) / 2);
577 }
578
579 return 0;
580 }
581
583 const struct aom_codec_iface *iface)
584 {
587 struct aom_codec_enc_cfg enccfg = { 0 };
588 #ifdef AOM_FRAME_IS_INTRAONLY
589 aom_codec_flags_t
flags =
591 #else
592 aom_codec_flags_t
flags = 0;
593 #endif
595 int res;
596 aom_img_fmt_t img_fmt;
597 aom_codec_caps_t codec_caps = aom_codec_get_caps(iface);
598
601
602 if ((res = aom_codec_enc_config_default(iface, &enccfg,
ctx->usage)) != AOM_CODEC_OK) {
604 aom_codec_err_to_string(res));
606 }
607
610
615 }
616
618
619 enccfg.g_w = avctx->
width;
620 enccfg.g_h = avctx->
height;
623 enccfg.g_threads =
625
626 if (
ctx->lag_in_frames >= 0)
627 enccfg.g_lag_in_frames =
ctx->lag_in_frames;
628
630 enccfg.g_pass = AOM_RC_FIRST_PASS;
632 enccfg.g_pass = AOM_RC_LAST_PASS;
633 else
634 enccfg.g_pass = AOM_RC_ONE_PASS;
635
638 enccfg.rc_end_usage = AOM_CBR;
639 }
else if (
ctx->crf >= 0) {
640 enccfg.rc_end_usage = AOM_CQ;
642 enccfg.rc_end_usage = AOM_Q;
643 }
644
648 } else if (enccfg.rc_end_usage != AOM_Q) {
649 enccfg.rc_end_usage = AOM_Q;
652 "Neither bitrate nor constrained quality specified, using default CRF of %d\n",
654 }
655
656 if (avctx->
qmin >= 0)
657 enccfg.rc_min_quantizer = avctx->
qmin;
658 if (avctx->
qmax >= 0) {
659 enccfg.rc_max_quantizer = avctx->
qmax;
660 }
else if (!
ctx->crf) {
661 enccfg.rc_max_quantizer = 0;
662 }
663
664 if (enccfg.rc_end_usage == AOM_CQ || enccfg.rc_end_usage == AOM_Q) {
665 if (
ctx->crf < enccfg.rc_min_quantizer ||
ctx->crf > enccfg.rc_max_quantizer) {
667 "CQ level %d must be between minimum and maximum quantizer value (%d-%d)\n",
668 ctx->crf, enccfg.rc_min_quantizer, enccfg.rc_max_quantizer);
670 }
671 }
672
673 enccfg.rc_dropframe_thresh =
ctx->drop_threshold;
674
675 // 0-100 (0 => CBR, 100 => VBR)
677 if (
ctx->minsection_pct >= 0)
678 enccfg.rc_2pass_vbr_minsection_pct =
ctx->minsection_pct;
680 enccfg.rc_2pass_vbr_minsection_pct =
682 if (
ctx->maxsection_pct >= 0)
683 enccfg.rc_2pass_vbr_maxsection_pct =
ctx->maxsection_pct;
685 enccfg.rc_2pass_vbr_maxsection_pct =
687
689 enccfg.rc_buf_sz =
692 enccfg.rc_buf_initial_sz =
694 enccfg.rc_buf_optimal_sz = enccfg.rc_buf_sz * 5 / 6;
695
696 if (
ctx->rc_undershoot_pct >= 0)
697 enccfg.rc_undershoot_pct =
ctx->rc_undershoot_pct;
698 if (
ctx->rc_overshoot_pct >= 0)
699 enccfg.rc_overshoot_pct =
ctx->rc_overshoot_pct;
700
701 // _enc_init() will balk if kf_min_dist differs from max w/AOM_KF_AUTO
705 enccfg.kf_max_dist = avctx->
gop_size;
706
707 if (enccfg.g_pass == AOM_RC_FIRST_PASS)
708 enccfg.g_lag_in_frames = 0;
709 else if (enccfg.g_pass == AOM_RC_LAST_PASS) {
710 int decode_size,
ret;
711
715 }
716
717 ctx->twopass_stats.sz = strlen(avctx->
stats_in) * 3 / 4;
722 ctx->twopass_stats.sz);
723 ctx->twopass_stats.sz = 0;
725 }
727 ctx->twopass_stats.sz);
728 if (decode_size < 0) {
731 }
732
733 ctx->twopass_stats.sz = decode_size;
734 enccfg.rc_twopass_stats_in =
ctx->twopass_stats;
735 }
736
737 /* 0-3: For non-zero values the encoder increasingly optimizes for reduced
738 * complexity playback on low powered devices at the expense of encode
739 * quality. */
741 enccfg.g_profile = avctx->
profile;
742
743 enccfg.g_error_resilient =
ctx->error_resilient;
744
746 if (res < 0)
747 return res;
748
749 /* Construct Encoder Context */
750 res = aom_codec_enc_init(&
ctx->encoder, iface, &enccfg,
flags);
751 if (res != AOM_CODEC_OK) {
755 }
757
758 // codec control failures are currently treated only as warnings
761 if (
ctx->auto_alt_ref >= 0)
763 if (
ctx->arnr_max_frames >= 0)
765 if (
ctx->arnr_strength >= 0)
767 if (
ctx->enable_cdef >= 0)
769 if (
ctx->enable_restoration >= 0)
770 codecctl_int(avctx, AV1E_SET_ENABLE_RESTORATION,
ctx->enable_restoration);
771 #if AOM_ENCODER_ABI_VERSION >= 22
772 if (
ctx->enable_rect_partitions >= 0)
773 codecctl_int(avctx, AV1E_SET_ENABLE_RECT_PARTITIONS,
ctx->enable_rect_partitions);
774 if (
ctx->enable_1to4_partitions >= 0)
775 codecctl_int(avctx, AV1E_SET_ENABLE_1TO4_PARTITIONS,
ctx->enable_1to4_partitions);
776 if (
ctx->enable_ab_partitions >= 0)
777 codecctl_int(avctx, AV1E_SET_ENABLE_AB_PARTITIONS,
ctx->enable_ab_partitions);
778 if (
ctx->enable_angle_delta >= 0)
779 codecctl_int(avctx, AV1E_SET_ENABLE_ANGLE_DELTA,
ctx->enable_angle_delta);
780 if (
ctx->enable_cfl_intra >= 0)
782 if (
ctx->enable_filter_intra >= 0)
783 codecctl_int(avctx, AV1E_SET_ENABLE_FILTER_INTRA,
ctx->enable_filter_intra);
784 if (
ctx->enable_intra_edge_filter >= 0)
785 codecctl_int(avctx, AV1E_SET_ENABLE_INTRA_EDGE_FILTER,
ctx->enable_intra_edge_filter);
786 if (
ctx->enable_paeth_intra >= 0)
787 codecctl_int(avctx, AV1E_SET_ENABLE_PAETH_INTRA,
ctx->enable_paeth_intra);
788 if (
ctx->enable_smooth_intra >= 0)
789 codecctl_int(avctx, AV1E_SET_ENABLE_SMOOTH_INTRA,
ctx->enable_smooth_intra);
790 if (
ctx->enable_palette >= 0)
792 if (
ctx->enable_tx64 >= 0)
794 if (
ctx->enable_flip_idtx >= 0)
796 if (
ctx->use_intra_dct_only >= 0)
798 if (
ctx->use_inter_dct_only >= 0)
800 if (
ctx->use_intra_default_tx_only >= 0)
801 codecctl_int(avctx, AV1E_SET_INTRA_DEFAULT_TX_ONLY,
ctx->use_intra_default_tx_only);
802 if (
ctx->reduced_tx_type_set >= 0)
803 codecctl_int(avctx, AV1E_SET_REDUCED_TX_TYPE_SET,
ctx->reduced_tx_type_set);
804 if (
ctx->enable_ref_frame_mvs >= 0)
805 codecctl_int(avctx, AV1E_SET_ENABLE_REF_FRAME_MVS,
ctx->enable_ref_frame_mvs);
806 if (
ctx->enable_reduced_reference_set >= 0)
807 codecctl_int(avctx, AV1E_SET_REDUCED_REFERENCE_SET,
ctx->enable_reduced_reference_set);
808 if (
ctx->enable_diff_wtd_comp >= 0)
809 codecctl_int(avctx, AV1E_SET_ENABLE_DIFF_WTD_COMP,
ctx->enable_diff_wtd_comp);
810 if (
ctx->enable_dist_wtd_comp >= 0)
811 codecctl_int(avctx, AV1E_SET_ENABLE_DIST_WTD_COMP,
ctx->enable_dist_wtd_comp);
812 if (
ctx->enable_dual_filter >= 0)
813 codecctl_int(avctx, AV1E_SET_ENABLE_DUAL_FILTER,
ctx->enable_dual_filter);
814 if (
ctx->enable_interinter_wedge >= 0)
815 codecctl_int(avctx, AV1E_SET_ENABLE_INTERINTER_WEDGE,
ctx->enable_interinter_wedge);
816 if (
ctx->enable_masked_comp >= 0)
817 codecctl_int(avctx, AV1E_SET_ENABLE_MASKED_COMP,
ctx->enable_masked_comp);
818 if (
ctx->enable_interintra_comp >= 0)
819 codecctl_int(avctx, AV1E_SET_ENABLE_INTERINTRA_COMP,
ctx->enable_interintra_comp);
820 if (
ctx->enable_interintra_wedge >= 0)
821 codecctl_int(avctx, AV1E_SET_ENABLE_INTERINTRA_WEDGE,
ctx->enable_interintra_wedge);
822 if (
ctx->enable_obmc >= 0)
824 if (
ctx->enable_onesided_comp >= 0)
825 codecctl_int(avctx, AV1E_SET_ENABLE_ONESIDED_COMP,
ctx->enable_onesided_comp);
826 if (
ctx->enable_smooth_interintra >= 0)
827 codecctl_int(avctx, AV1E_SET_ENABLE_SMOOTH_INTERINTRA,
ctx->enable_smooth_interintra);
828 #endif
829
835
840 } else {
844 }
845 if (
ctx->aq_mode >= 0)
847 if (
ctx->frame_parallel >= 0)
848 codecctl_int(avctx, AV1E_SET_FRAME_PARALLEL_DECODING,
ctx->frame_parallel);
850
852 if (
ctx->uniform_tiles) {
855 }
856
857 #ifdef AOM_CTRL_AV1E_SET_DENOISE_NOISE_LEVEL
858 if (
ctx->denoise_noise_level >= 0)
859 codecctl_int(avctx, AV1E_SET_DENOISE_NOISE_LEVEL,
ctx->denoise_noise_level);
860 #endif
861 #ifdef AOM_CTRL_AV1E_SET_DENOISE_BLOCK_SIZE
862 if (
ctx->denoise_block_size >= 0)
863 codecctl_int(avctx, AV1E_SET_DENOISE_BLOCK_SIZE,
ctx->denoise_block_size);
864 #endif
865 #ifdef AOM_CTRL_AV1E_SET_ENABLE_GLOBAL_MOTION
866 if (
ctx->enable_global_motion >= 0)
867 codecctl_int(avctx, AV1E_SET_ENABLE_GLOBAL_MOTION,
ctx->enable_global_motion);
868 #endif
869 #ifdef AOM_CTRL_AV1E_SET_MAX_REFERENCE_FRAMES
870 if (avctx->
refs >= 3) {
872 }
873 #endif
874 #ifdef AOM_CTRL_AV1E_SET_ROW_MT
875 if (
ctx->row_mt >= 0)
877 #endif
878 #ifdef AOM_CTRL_AV1E_SET_ENABLE_INTRABC
879 if (
ctx->enable_intrabc >= 0)
881 #endif
882
883 #if AOM_ENCODER_ABI_VERSION >= 23
884 {
886
888 int ret = aom_codec_set_option(&
ctx->encoder, en->
key, en->
value);
889 if (
ret != AOM_CODEC_OK) {
892 }
893 }
894 }
895 #endif
896
897 // provide dummy value to initialize wrapper, values will be updated each _encode()
898 aom_img_wrap(&
ctx->rawimg, img_fmt, avctx->
width, avctx->
height, 1,
899 (unsigned char*)1);
900
901 if (codec_caps & AOM_CODEC_CAP_HIGHBITDEPTH)
902 ctx->rawimg.bit_depth = enccfg.g_bit_depth;
903
905 if (!cpb_props)
907
911
914 "not found. This is a bug, please report it.\n");
916 }
920
924
928 }
929
930 if (enccfg.rc_end_usage == AOM_CBR ||
931 enccfg.g_pass != AOM_RC_ONE_PASS) {
935 }
937
938 return 0;
939 }
940
943 const struct aom_codec_cx_pkt *
src)
944 {
945 dst->
pts =
src->data.frame.pts;
948 dst->
sz =
src->data.frame.sz;
949 dst->
buf =
src->data.frame.buf;
950 #ifdef AOM_FRAME_IS_INTRAONLY
954 /* associate last-seen SSE to the frame. */
955 /* Transfers ownership from ctx to dst. */
956 memcpy(dst->
sse,
ctx->sse,
sizeof(dst->
sse));
958 }
959 #endif
960 }
961
962 /**
963 * Store coded frame information in format suitable for return from encode2().
964 *
965 * Write information from @a cx_frame to @a pkt
966 * @return packet data size on success
967 * @return a negative AVERROR on error
968 */
971 {
979 }
982
983 if (!!(cx_frame->
flags & AOM_FRAME_IS_KEY)) {
985 #ifdef AOM_FRAME_IS_INTRAONLY
987 }
else if (cx_frame->
flags & AOM_FRAME_IS_INTRAONLY) {
989 } else {
991 }
992
994 cx_frame->
have_sse ? 3 : 0, pict_type);
995
998 for (
i = 0;
i < 3; ++
i) {
1000 }
1002 #endif
1003 }
1004
1009 "failed to send input packet\n");
1011 }
1013
1016 "failed to receive output packet\n");
1018 }
1019 }
1021 }
1022
1023 /**
1024 * Queue multiple output frames from the encoder, returning the front-most.
1025 * In cases where aom_codec_get_cx_data() returns more than 1 frame append
1026 * the frame queue. Return the head frame if available.
1027 * @return Stored frame size
1028 * @return AVERROR(EINVAL) on output size error
1029 * @return AVERROR(ENOMEM) on coded frame queue data allocation error
1030 */
1032 {
1034 const struct aom_codec_cx_pkt *
pkt;
1035 const void *iter =
NULL;
1037
1038 if (
ctx->coded_frame_list) {
1040 /* return the leading frame if we've already begun queueing */
1044 ctx->coded_frame_list = cx_frame->
next;
1046 }
1047
1048 /* consume all available output from the encoder before returning. buffers
1049 * are only good through the next aom_codec call */
1050 while ((
pkt = aom_codec_get_cx_data(&
ctx->encoder, &iter))) {
1051 switch (
pkt->kind) {
1052 case AOM_CODEC_CX_FRAME_PKT:
1055
1056 /* avoid storing the frame when the list is empty and we haven't yet
1057 * provided a frame for output */
1063 } else {
1066
1067 if (!cx_frame) {
1069 "Frame queue element alloc failed\n");
1071 }
1074
1075 if (!cx_frame->
buf) {
1081 }
1084 }
1085 break;
1086 case AOM_CODEC_STATS_PKT:
1087 {
1088 struct aom_fixed_buf *
stats = &
ctx->twopass_stats;
1089 int err;
1092 pkt->
data.twopass_stats.sz)) < 0) {
1095 return err;
1096 }
1100 break;
1101 }
1102 #ifdef AOM_FRAME_IS_INTRAONLY
1103 case AOM_CODEC_PSNR_PKT:
1104 {
1111 break;
1112 }
1113 #endif
1114 case AOM_CODEC_CUSTOM_PKT:
1115 // ignore unsupported/unrecognized packet types
1116 break;
1117 }
1118 }
1119
1121 }
1122
1125 {
1127 struct aom_image *rawimg =
NULL;
1128 int64_t timestamp = 0;
1129 int res, coded_size;
1130 aom_enc_frame_flags_t
flags = 0;
1131
1133 rawimg = &
ctx->rawimg;
1134 rawimg->planes[AOM_PLANE_Y] =
frame->data[0];
1135 rawimg->planes[AOM_PLANE_U] =
frame->data[1];
1136 rawimg->planes[AOM_PLANE_V] =
frame->data[2];
1137 rawimg->stride[AOM_PLANE_Y] =
frame->linesize[0];
1138 rawimg->stride[AOM_PLANE_U] =
frame->linesize[1];
1139 rawimg->stride[AOM_PLANE_V] =
frame->linesize[2];
1140 timestamp =
frame->pts;
1141 switch (
frame->color_range) {
1143 rawimg->range = AOM_CR_STUDIO_RANGE;
1144 break;
1146 rawimg->range = AOM_CR_FULL_RANGE;
1147 break;
1148 }
1149
1151 flags |= AOM_EFLAG_FORCE_KF;
1152 }
1153
1154 res = aom_codec_encode(&
ctx->encoder, rawimg, timestamp,
1156 if (res != AOM_CODEC_OK) {
1159 }
1161
1164
1168 b64_size);
1170 }
1172 ctx->twopass_stats.sz);
1173 }
1174
1175 *got_packet = !!coded_size;
1176 return 0;
1177 }
1178
1185 };
1186
1194 };
1195
1210 };
1211
1229 };
1230
1232 {
1233 int supports_monochrome = aom_codec_version() >= 20001;
1234 aom_codec_caps_t codec_caps = aom_codec_get_caps(aom_codec_av1_cx());
1235 if (codec_caps & AOM_CODEC_CAP_HIGHBITDEPTH)
1238 else
1241
1242 if (aom_codec_version_major() < 2)
1244 }
1245
1247 {
1248 return aom_init(avctx, aom_codec_av1_cx());
1249 }
1250
1251 #define OFFSET(x) offsetof(AOMContext, x)
1252 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
1255 { "auto-alt-ref", "Enable use of alternate reference "
1257 { "lag-in-frames", "Number of frames to look ahead at for "
1259 {
"arnr-max-frames",
"altref noise reduction max frame count",
OFFSET(arnr_max_frames),
AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX,
VE},
1260 {
"arnr-strength",
"altref noise reduction filter strength",
OFFSET(arnr_strength),
AV_OPT_TYPE_INT, {.i64 = -1}, -1, 6,
VE},
1261 {
"aq-mode",
"adaptive quantization mode",
OFFSET(aq_mode),
AV_OPT_TYPE_INT, {.i64 = -1}, -1, 4,
VE,
"aq_mode"},
1263 {
"variance",
"Variance based Aq", 0,
AV_OPT_TYPE_CONST, {.i64 = 1}, 0, 0,
VE,
"aq_mode"},
1264 {
"complexity",
"Complexity based Aq", 0,
AV_OPT_TYPE_CONST, {.i64 = 2}, 0, 0,
VE,
"aq_mode"},
1266 {
"error-resilience",
"Error resilience configuration",
OFFSET(error_resilient),
AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX,
VE,
"er"},
1267 {
"default",
"Improve resiliency against losses of whole frames", 0,
AV_OPT_TYPE_CONST, {.i64 = AOM_ERROR_RESILIENT_DEFAULT}, 0, 0,
VE,
"er"},
1268 {
"crf",
"Select the quality for constant quality mode", offsetof(AOMContext, crf),
AV_OPT_TYPE_INT, {.i64 = -1}, -1, 63,
VE },
1269 {
"static-thresh",
"A change threshold on blocks below which they will be skipped by the encoder",
OFFSET(static_thresh),
AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX,
VE },
1270 {
"drop-threshold",
"Frame drop threshold", offsetof(AOMContext, drop_threshold),
AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX,
VE },
1271 {
"denoise-noise-level",
"Amount of noise to be removed",
OFFSET(denoise_noise_level),
AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX,
VE},
1272 {
"denoise-block-size",
"Denoise block size ",
OFFSET(denoise_block_size),
AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX,
VE},
1273 {
"undershoot-pct",
"Datarate undershoot (min) target (%)",
OFFSET(rc_undershoot_pct),
AV_OPT_TYPE_INT, {.i64 = -1}, -1, 100,
VE},
1274 {
"overshoot-pct",
"Datarate overshoot (max) target (%)",
OFFSET(rc_overshoot_pct),
AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1000,
VE},
1275 {
"minsection-pct",
"GOP min bitrate (% of target)",
OFFSET(minsection_pct),
AV_OPT_TYPE_INT, {.i64 = -1}, -1, 100,
VE},
1276 {
"maxsection-pct",
"GOP max bitrate (% of target)",
OFFSET(maxsection_pct),
AV_OPT_TYPE_INT, {.i64 = -1}, -1, 5000,
VE},
1277 {
"frame-parallel",
"Enable frame parallel decodability features",
OFFSET(frame_parallel),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1279 {
"tile-columns",
"Log2 of number of tile columns to use",
OFFSET(tile_cols_log2),
AV_OPT_TYPE_INT, {.i64 = -1}, -1, 6,
VE},
1280 {
"tile-rows",
"Log2 of number of tile rows to use",
OFFSET(tile_rows_log2),
AV_OPT_TYPE_INT, {.i64 = -1}, -1, 6,
VE},
1283 {
"enable-global-motion",
"Enable global motion",
OFFSET(enable_global_motion),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1284 {
"enable-intrabc",
"Enable intra block copy prediction mode",
OFFSET(enable_intrabc),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1285 {
"enable-restoration",
"Enable Loop Restoration filtering",
OFFSET(enable_restoration),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1286 {
"usage",
"Quality and compression efficiency vs speed trade-off",
OFFSET(
usage),
AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX,
VE,
"usage"},
1287 {
"good",
"Good quality", 0,
AV_OPT_TYPE_CONST, {.i64 = 0
/* AOM_USAGE_GOOD_QUALITY */}, 0, 0,
VE,
"usage"},
1288 {
"realtime",
"Realtime encoding", 0,
AV_OPT_TYPE_CONST, {.i64 = 1
/* AOM_USAGE_REALTIME */}, 0, 0,
VE,
"usage"},
1289 {
"tune",
"The metric that the encoder tunes for. Automatically chosen by the encoder by default",
OFFSET(tune),
AV_OPT_TYPE_INT, {.i64 = -1}, -1, AOM_TUNE_SSIM,
VE,
"tune"},
1293 {
"enable-rect-partitions",
"Enable rectangular partitions",
OFFSET(enable_rect_partitions),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1294 {
"enable-1to4-partitions",
"Enable 1:4/4:1 partitions",
OFFSET(enable_1to4_partitions),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1295 {
"enable-ab-partitions",
"Enable ab shape partitions",
OFFSET(enable_ab_partitions),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1296 {
"enable-angle-delta",
"Enable angle delta intra prediction",
OFFSET(enable_angle_delta),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1297 {
"enable-cfl-intra",
"Enable chroma predicted from luma intra prediction",
OFFSET(enable_cfl_intra),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1298 {
"enable-filter-intra",
"Enable filter intra predictor",
OFFSET(enable_filter_intra),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1299 {
"enable-intra-edge-filter",
"Enable intra edge filter",
OFFSET(enable_intra_edge_filter),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1300 {
"enable-smooth-intra",
"Enable smooth intra prediction mode",
OFFSET(enable_smooth_intra),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1301 {
"enable-paeth-intra",
"Enable paeth predictor in intra prediction",
OFFSET(enable_paeth_intra),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1302 {
"enable-palette",
"Enable palette prediction mode",
OFFSET(enable_palette),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1303 {
"enable-flip-idtx",
"Enable extended transform type",
OFFSET(enable_flip_idtx),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1305 {
"reduced-tx-type-set",
"Use reduced set of transform types",
OFFSET(reduced_tx_type_set),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1306 {
"use-intra-dct-only",
"Use DCT only for INTRA modes",
OFFSET(use_intra_dct_only),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1307 {
"use-inter-dct-only",
"Use DCT only for INTER modes",
OFFSET(use_inter_dct_only),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1308 {
"use-intra-default-tx-only",
"Use default-transform only for INTRA modes",
OFFSET(use_intra_default_tx_only),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1309 {
"enable-ref-frame-mvs",
"Enable temporal mv prediction",
OFFSET(enable_ref_frame_mvs),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1310 {
"enable-reduced-reference-set",
"Use reduced set of single and compound references",
OFFSET(enable_reduced_reference_set),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1312 {
"enable-dual-filter",
"Enable dual filter",
OFFSET(enable_dual_filter),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1313 {
"enable-diff-wtd-comp",
"Enable difference-weighted compound",
OFFSET(enable_diff_wtd_comp),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1314 {
"enable-dist-wtd-comp",
"Enable distance-weighted compound",
OFFSET(enable_dist_wtd_comp),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1315 {
"enable-onesided-comp",
"Enable one sided compound",
OFFSET(enable_onesided_comp),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1316 {
"enable-interinter-wedge",
"Enable interinter wedge compound",
OFFSET(enable_interinter_wedge),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1317 {
"enable-interintra-wedge",
"Enable interintra wedge compound",
OFFSET(enable_interintra_wedge),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1318 {
"enable-masked-comp",
"Enable masked compound",
OFFSET(enable_masked_comp),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1319 {
"enable-interintra-comp",
"Enable interintra compound",
OFFSET(enable_interintra_comp),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1320 {
"enable-smooth-interintra",
"Enable smooth interintra mode",
OFFSET(enable_smooth_interintra),
AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
VE},
1321 #if AOM_ENCODER_ABI_VERSION >= 23
1322 {
"aom-params",
"Set libaom options using a :-separated list of key=value pairs",
OFFSET(aom_params),
AV_OPT_TYPE_DICT, { 0 }, 0, 0,
VE },
1323 #endif
1325 };
1326
1328 { "b", "0" },
1329 { "qmin", "-1" },
1330 { "qmax", "-1" },
1331 { "g", "-1" },
1332 { "keyint_min", "-1" },
1334 };
1335
1341 };
1342
1344 .
name =
"libaom-av1",
1350 .priv_data_size = sizeof(AOMContext),
1359 .wrapper_name = "libaom",
1360 };