- lavc/aomenc: Force default qmax of 0 if crf was set to 0
- avcodec/libaomenc: Avoid copying data, allow user-supplied buffers
- lavc/libaomenc: Show encoder config as a warning in case of failed initialization
- avcodec/libaomenc: use ctx->usage to get default cfg
- avcodec/libaomenc: remove the redundant initialization
- avcodec/libaomenc: Add unmet target level warning
- avcodec/libaomenc: Expose the allintra usage mode
- avcodec/libaomenc: Get number of operating points

Index: libavcodec/libaomenc.c
--- libavcodec/libaomenc.c.orig
+++ libavcodec/libaomenc.c
@@ -36,6 +36,7 @@
 
 #include "av1.h"
 #include "avcodec.h"
+#include "encode.h"
 #include "internal.h"
 #include "packet_internal.h"
 #include "profiles.h"
@@ -194,6 +195,15 @@ static const char *const ctlidstr[] = {
     [AV1E_SET_ENABLE_SMOOTH_INTERINTRA] = "AV1E_SET_ENABLE_SMOOTH_INTERINTRA",
     [AV1E_SET_ENABLE_REF_FRAME_MVS]     = "AV1E_SET_ENABLE_REF_FRAME_MVS",
 #endif
+#ifdef AOM_CTRL_AV1E_GET_NUM_OPERATING_POINTS
+    [AV1E_GET_NUM_OPERATING_POINTS]     = "AV1E_GET_NUM_OPERATING_POINTS",
+#endif
+#ifdef AOM_CTRL_AV1E_GET_SEQ_LEVEL_IDX
+    [AV1E_GET_SEQ_LEVEL_IDX]            = "AV1E_GET_SEQ_LEVEL_IDX",
+#endif
+#ifdef AOM_CTRL_AV1E_GET_TARGET_SEQ_LEVEL_IDX
+    [AV1E_GET_TARGET_SEQ_LEVEL_IDX]     = "AV1E_GET_TARGET_SEQ_LEVEL_IDX",
+#endif
 };
 
 static av_cold void log_encoder_error(AVCodecContext *avctx, const char *desc)
