Signed-off-by: James Almer <jamr...@gmail.com>
---
 libavcodec/libaomenc.c | 266 ++++++++++++++++++++++++-----------------
 1 file changed, 159 insertions(+), 107 deletions(-)

diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c
index 0f7571ee7a..45d3fe862a 100644
--- a/libavcodec/libaomenc.c
+++ b/libavcodec/libaomenc.c
@@ -73,7 +73,10 @@ typedef struct AOMEncoderContext {
     AVBSFContext *bsf;
     DOVIContext dovi;
     struct aom_codec_ctx encoder;
+    struct aom_codec_enc_cfg enccfg;
     struct aom_image rawimg;
+    aom_codec_flags_t flags;
+    aom_img_fmt_t img_fmt;
     struct aom_fixed_buf twopass_stats;
     unsigned twopass_stats_size;
     struct FrameListData *coded_frame_list;
@@ -342,9 +345,6 @@ static av_cold int codecctl_intp(AVCodecContext *avctx,
     int width = -30;
     int res;
 
-    snprintf(buf, sizeof(buf), "%s:", ctlidstr[id]);
-    av_log(avctx, AV_LOG_DEBUG, "  %*s%d\n", width, buf, *ptr);
-
     res = aom_codec_control(&ctx->encoder, id, ptr);
     if (res != AOM_CODEC_OK) {
         snprintf(buf, sizeof(buf), "Failed to set %s codec control",
@@ -353,6 +353,9 @@ static av_cold int codecctl_intp(AVCodecContext *avctx,
         return AVERROR(EINVAL);
     }
 
+    snprintf(buf, sizeof(buf), "%s:", ctlidstr[id]);
+    av_log(avctx, AV_LOG_DEBUG, "  %*s%d\n", width, buf, *ptr);
+
     return 0;
 }
 #endif
@@ -673,29 +676,22 @@ static int choose_tiling(AVCodecContext *avctx,
     return 0;
 }
 
-static av_cold int aom_init(AVCodecContext *avctx,
-                            const struct aom_codec_iface *iface)
+static av_cold int aom_config(AVCodecContext *avctx,
+                              const struct aom_codec_iface *iface)
 {
     AOMContext *ctx = avctx->priv_data;
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
-    struct aom_codec_enc_cfg enccfg = { 0 };
-    aom_codec_flags_t flags =
-        (avctx->flags & AV_CODEC_FLAG_PSNR) ? AOM_CODEC_USE_PSNR : 0;
-    AVCPBProperties *cpb_props;
     int res;
-    aom_img_fmt_t img_fmt;
     aom_codec_caps_t codec_caps = aom_codec_get_caps(iface);
 
-    av_log(avctx, AV_LOG_INFO, "%s\n", aom_codec_version_str());
-    av_log(avctx, AV_LOG_VERBOSE, "%s\n", aom_codec_build_config());
+    ctx->flags = (avctx->flags & AV_CODEC_FLAG_PSNR) ? AOM_CODEC_USE_PSNR : 0;
 
-    if ((res = aom_codec_enc_config_default(iface, &enccfg, ctx->usage)) != 
AOM_CODEC_OK) {
+    if ((res = aom_codec_enc_config_default(iface, &ctx->enccfg, ctx->usage)) 
!= AOM_CODEC_OK) {
         av_log(avctx, AV_LOG_ERROR, "Failed to get config: %s\n",
                aom_codec_err_to_string(res));
         return AVERROR(EINVAL);
     }
 
-    if (set_pix_fmt(avctx, codec_caps, &enccfg, &flags, &img_fmt))
+    if (set_pix_fmt(avctx, codec_caps, &ctx->enccfg, &ctx->flags, 
&ctx->img_fmt))
         return AVERROR(EINVAL);
 
     if(!avctx->bit_rate)
@@ -704,39 +700,30 @@ static av_cold int aom_init(AVCodecContext *avctx,
             return AVERROR(EINVAL);
         }
 
-    dump_enc_cfg(avctx, &enccfg, AV_LOG_DEBUG);
-
-    enccfg.g_w            = avctx->width;
-    enccfg.g_h            = avctx->height;
-    enccfg.g_timebase.num = avctx->time_base.num;
-    enccfg.g_timebase.den = avctx->time_base.den;
-    enccfg.g_threads      =
+    ctx->enccfg.g_w            = avctx->width;
+    ctx->enccfg.g_h            = avctx->height;
+    ctx->enccfg.g_timebase.num = avctx->time_base.num;
+    ctx->enccfg.g_timebase.den = avctx->time_base.den;
+    ctx->enccfg.g_threads      =
         FFMIN(avctx->thread_count ? avctx->thread_count : av_cpu_count(), 64);
 
     if (ctx->lag_in_frames >= 0)
-        enccfg.g_lag_in_frames = ctx->lag_in_frames;
-
-    if (avctx->flags & AV_CODEC_FLAG_PASS1)
-        enccfg.g_pass = AOM_RC_FIRST_PASS;
-    else if (avctx->flags & AV_CODEC_FLAG_PASS2)
-        enccfg.g_pass = AOM_RC_LAST_PASS;
-    else
-        enccfg.g_pass = AOM_RC_ONE_PASS;
+        ctx->enccfg.g_lag_in_frames = ctx->lag_in_frames;
 
     if (avctx->rc_min_rate == avctx->rc_max_rate &&
         avctx->rc_min_rate == avctx->bit_rate && avctx->bit_rate) {
-        enccfg.rc_end_usage = AOM_CBR;
+        ctx->enccfg.rc_end_usage = AOM_CBR;
     } else if (ctx->crf >= 0) {
-        enccfg.rc_end_usage = AOM_CQ;
+        ctx->enccfg.rc_end_usage = AOM_CQ;
         if (!avctx->bit_rate)
-            enccfg.rc_end_usage = AOM_Q;
+            ctx->enccfg.rc_end_usage = AOM_Q;
     }
 
     if (avctx->bit_rate) {
-        enccfg.rc_target_bitrate = av_rescale_rnd(avctx->bit_rate, 1, 1000,
+        ctx->enccfg.rc_target_bitrate = av_rescale_rnd(avctx->bit_rate, 1, 
1000,
                                                   AV_ROUND_NEAR_INF);
-    } else if (enccfg.rc_end_usage != AOM_Q) {
-        enccfg.rc_end_usage = AOM_Q;
+    } else if (ctx->enccfg.rc_end_usage != AOM_Q) {
+        ctx->enccfg.rc_end_usage = AOM_Q;
         ctx->crf = 32;
         av_log(avctx, AV_LOG_WARNING,
                "Neither bitrate nor constrained quality specified, using 
default CRF of %d\n",
@@ -744,95 +731,65 @@ static av_cold int aom_init(AVCodecContext *avctx,
     }
 
     if (avctx->qmin >= 0)
-        enccfg.rc_min_quantizer = avctx->qmin;
+        ctx->enccfg.rc_min_quantizer = avctx->qmin;
     if (avctx->qmax >= 0) {
-        enccfg.rc_max_quantizer = avctx->qmax;
+        ctx->enccfg.rc_max_quantizer = avctx->qmax;
     } else if (!ctx->crf) {
-        enccfg.rc_max_quantizer = 0;
+        ctx->enccfg.rc_max_quantizer = 0;
     }
 
-    if (enccfg.rc_end_usage == AOM_CQ || enccfg.rc_end_usage == AOM_Q) {
-        if (ctx->crf < enccfg.rc_min_quantizer || ctx->crf > 
enccfg.rc_max_quantizer) {
+    if (ctx->enccfg.rc_end_usage == AOM_CQ || ctx->enccfg.rc_end_usage == 
AOM_Q) {
+        if (ctx->crf < ctx->enccfg.rc_min_quantizer || ctx->crf > 
ctx->enccfg.rc_max_quantizer) {
             av_log(avctx, AV_LOG_ERROR,
                    "CQ level %d must be between minimum and maximum quantizer 
value (%d-%d)\n",
-                   ctx->crf, enccfg.rc_min_quantizer, enccfg.rc_max_quantizer);
+                   ctx->crf, ctx->enccfg.rc_min_quantizer, 
ctx->enccfg.rc_max_quantizer);
             return AVERROR(EINVAL);
         }
     }
 
-    enccfg.rc_dropframe_thresh = ctx->drop_threshold;
+    ctx->enccfg.rc_dropframe_thresh = ctx->drop_threshold;
 
     // 0-100 (0 => CBR, 100 => VBR)
-    enccfg.rc_2pass_vbr_bias_pct       = round(avctx->qcompress * 100);
+    ctx->enccfg.rc_2pass_vbr_bias_pct       = round(avctx->qcompress * 100);
     if (ctx->minsection_pct >= 0)
-        enccfg.rc_2pass_vbr_minsection_pct = ctx->minsection_pct;
+        ctx->enccfg.rc_2pass_vbr_minsection_pct = ctx->minsection_pct;
     else if (avctx->bit_rate)
-        enccfg.rc_2pass_vbr_minsection_pct =
+        ctx->enccfg.rc_2pass_vbr_minsection_pct =
             avctx->rc_min_rate * 100LL / avctx->bit_rate;
     if (ctx->maxsection_pct >= 0)
-        enccfg.rc_2pass_vbr_maxsection_pct = ctx->maxsection_pct;
+        ctx->enccfg.rc_2pass_vbr_maxsection_pct = ctx->maxsection_pct;
     else if (avctx->rc_max_rate)
-        enccfg.rc_2pass_vbr_maxsection_pct =
+        ctx->enccfg.rc_2pass_vbr_maxsection_pct =
             avctx->rc_max_rate * 100LL / avctx->bit_rate;
 
     if (avctx->rc_buffer_size)
-        enccfg.rc_buf_sz =
+        ctx->enccfg.rc_buf_sz =
             avctx->rc_buffer_size * 1000LL / avctx->bit_rate;
     if (avctx->rc_initial_buffer_occupancy)
-        enccfg.rc_buf_initial_sz =
+        ctx->enccfg.rc_buf_initial_sz =
             avctx->rc_initial_buffer_occupancy * 1000LL / avctx->bit_rate;
-    enccfg.rc_buf_optimal_sz = enccfg.rc_buf_sz * 5 / 6;
+    ctx->enccfg.rc_buf_optimal_sz = ctx->enccfg.rc_buf_sz * 5 / 6;
 
     if (ctx->rc_undershoot_pct >= 0)
-        enccfg.rc_undershoot_pct = ctx->rc_undershoot_pct;
+        ctx->enccfg.rc_undershoot_pct = ctx->rc_undershoot_pct;
     if (ctx->rc_overshoot_pct >= 0)
-        enccfg.rc_overshoot_pct = ctx->rc_overshoot_pct;
+        ctx->enccfg.rc_overshoot_pct = ctx->rc_overshoot_pct;
 
     // _enc_init() will balk if kf_min_dist differs from max w/AOM_KF_AUTO
     if (avctx->keyint_min >= 0 && avctx->keyint_min == avctx->gop_size)
-        enccfg.kf_min_dist = avctx->keyint_min;
+        ctx->enccfg.kf_min_dist = avctx->keyint_min;
     if (avctx->gop_size >= 0)
-        enccfg.kf_max_dist = avctx->gop_size;
-
-    if (enccfg.g_pass == AOM_RC_FIRST_PASS)
-        enccfg.g_lag_in_frames = 0;
-    else if (enccfg.g_pass == AOM_RC_LAST_PASS) {
-        int decode_size, ret;
-
-        if (!avctx->stats_in) {
-            av_log(avctx, AV_LOG_ERROR, "No stats file for second pass\n");
-            return AVERROR_INVALIDDATA;
-        }
-
-        ctx->twopass_stats.sz = strlen(avctx->stats_in) * 3 / 4;
-        ret                   = av_reallocp(&ctx->twopass_stats.buf, 
ctx->twopass_stats.sz);
-        if (ret < 0) {
-            av_log(avctx, AV_LOG_ERROR,
-                   "Stat buffer alloc (%"SIZE_SPECIFIER" bytes) failed\n",
-                   ctx->twopass_stats.sz);
-            ctx->twopass_stats.sz = 0;
-            return ret;
-        }
-        decode_size = av_base64_decode(ctx->twopass_stats.buf, avctx->stats_in,
-                                       ctx->twopass_stats.sz);
-        if (decode_size < 0) {
-            av_log(avctx, AV_LOG_ERROR, "Stat buffer decode failed\n");
-            return AVERROR_INVALIDDATA;
-        }
-
-        ctx->twopass_stats.sz      = decode_size;
-        enccfg.rc_twopass_stats_in = ctx->twopass_stats;
-    }
+        ctx->enccfg.kf_max_dist = avctx->gop_size;
 
     /* 0-3: For non-zero values the encoder increasingly optimizes for reduced
      * complexity playback on low powered devices at the expense of encode
      * quality. */
     if (avctx->profile != AV_PROFILE_UNKNOWN)
-        enccfg.g_profile = avctx->profile;
+        ctx->enccfg.g_profile = avctx->profile;
 
-    enccfg.g_error_resilient = ctx->error_resilient;
+    ctx->enccfg.g_error_resilient = ctx->error_resilient;
 
-    res = choose_tiling(avctx, &enccfg);
+    res = choose_tiling(avctx, &ctx->enccfg);
     if (res < 0)
         return res;
 
@@ -840,22 +797,22 @@ static av_cold int aom_init(AVCodecContext *avctx,
         // Set the maximum number of frames to 1. This will let libaom set
         // still_picture and reduced_still_picture_header to 1 in the Sequence
         // Header as required by AVIF still images.
-        enccfg.g_limit = 1;
+        ctx->enccfg.g_limit = 1;
         // Reduce memory usage for still images.
-        enccfg.g_lag_in_frames = 0;
+        ctx->enccfg.g_lag_in_frames = 0;
         // All frames will be key frames.
-        enccfg.kf_max_dist = 0;
-        enccfg.kf_mode = AOM_KF_DISABLED;
+        ctx->enccfg.kf_max_dist = 0;
+        ctx->enccfg.kf_mode = AOM_KF_DISABLED;
     }
 
-    /* Construct Encoder Context */
-    res = aom_codec_enc_init(&ctx->encoder, iface, &enccfg, flags);
-    if (res != AOM_CODEC_OK) {
-        dump_enc_cfg(avctx, &enccfg, AV_LOG_WARNING);
-        log_encoder_error(avctx, "Failed to initialize encoder");
-        return AVERROR(EINVAL);
-    }
-    dump_enc_cfg(avctx, &enccfg, AV_LOG_DEBUG);
+    return 0;
+}
+
+static av_cold int aom_codecctl(AVCodecContext *avctx)
+{
+    AOMContext *ctx = avctx->priv_data;
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
+    aom_codec_caps_t codec_caps = aom_codec_get_caps(ctx->encoder.iface);
 
     // codec control failures are currently treated only as warnings
     av_log(avctx, AV_LOG_DEBUG, "aom_codec_control\n");
@@ -983,20 +940,87 @@ static av_cold int aom_init(AVCodecContext *avctx,
 #endif
 
     // provide dummy value to initialize wrapper, values will be updated each 
_encode()
-    aom_img_wrap(&ctx->rawimg, img_fmt, avctx->width, avctx->height, 1,
+    aom_img_wrap(&ctx->rawimg, ctx->img_fmt, avctx->width, avctx->height, 1,
                  (unsigned char*)1);
 
     if (codec_caps & AOM_CODEC_CAP_HIGHBITDEPTH)
-        ctx->rawimg.bit_depth = enccfg.g_bit_depth;
+        ctx->rawimg.bit_depth = ctx->enccfg.g_bit_depth;
 
-    cpb_props = ff_encode_add_cpb_side_data(avctx);
-    if (!cpb_props)
-        return AVERROR(ENOMEM);
+    return 0;
+}
+
+static av_cold int aom_init(AVCodecContext *avctx,
+                            const struct aom_codec_iface *iface)
+{
+    AOMContext *ctx = avctx->priv_data;
+    AVCPBProperties *cpb_props;
+    int res;
+
+    av_log(avctx, AV_LOG_INFO, "%s\n", aom_codec_version_str());
+    av_log(avctx, AV_LOG_VERBOSE, "%s\n", aom_codec_build_config());
+
+    res = aom_config(avctx, iface);
+    if (res < 0)
+        return res;
+
+    if (avctx->flags & AV_CODEC_FLAG_PASS1)
+        ctx->enccfg.g_pass = AOM_RC_FIRST_PASS;
+    else if (avctx->flags & AV_CODEC_FLAG_PASS2)
+        ctx->enccfg.g_pass = AOM_RC_LAST_PASS;
+    else
+        ctx->enccfg.g_pass = AOM_RC_ONE_PASS;
+
+    if (ctx->enccfg.g_pass == AOM_RC_FIRST_PASS)
+        ctx->enccfg.g_lag_in_frames = 0;
+    else if (ctx->enccfg.g_pass == AOM_RC_LAST_PASS) {
+        int decode_size, ret;
+
+        if (!avctx->stats_in) {
+            av_log(avctx, AV_LOG_ERROR, "No stats file for second pass\n");
+            return AVERROR_INVALIDDATA;
+        }
+
+        ctx->twopass_stats.sz = strlen(avctx->stats_in) * 3 / 4;
+        ret                   = av_reallocp(&ctx->twopass_stats.buf, 
ctx->twopass_stats.sz);
+        if (ret < 0) {
+            av_log(avctx, AV_LOG_ERROR,
+                   "Stat buffer alloc (%"SIZE_SPECIFIER" bytes) failed\n",
+                   ctx->twopass_stats.sz);
+            ctx->twopass_stats.sz = 0;
+            return ret;
+        }
+        decode_size = av_base64_decode(ctx->twopass_stats.buf, avctx->stats_in,
+                                       ctx->twopass_stats.sz);
+        if (decode_size < 0) {
+            av_log(avctx, AV_LOG_ERROR, "Stat buffer decode failed\n");
+            return AVERROR_INVALIDDATA;
+        }
+
+        ctx->twopass_stats.sz      = decode_size;
+        ctx->enccfg.rc_twopass_stats_in = ctx->twopass_stats;
+    }
+
+    /* Construct Encoder Context */
+    res = aom_codec_enc_init(&ctx->encoder, iface, &ctx->enccfg, ctx->flags);
+    if (res != AOM_CODEC_OK) {
+        dump_enc_cfg(avctx, &ctx->enccfg, AV_LOG_WARNING);
+        log_encoder_error(avctx, "Failed to initialize encoder");
+        return AVERROR(EINVAL);
+    }
+    dump_enc_cfg(avctx, &ctx->enccfg, AV_LOG_DEBUG);
+
+    res = aom_codecctl(avctx);
+    if (res < 0)
+        return res;
 
     ctx->dovi.logctx = avctx;
     if ((res = ff_dovi_configure(&ctx->dovi, avctx)) < 0)
         return res;
 
+    cpb_props = ff_encode_add_cpb_side_data(avctx);
+    if (!cpb_props)
+        return AVERROR(ENOMEM);
+
     if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
         const AVBitStreamFilter *filter = 
av_bsf_get_by_name("extract_extradata");
         int ret;
@@ -1019,8 +1043,8 @@ static av_cold int aom_init(AVCodecContext *avctx,
            return ret;
     }
 
-    if (enccfg.rc_end_usage == AOM_CBR ||
-        enccfg.g_pass != AOM_RC_ONE_PASS) {
+    if (ctx->enccfg.rc_end_usage == AOM_CBR ||
+        ctx->enccfg.g_pass != AOM_RC_ONE_PASS) {
         cpb_props->max_bitrate = avctx->rc_max_rate;
         cpb_props->min_bitrate = avctx->rc_min_rate;
         cpb_props->avg_bitrate = avctx->bit_rate;
@@ -1464,6 +1488,32 @@ static av_cold int av1_init(AVCodecContext *avctx)
     return aom_init(avctx, aom_codec_av1_cx());
 }
 
+static av_cold int av1_reconf(AVCodecContext *avctx)
+{
+    AOMContext *ctx = avctx->priv_data;
+    int loglevel;
+    int res;
+
+    res = aom_config(avctx, ctx->encoder.iface);
+    if (res < 0)
+        return res;
+
+    res = aom_codec_enc_config_set(&ctx->encoder, &ctx->enccfg);
+    loglevel = res != AOM_CODEC_OK ? AV_LOG_WARNING : AV_LOG_DEBUG;
+    av_log(avctx, loglevel, "Reconfigure options:\n");
+    dump_enc_cfg(avctx, &ctx->enccfg, loglevel);
+    if (res != AOM_CODEC_OK) {
+        log_encoder_error(avctx, "Failed to reconfigure encoder");
+        return AVERROR(EINVAL);
+    }
+
+    res = aom_codecctl(avctx);
+    if (res < 0)
+        return res;
+
+    return 0;
+}
+
 #define OFFSET(x) offsetof(AOMContext, x)
 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
 static const AVOption options[] = {
@@ -1567,6 +1617,7 @@ FFCodec ff_libaom_av1_encoder = {
     .p.id           = AV_CODEC_ID_AV1,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
                       AV_CODEC_CAP_ENCODER_RECON_FRAME |
+                      AV_CODEC_CAP_PARAM_CHANGE |
                       AV_CODEC_CAP_OTHER_THREADS,
     .color_ranges   = AVCOL_RANGE_MPEG | AVCOL_RANGE_JPEG,
     .p.profiles     = NULL_IF_CONFIG_SMALL(ff_av1_profiles),
@@ -1574,6 +1625,7 @@ FFCodec ff_libaom_av1_encoder = {
     .p.wrapper_name = "libaom",
     .priv_data_size = sizeof(AOMContext),
     .init           = av1_init,
+    .reconf         = av1_reconf,
     FF_CODEC_ENCODE_CB(aom_encode),
     .close          = aom_free,
     .caps_internal  = FF_CODEC_CAP_NOT_INIT_THREADSAFE |
-- 
2.48.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to