Imported Upstream version 6.1
[platform/upstream/ffmpeg.git] / libavcodec / libsvtav1.c
index 4001cf7..8d2c7f3 100644 (file)
@@ -124,16 +124,12 @@ static int svt_print_error(void *log_ctx, EbErrorType err,
 
 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));
@@ -159,17 +155,22 @@ static int config_enc_params(EbSvtAv1EncConfiguration *param,
 
     // 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) {
@@ -183,7 +184,10 @@ static int config_enc_params(EbSvtAv1EncConfiguration *param,
         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;
@@ -232,21 +236,43 @@ static int config_enc_params(EbSvtAv1EncConfiguration *param,
     }
 #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 */
@@ -289,21 +315,22 @@ static int config_enc_params(EbSvtAv1EncConfiguration *param,
     }
 
     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);
 
@@ -451,6 +478,9 @@ static int eb_send_frame(AVCodecContext *avctx, const AVFrame *frame)
         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;
@@ -575,7 +605,7 @@ static av_cold int eb_enc_close(AVCodecContext *avctx)
 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" },
 
@@ -583,12 +613,12 @@ static const AVOption options[] = {
       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
 
@@ -626,10 +656,10 @@ static const AVOption options[] = {
       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 },
@@ -655,7 +685,7 @@ static const FFCodecDefault eb_enc_defaults[] = {
 
 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,
@@ -663,7 +693,8 @@ const FFCodec ff_libsvtav1_encoder = {
     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 },