@@ -208,10 +218,10 @@ static av_cold void log_encoder_error(AVCodecContext *
 }
 
 static av_cold void dump_enc_cfg(AVCodecContext *avctx,
-                                 const struct aom_codec_enc_cfg *cfg)
+                                 const struct aom_codec_enc_cfg *cfg,
+                                 int level)
 {
     int width = -30;
-    int level = AV_LOG_DEBUG;
 
     av_log(avctx, level, "aom_codec_enc_cfg\n");
     av_log(avctx, level, "generic settings\n"
@@ -319,10 +329,73 @@ static av_cold int codecctl_int(AVCodecContext *avctx,
     return 0;
 }
 
+#if defined(AOM_CTRL_AV1E_GET_NUM_OPERATING_POINTS) && \
+    defined(AOM_CTRL_AV1E_GET_SEQ_LEVEL_IDX) && \
+    defined(AOM_CTRL_AV1E_GET_TARGET_SEQ_LEVEL_IDX)
+static av_cold int codecctl_intp(AVCodecContext *avctx,
+#ifdef UENUM1BYTE
+                                 aome_enc_control_id id,
+#else
+                                 enum aome_enc_control_id id,
+#endif
+                                 int* ptr)
+{
+    AOMContext *ctx = avctx->priv_data;
+    char buf[80];
+    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",
+                 ctlidstr[id]);
+        log_encoder_error(avctx, buf);
+        return AVERROR(EINVAL);
+    }
+
+    return 0;
+}
+#endif
+
 static av_cold int aom_free(AVCodecContext *avctx)
 {
     AOMContext *ctx = avctx->priv_data;
 
+#if defined(AOM_CTRL_AV1E_GET_NUM_OPERATING_POINTS) && \
+    defined(AOM_CTRL_AV1E_GET_SEQ_LEVEL_IDX) && \
+    defined(AOM_CTRL_AV1E_GET_TARGET_SEQ_LEVEL_IDX)
+    if (!(avctx->flags & AV_CODEC_FLAG_PASS1)) {
+        int num_operating_points;
+        int levels[32];
+        int target_levels[32];
+
+        if (!codecctl_intp(avctx, AV1E_GET_NUM_OPERATING_POINTS,
+                           &num_operating_points) &&
+            !codecctl_intp(avctx, AV1E_GET_SEQ_LEVEL_IDX, levels) &&
+            !codecctl_intp(avctx, AV1E_GET_TARGET_SEQ_LEVEL_IDX,
+                           target_levels)) {
+            for (int i = 0; i < num_operating_points; i++) {
+                if (levels[i] > target_levels[i]) {
+                    // Warn when the target level was not met
+                    av_log(avctx, AV_LOG_WARNING,
+                           "Could not encode to target level %d.%d for "
+                           "operating point %d. The output level is %d.%d.\n",
+                           2 + (target_levels[i] >> 2), target_levels[i] & 3,
+                           i, 2 + (levels[i] >> 2), levels[i] & 3);
+                } else if (target_levels[i] < 31) {
+                    // Log the encoded level if a target level was given
+                    av_log(avctx, AV_LOG_INFO,
+                           "Output level for operating point %d is %d.%d.\n",
+                           i, 2 + (levels[i] >> 2), levels[i] & 3);
+                }
+            }
+        }
+    }
+#endif
+
     aom_codec_destroy(&ctx->encoder);
     av_freep(&ctx->twopass_stats.buf);
     av_freep(&avctx->stats_out);
@@ -596,7 +669,7 @@ static av_cold int aom_init(AVCodecContext *avctx,
     av_log(avctx, AV_LOG_INFO, "%s\n", aom_codec_version_str());
     av_log(avctx, AV_LOG_VERBOSE, "%s\n", aom_codec_build_config());
 
-    if ((res = aom_codec_enc_config_default(iface, &enccfg, 0)) != AOM_CODEC_OK) {
+    if ((res = aom_codec_enc_config_default(iface, &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);
@@ -611,7 +684,7 @@ static av_cold int aom_init(AVCodecContext *avctx,
             return AVERROR(EINVAL);
         }
 
-    dump_enc_cfg(avctx, &enccfg);
+    dump_enc_cfg(avctx, &enccfg, AV_LOG_DEBUG);
 
     enccfg.g_w            = avctx->width;
     enccfg.g_h            = avctx->height;
@@ -620,8 +693,6 @@ static av_cold int aom_init(AVCodecContext *avctx,
     enccfg.g_threads      =
         FFMIN(avctx->thread_count ? avctx->thread_count : av_cpu_count(), 64);
 
-    enccfg.g_usage        = ctx->usage;
-
     if (ctx->lag_in_frames >= 0)
         enccfg.g_lag_in_frames = ctx->lag_in_frames;
 
@@ -654,8 +725,11 @@ static av_cold int aom_init(AVCodecContext *avctx,
 
     if (avctx->qmin >= 0)
         enccfg.rc_min_quantizer = avctx->qmin;
-    if (avctx->qmax >= 0)
+    if (avctx->qmax >= 0) {
         enccfg.rc_max_quantizer = avctx->qmax;
+    } else if (!ctx->crf) {
+        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) {
@@ -742,13 +816,14 @@ static av_cold int aom_init(AVCodecContext *avctx,
     if (res < 0)
         return res;
 
-    dump_enc_cfg(avctx, &enccfg);
     /* 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);
 
     // codec control failures are currently treated only as warnings
     av_log(avctx, AV_LOG_DEBUG, "aom_codec_control\n");
@@ -943,7 +1018,6 @@ static inline void cx_pktcpy(AOMContext *ctx,
     dst->sz       = src->data.frame.sz;
     dst->buf      = src->data.frame.buf;
 #ifdef AOM_FRAME_IS_INTRAONLY
-    dst->have_sse = 0;
     dst->frame_number = ++ctx->frame_number;
     dst->have_sse = ctx->have_sse;
     if (ctx->have_sse) {
@@ -967,7 +1041,7 @@ static int storeframe(AVCodecContext *avctx, struct Fr
 {
     AOMContext *ctx = avctx->priv_data;
     int av_unused pict_type;
-    int ret = ff_alloc_packet2(avctx, pkt, cx_frame->sz, 0);
+    int ret = ff_get_encode_buffer(avctx, pkt, cx_frame->sz, 0);
     if (ret < 0) {
         av_log(avctx, AV_LOG_ERROR,
                "Error getting output packet of size %"SIZE_SPECIFIER".\n", cx_frame->sz);
@@ -1282,6 +1356,7 @@ static const AVOption options[] = {
     { "usage",           "Quality and compression efficiency vs speed trade-off", OFFSET(usage), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE, "usage"},
     { "good",            "Good quality",      0, AV_OPT_TYPE_CONST, {.i64 = 0 /* AOM_USAGE_GOOD_QUALITY */}, 0, 0, VE, "usage"},
     { "realtime",        "Realtime encoding", 0, AV_OPT_TYPE_CONST, {.i64 = 1 /* AOM_USAGE_REALTIME */},     0, 0, VE, "usage"},
+    { "allintra",        "All Intra encoding", 0, AV_OPT_TYPE_CONST, {.i64 = 2 /* AOM_USAGE_ALL_INTRA */},    0, 0, VE, "usage"},
     { "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"},
     { "psnr",            NULL,         0, AV_OPT_TYPE_CONST, {.i64 = AOM_TUNE_PSNR}, 0, 0, VE, "tune"},
     { "ssim",            NULL,         0, AV_OPT_TYPE_CONST, {.i64 = AOM_TUNE_SSIM}, 0, 0, VE, "tune"},
@@ -1341,11 +1416,12 @@ AVCodec ff_libaom_av1_encoder = {
     .long_name      = NULL_IF_CONFIG_SMALL("libaom AV1"),
     .type           = AVMEDIA_TYPE_VIDEO,
     .id             = AV_CODEC_ID_AV1,
+    .capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
+                      AV_CODEC_CAP_OTHER_THREADS,
     .priv_data_size = sizeof(AOMContext),
     .init           = av1_init,
     .encode2        = aom_encode,
     .close          = aom_free,
-    .capabilities   = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS,
     .caps_internal  = FF_CODEC_CAP_AUTO_THREADS,
     .profiles       = NULL_IF_CONFIG_SMALL(ff_av1_profiles),
     .priv_class     = &class_aom,
