Commit 20f44593be for aom

commit 20f44593bea8b2ce834098fe5c623075b77d0dbc
Author: Ihor Buhaiov <freedbrt@gmail.com>
Date:   Mon Oct 19 23:30:03 2026 +0200

    rtc: Build both MV cost tables at frame level

    The frame level MV cost update only builds the table for the current
    MV precision. With nonrd pick mode and the MV cost update level off,
    the realtime only default, it runs only on key frames and on the first
    inter frame after them. av1_pick_and_set_high_precision_mv() still
    picks the precision from q on every inter frame. So if the first inter
    frame has q below HIGH_PRECISION_MV_QTHRESH and a later frame goes
    above it, that frame codes with the 1/4 pel table, which was never
    built and is still all zeros. MV components then cost no rate. The
    default build updates the costs per superblock row, but frames that
    skip CDF updates skip that too and can hit the same zero table.

    Build the table for the other precision as well whenever the frame
    level update runs. In realtime that is two more table builds per key
    frame interval.

    Found with VBR at 30 fps and max q 63, where the first inter frame
    gets q around 100. For example niklas 640x480 at speed 9, 3000 kbps
    dropping to 400 kbps at frame 100: 194 of 299 inter frames used the
    zero table. In 570 test encodes (camera and screen clips, speeds 7 to
    11, CBR and VBR, bitrate drops, 1 and 4 threads) 69 hit it, none of
    them CBR. With this change none do, and the encodes that never hit it
    give the same output. On the 19 rate curves where 3 or 4 of the 4
    points changed, BD rate is -1.56% to +0.15%, median -0.43%.

    Change-Id: I4089f07e5bbce77fe574ffea65ddcca47455423c

diff --git a/av1/encoder/rd.c b/av1/encoder/rd.c
index 9a6e89bf01..d379858a3b 100644
--- a/av1/encoder/rd.c
+++ b/av1/encoder/rd.c
@@ -825,9 +825,16 @@ void av1_initialize_rd_consts(AV1_COMP *cpi) {
   const INTER_MODE_SPEED_FEATURES *const inter_sf = &cpi->sf.inter_sf;
   // Frame level mv cost update
   if (is_frame_level_cost_upd_freq_set(cm, inter_sf->mv_cost_upd_level,
-                                       use_nonrd_pick_mode, frames_since_key))
+                                       use_nonrd_pick_mode, frames_since_key)) {
+    // Also build the table for the other precision. A later frame that skips
+    // this update can switch to it in av1_pick_and_set_high_precision_mv().
+    if (!cm->features.cur_frame_force_integer_mv) {
+      av1_fill_mv_costs(&cm->fc->nmvc, 0, !cm->features.allow_high_precision_mv,
+                        x->mv_costs);
+    }
     av1_fill_mv_costs(&cm->fc->nmvc, cm->features.cur_frame_force_integer_mv,
                       cm->features.allow_high_precision_mv, x->mv_costs);
+  }

   // Frame level coefficient cost update
   if (is_frame_level_cost_upd_freq_set(cm, inter_sf->coeff_cost_upd_level,