diff --git a/api/video_codecs/video_encoder.h b/api/video_codecs/video_encoder.h index 49ea6e1c0e..1fcde28fdc 100644 --- a/api/video_codecs/video_encoder.h +++ b/api/video_codecs/video_encoder.h @@ -259,6 +259,11 @@ class RTC_EXPORT VideoEncoder { // Indicates whether or not QP value encoder writes into frame/slice/tile // header can be interpreted as average frame/slice/tile QP. absl::optional 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 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 a42c08e520..93eeddd8b2 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 @@ namespace { // 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 @@ VideoEncoder::EncoderInfo LibaomAv1Encoder::GetEncoderInfo() const { 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 6dcdbfd2c8..3d2d4821b2 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 @@ constexpr char kVp8ForcePartitionResilience[] = // 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 @@ VideoEncoder::EncoderInfo LibvpxVp8Encoder::GetEncoderInfo() const { } } } + + 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 cef37a9300..b9a9ffe9a9 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 @@ VideoEncoder::EncoderInfo LibvpxVp9Encoder::GetEncoderInfo() const { 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 =