Commit 8e65bb0620 for aom

commit 8e65bb0620f2aa6586cdcfe54eef12b843b5b334
Author: Lin Zheng <linzhen@google.com>
Date:   Wed Sep 9 13:59:11 2026 +0000

    Reallocate frame buffer on resolution change in lookahead

    Fix the assertion by calling aom_realloc_frame_buffer() whenever
    new_dimensions is true, ensuring the frame buffer and its
    associated image pyramid are reallocated properly for the new frame size.

    Bug: 558434716

    Change-Id: I0f7f92798a0a1aec60c2c7f623f3c227d78c784c

diff --git a/av1/encoder/lookahead.c b/av1/encoder/lookahead.c
index ee2e0659d1..7dcabf9710 100644
--- a/av1/encoder/lookahead.c
+++ b/av1/encoder/lookahead.c
@@ -105,7 +105,7 @@ int av1_lookahead_push(struct lookahead_ctx *ctx, const YV12_BUFFER_CONFIG *src,
   int uv_height = src->uv_crop_height;
   int subsampling_x = src->subsampling_x;
   int subsampling_y = src->subsampling_y;
-  int larger_dimensions, new_dimensions;
+  int new_dimensions;

   assert(ctx->read_ctxs[ENCODE_STAGE].valid == 1);
   if (ctx->read_ctxs[ENCODE_STAGE].sz + ctx->max_pre_frames > ctx->max_sz)
@@ -122,31 +122,13 @@ int av1_lookahead_push(struct lookahead_ctx *ctx, const YV12_BUFFER_CONFIG *src,
                    height != buf->img.y_crop_height ||
                    uv_width != buf->img.uv_crop_width ||
                    uv_height != buf->img.uv_crop_height;
-  larger_dimensions =
-      width > buf->img.y_crop_width || height > buf->img.y_crop_height ||
-      uv_width > buf->img.uv_crop_width || uv_height > buf->img.uv_crop_height;
-  assert(!larger_dimensions || new_dimensions);
-
-  if (larger_dimensions) {
-    YV12_BUFFER_CONFIG new_img;
-    memset(&new_img, 0, sizeof(new_img));
-    if (aom_alloc_frame_buffer(&new_img, width, height, subsampling_x,
-                               subsampling_y, use_highbitdepth,
-                               AOM_BORDER_IN_PIXELS, 0, alloc_pyramid, 0))
+
+  if (new_dimensions) {
+    if (aom_realloc_frame_buffer(&buf->img, width, height, subsampling_x,
+                                 subsampling_y, use_highbitdepth,
+                                 AOM_BORDER_IN_PIXELS, 0, NULL, NULL, NULL,
+                                 alloc_pyramid, 0))
       return 1;
-    aom_free_frame_buffer(&buf->img);
-    buf->img = new_img;
-  } else if (new_dimensions) {
-    buf->img.y_width = src->y_width;
-    buf->img.y_height = src->y_height;
-    buf->img.uv_width = src->uv_width;
-    buf->img.uv_height = src->uv_height;
-    buf->img.y_crop_width = src->y_crop_width;
-    buf->img.y_crop_height = src->y_crop_height;
-    buf->img.uv_crop_width = src->uv_crop_width;
-    buf->img.uv_crop_height = src->uv_crop_height;
-    buf->img.subsampling_x = src->subsampling_x;
-    buf->img.subsampling_y = src->subsampling_y;
   }
   av1_copy_and_extend_frame(src, &buf->img);

diff --git a/test/encode_api_test.cc b/test/encode_api_test.cc
index e67282226d..cf8d636e19 100644
--- a/test/encode_api_test.cc
+++ b/test/encode_api_test.cc
@@ -2684,4 +2684,63 @@ TEST(EncodeAPI, Buganizer503810640V2) {
   ASSERT_EQ(aom_codec_destroy(&codec), AOM_CODEC_OK);
 }

+#if !CONFIG_REALTIME_ONLY
+TEST(EncodeAPI, Buganizer558434716) {
+  aom_codec_iface_t *iface = aom_codec_av1_cx();
+  aom_codec_enc_cfg_t cfg;
+  ASSERT_EQ(aom_codec_enc_config_default(iface, &cfg, AOM_USAGE_GOOD_QUALITY),
+            AOM_CODEC_OK);
+
+  cfg.g_w = 128;
+  cfg.g_h = 96;
+  cfg.g_forced_max_frame_width = 1920;
+  cfg.g_forced_max_frame_height = 1080;
+  cfg.g_pass = AOM_RC_ONE_PASS;
+  cfg.g_lag_in_frames = 0;
+  cfg.g_threads = 1;
+
+  aom_codec_ctx_t enc;
+  ASSERT_EQ(aom_codec_enc_init(&enc, iface, &cfg, 0), AOM_CODEC_OK);
+
+  aom_image_t *img_small = aom_img_alloc(nullptr, AOM_IMG_FMT_I420, 128, 96, 1);
+  ASSERT_NE(img_small, nullptr);
+  FillImage(img_small, 128);
+
+  aom_image_t *img_large =
+      aom_img_alloc(nullptr, AOM_IMG_FMT_I420, 320, 240, 1);
+  ASSERT_NE(img_large, nullptr);
+  FillImage(img_large, 128);
+
+  // Frame 0 at 128x96
+  ASSERT_EQ(aom_codec_encode(&enc, img_small, 0, 1, 0), AOM_CODEC_OK);
+
+  // Switch to larger resolution
+  cfg.g_w = 320;
+  cfg.g_h = 240;
+  ASSERT_EQ(aom_codec_enc_config_set(&enc, &cfg), AOM_CODEC_OK);
+
+  // Frame 1 at 320x240
+  ASSERT_EQ(aom_codec_encode(&enc, img_large, 1, 1, AOM_EFLAG_FORCE_KF),
+            AOM_CODEC_OK);
+
+  // Switch back to smaller resolution
+  cfg.g_w = 128;
+  cfg.g_h = 96;
+  ASSERT_EQ(aom_codec_enc_config_set(&enc, &cfg), AOM_CODEC_OK);
+
+  // Frame 2 at 128x96 (keyframe)
+  ASSERT_EQ(aom_codec_encode(&enc, img_small, 2, 1, AOM_EFLAG_FORCE_KF),
+            AOM_CODEC_OK);
+
+  // Frames 3+ at 128x96 (interframes referencing frame 2)
+  for (int i = 3; i < 8; ++i) {
+    ASSERT_EQ(aom_codec_encode(&enc, img_small, i, 1, 0), AOM_CODEC_OK);
+  }
+
+  aom_img_free(img_small);
+  aom_img_free(img_large);
+  ASSERT_EQ(aom_codec_destroy(&enc), AOM_CODEC_OK);
+}
+#endif  // !CONFIG_REALTIME_ONLY
+
 }  // namespace