Add minimum_qp to VideoEncoder::EncoderInfo

The minimum QP field will be used to signal what the QP value will be
once the encoder reach its target video quality. This will be used
in the generalized QP convergence detection.

Bug: chromium:328598314
Change-Id: I82299cd921e3c091e651218d1e3f337875176567
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/355701
Reviewed-by: Erik Språng <sprang@webrtc.org>
Commit-Queue: Johannes Kron <kron@webrtc.org>
Reviewed-by: Markus Handell <handellm@google.com>
Cr-Commit-Position: refs/heads/main@{#42559}
diff --git a/api/video_codecs/video_encoder.h b/api/video_codecs/video_encoder.h
index 49ea6e1..1fcde28 100644
--- a/api/video_codecs/video_encoder.h
+++ b/api/video_codecs/video_encoder.h
@@ -259,6 +259,11 @@
     // Indicates whether or not QP value encoder writes into frame/slice/tile
     // header can be interpreted as average frame/slice/tile QP.
     absl::optional<bool> is_qp_trusted;
+
+    // The minimum QP that the encoder is expected to use with the current
+    // configuration. This may be used to determine if the encoder has reached
+    // its target video quality for static screenshare content.
+    absl::optional<int> minimum_qp;
   };
 
   struct RTC_EXPORT RateControlParameters {
diff --git a/modules/video_coding/codecs/av1/libaom_av1_encoder.cc b/modules/video_coding/codecs/av1/libaom_av1_encoder.cc
index a42c08e..93eeddd 100644
--- a/modules/video_coding/codecs/av1/libaom_av1_encoder.cc
+++ b/modules/video_coding/codecs/av1/libaom_av1_encoder.cc
@@ -59,6 +59,8 @@
 
 // Encoder configuration parameters
 constexpr int kQpMin = 10;
+constexpr int kAv1ScreenshareMinimumQindex =
+    40;  // Min qindex corresponding to kQpMin.
 constexpr int kUsageProfile = AOM_USAGE_REALTIME;
 constexpr int kMinQindex = 145;  // Min qindex threshold for QP scaling.
 constexpr int kMaxQindex = 205;  // Max qindex threshold for QP scaling.
@@ -866,6 +868,8 @@
     info.resolution_bitrate_limits =
         encoder_info_override_.resolution_bitrate_limits();
   }
+
+  info.minimum_qp = kAv1ScreenshareMinimumQindex;
   return info;
 }
 
diff --git a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc
index 6dcdbfd..3d2d482 100644
--- a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc
+++ b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc
@@ -68,6 +68,7 @@
 // bitstream range of [0, 127] and not the user-level range of [0,63].
 constexpr int kLowVp8QpThreshold = 29;
 constexpr int kHighVp8QpThreshold = 95;
+constexpr int kVp8ScreenshareMinimumQp = 15;
 
 constexpr int kTokenPartitions = VP8_ONE_TOKENPARTITION;
 constexpr uint32_t kVp832ByteAlign = 32u;
@@ -1348,6 +1349,10 @@
         }
       }
     }
+
+    if (codec_.mode == VideoCodecMode::kScreensharing) {
+      info.minimum_qp = kVp8ScreenshareMinimumQp;
+    }
   }
 
   return info;
diff --git a/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc b/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc
index cef37a9..b9a9ffe 100644
--- a/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc
+++ b/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc
@@ -1825,6 +1825,10 @@
       info.preferred_pixel_formats = {VideoFrameBuffer::Type::kI420,
                                       VideoFrameBuffer::Type::kNV12};
     }
+
+    if (codec_.mode == VideoCodecMode::kScreensharing) {
+      info.minimum_qp = variable_framerate_screenshare::kMinQP;
+    }
   }
   if (!encoder_info_override_.resolution_bitrate_limits().empty()) {
     info.resolution_bitrate_limits =