static int alloc_buffer(EbSvtAv1EncConfiguration *config, SvtContext *svt_enc)
{
- const int pack_mode_10bit =
- (config->encoder_bit_depth > 8) && (config->compressed_ten_bit_format == 0) ? 1 : 0;
- const size_t luma_size_8bit =
- config->source_width * config->source_height * (1 << pack_mode_10bit);
- const size_t luma_size_10bit =
- (config->encoder_bit_depth > 8 && pack_mode_10bit == 0) ? luma_size_8bit : 0;
+ const size_t luma_size = config->source_width * config->source_height *
+ (config->encoder_bit_depth > 8 ? 2 : 1);
EbSvtIOFormat *in_data;
- svt_enc->raw_size = (luma_size_8bit + luma_size_10bit) * 3 / 2;
+ svt_enc->raw_size = luma_size * 3 / 2;
// allocate buffer for in and out
svt_enc->in_buf = av_mallocz(sizeof(*svt_enc->in_buf));
// Update param from options
#if FF_API_SVTAV1_OPTS
- param->hierarchical_levels = svt_enc->hierarchical_level;
- param->tier = svt_enc->tier;
- param->scene_change_detection = svt_enc->scd;
- param->tile_columns = svt_enc->tile_columns;
- param->tile_rows = svt_enc->tile_rows;
+ if (svt_enc->hierarchical_level >= 0)
+ param->hierarchical_levels = svt_enc->hierarchical_level;
+ if (svt_enc->tier >= 0)
+ param->tier = svt_enc->tier;
+ if (svt_enc->scd >= 0)
+ param->scene_change_detection = svt_enc->scd;
+ if (svt_enc->tile_columns >= 0)
+ param->tile_columns = svt_enc->tile_columns;
+ if (svt_enc->tile_rows >= 0)
+ param->tile_rows = svt_enc->tile_rows;
if (svt_enc->la_depth >= 0)
- param->look_ahead_distance = svt_enc->la_depth;
+ param->look_ahead_distance = svt_enc->la_depth;
#endif
- if (svt_enc->enc_mode >= 0)
+ if (svt_enc->enc_mode >= -1)
param->enc_mode = svt_enc->enc_mode;
if (avctx->bit_rate) {
param->min_qp_allowed = avctx->qmin;
}
param->max_bit_rate = avctx->rc_max_rate;
- param->vbv_bufsize = avctx->rc_buffer_size;
+ if ((avctx->bit_rate > 0 || avctx->rc_max_rate > 0) && avctx->rc_buffer_size)
+ param->maximum_buffer_size_ms =
+ avctx->rc_buffer_size * 1000LL /
+ FFMAX(avctx->bit_rate, avctx->rc_max_rate);
if (svt_enc->crf > 0) {
param->qp = svt_enc->crf;
}
#endif
- if (avctx->profile != FF_PROFILE_UNKNOWN)
+ if (avctx->profile != AV_PROFILE_UNKNOWN)
param->profile = avctx->profile;
- if (avctx->level != FF_LEVEL_UNKNOWN)
+ if (avctx->level != AV_LEVEL_UNKNOWN)
param->level = avctx->level;
- if (avctx->gop_size > 0)
+ // gop_size == 1 case is handled when encoding each frame by setting
+ // pic_type to EB_AV1_KEY_PICTURE. For gop_size > 1, set the
+ // intra_period_length. Even though setting intra_period_length to 0 should
+ // work in this case, it does not.
+ // See: https://gitlab.com/AOMediaCodec/SVT-AV1/-/issues/2076
+ if (avctx->gop_size > 1)
param->intra_period_length = avctx->gop_size - 1;
+ // In order for SVT-AV1 to force keyframes by setting pic_type to
+ // EB_AV1_KEY_PICTURE on any frame, force_key_frames has to be set. Note
+ // that this does not force all frames to be keyframes (it only forces a
+ // keyframe with pic_type is set to EB_AV1_KEY_PICTURE). As of now, SVT-AV1
+ // does not support arbitrary keyframe requests by setting pic_type to
+ // EB_AV1_KEY_PICTURE, so it is done only when gop_size == 1.
+ // FIXME: When SVT-AV1 supports arbitrary keyframe requests, this code needs
+ // to be updated to set force_key_frames accordingly.
+ if (avctx->gop_size == 1)
+ param->force_key_frames = 1;
+
if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
param->frame_rate_numerator = avctx->framerate.num;
param->frame_rate_denominator = avctx->framerate.den;
} else {
param->frame_rate_numerator = avctx->time_base.den;
- param->frame_rate_denominator = avctx->time_base.num * avctx->ticks_per_frame;
+FF_DISABLE_DEPRECATION_WARNINGS
+ param->frame_rate_denominator = avctx->time_base.num
+#if FF_API_TICKS_PER_FRAME
+ * avctx->ticks_per_frame
+#endif
+ ;
+FF_ENABLE_DEPRECATION_WARNINGS
}
/* 2 = IDR, closed GOP, 1 = CRA, open GOP */
}
if ((param->encoder_color_format == EB_YUV422 || param->encoder_bit_depth > 10)
- && param->profile != FF_PROFILE_AV1_PROFESSIONAL ) {
+ && param->profile != AV_PROFILE_AV1_PROFESSIONAL ) {
av_log(avctx, AV_LOG_WARNING, "Forcing Professional profile\n");
- param->profile = FF_PROFILE_AV1_PROFESSIONAL;
- } else if (param->encoder_color_format == EB_YUV444 && param->profile != FF_PROFILE_AV1_HIGH) {
+ param->profile = AV_PROFILE_AV1_PROFESSIONAL;
+ } else if (param->encoder_color_format == EB_YUV444 && param->profile != AV_PROFILE_AV1_HIGH) {
av_log(avctx, AV_LOG_WARNING, "Forcing High profile\n");
- param->profile = FF_PROFILE_AV1_HIGH;
+ param->profile = AV_PROFILE_AV1_HIGH;
}
avctx->bit_rate = param->rate_control_mode > 0 ?
param->target_bit_rate : 0;
avctx->rc_max_rate = param->max_bit_rate;
- avctx->rc_buffer_size = param->vbv_bufsize;
+ avctx->rc_buffer_size = param->maximum_buffer_size_ms *
+ FFMAX(avctx->bit_rate, avctx->rc_max_rate) / 1000LL;
if (avctx->bit_rate || avctx->rc_max_rate || avctx->rc_buffer_size) {
- AVCPBProperties *cpb_props = ff_add_cpb_side_data(avctx);
+ AVCPBProperties *cpb_props = ff_encode_add_cpb_side_data(avctx);
if (!cpb_props)
return AVERROR(ENOMEM);
break;
}
+ if (avctx->gop_size == 1)
+ headerPtr->pic_type = EB_AV1_KEY_PICTURE;
+
svt_av1_enc_send_picture(svt_enc->svt_handle, headerPtr);
return 0;
static const AVOption options[] = {
#if FF_API_SVTAV1_OPTS
{ "hielevel", "Hierarchical prediction levels setting (Deprecated, use svtav1-params)", OFFSET(hierarchical_level),
- AV_OPT_TYPE_INT, { .i64 = 4 }, 3, 4, VE | AV_OPT_FLAG_DEPRECATED , "hielevel"},
+ AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 4, VE | AV_OPT_FLAG_DEPRECATED , "hielevel"},
{ "3level", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 3 }, INT_MIN, INT_MAX, VE, "hielevel" },
{ "4level", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 4 }, INT_MIN, INT_MAX, VE, "hielevel" },
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 120, VE | AV_OPT_FLAG_DEPRECATED },
{ "tier", "Set operating point tier (Deprecated, use svtav1-params)", OFFSET(tier),
- AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE | AV_OPT_FLAG_DEPRECATED, "tier" },
+ AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE | AV_OPT_FLAG_DEPRECATED, "tier" },
{ "main", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, VE, "tier" },
{ "high", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, VE, "tier" },
#endif
{ "preset", "Encoding preset",
- OFFSET(enc_mode), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, MAX_ENC_PRESET, VE },
+ OFFSET(enc_mode), AV_OPT_TYPE_INT, { .i64 = -2 }, -2, MAX_ENC_PRESET, VE },
FF_AV1_PROFILE_OPTS
AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 63, VE },
#if FF_API_SVTAV1_OPTS
{ "sc_detection", "Scene change detection (Deprecated, use svtav1-params)", OFFSET(scd),
- AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE | AV_OPT_FLAG_DEPRECATED },
+ AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, VE | AV_OPT_FLAG_DEPRECATED },
- { "tile_columns", "Log2 of number of tile columns to use (Deprecated, use svtav1-params)", OFFSET(tile_columns), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 4, VE | AV_OPT_FLAG_DEPRECATED },
- { "tile_rows", "Log2 of number of tile rows to use (Deprecated, use svtav1-params)", OFFSET(tile_rows), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 6, VE | AV_OPT_FLAG_DEPRECATED },
+ { "tile_columns", "Log2 of number of tile columns to use (Deprecated, use svtav1-params)", OFFSET(tile_columns), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 4, VE | AV_OPT_FLAG_DEPRECATED },
+ { "tile_rows", "Log2 of number of tile rows to use (Deprecated, use svtav1-params)", OFFSET(tile_rows), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 6, VE | AV_OPT_FLAG_DEPRECATED },
#endif
{ "svtav1-params", "Set the SVT-AV1 configuration using a :-separated list of key=value parameters", OFFSET(svtav1_opts), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE },
const FFCodec ff_libsvtav1_encoder = {
.p.name = "libsvtav1",
- .p.long_name = NULL_IF_CONFIG_SMALL("SVT-AV1(Scalable Video Technology for AV1) encoder"),
+ CODEC_LONG_NAME("SVT-AV1(Scalable Video Technology for AV1) encoder"),
.priv_data_size = sizeof(SvtContext),
.p.type = AVMEDIA_TYPE_VIDEO,
.p.id = AV_CODEC_ID_AV1,
FF_CODEC_RECEIVE_PACKET_CB(eb_receive_packet),
.close = eb_enc_close,
.p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS,
- .caps_internal = FF_CODEC_CAP_AUTO_THREADS | FF_CODEC_CAP_INIT_CLEANUP,
+ .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE |
+ FF_CODEC_CAP_AUTO_THREADS | FF_CODEC_CAP_INIT_CLEANUP,
.p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P,
AV_PIX_FMT_YUV420P10,
AV_PIX_FMT_NONE },