Ensure calls to QP convergence controller are on the same sequence

The original CL overlooked the possibility that the encoder may be
reconfigured in the middle of a stream.

Restructure the code so that all calls to QP convergence controller
happen on the encoder queue.

A side effect of this CL is that `EncodedImage::SetAtTargetQuality()`
is never called. The information is supplied to the frame cadence
adapter directly without this intermediate step.

`EncodedImage::SetAtTargetQuality()` and
`EncodedImage::IsAtTargetQuality()` are being marked as deprecated
in https://webrtc-review.googlesource.com/c/src/+/359660.

Bug: chromium:359410061
Change-Id: I941b5f60b1a9fd7694dbedf2f3e4ff5253ccf357
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/359640
Commit-Queue: Johannes Kron <kron@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Reviewed-by: Markus Handell <handellm@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#42788}
This commit is contained in:
Johannes Kron 2024-08-15 11:49:54 +02:00 committed by WebRTC LUCI CQ
parent e50b7305e0
commit b47cd6fbe3
4 changed files with 23 additions and 16 deletions

View File

@ -44,6 +44,7 @@ void QualityConvergenceController::Initialize(
absl::optional<int> static_qp_threshold,
VideoCodecType codec,
const FieldTrialsView& trials) {
RTC_DCHECK(sequence_checker_.IsCurrent());
RTC_CHECK(number_of_layers > 0);
number_of_layers_ = number_of_layers;
convergence_monitors_.clear();
@ -61,11 +62,20 @@ bool QualityConvergenceController::AddSampleAndCheckTargetQuality(
int layer_index,
int qp,
bool is_refresh_frame) {
RTC_DCHECK(sequence_checker_.IsCurrent());
RTC_CHECK(initialized_);
if (layer_index < 0 || layer_index >= number_of_layers_) {
return false;
}
// TODO(kron): Remove temporary check that verifies that the initialization is
// working as expected. See https://crbug.com/359410061.
RTC_DCHECK(number_of_layers_ ==
static_cast<int>(convergence_monitors_.size()));
if (number_of_layers_ != static_cast<int>(convergence_monitors_.size())) {
return false;
}
convergence_monitors_[layer_index]->AddSample(qp, is_refresh_frame);
return convergence_monitors_[layer_index]->AtTargetQuality();
}

View File

@ -16,6 +16,7 @@
#include "absl/types/optional.h"
#include "api/field_trials_view.h"
#include "api/sequence_checker.h"
#include "api/video/video_codec_type.h"
#include "video/quality_convergence_monitor.h"
@ -41,6 +42,7 @@ class QualityConvergenceController {
bool initialized_ = false;
int number_of_layers_ = 0;
std::vector<std::unique_ptr<QualityConvergenceMonitor>> convergence_monitors_;
SequenceChecker sequence_checker_{SequenceChecker::kDetached};
};
} // namespace webrtc

View File

@ -2090,22 +2090,11 @@ EncodedImage VideoStreamEncoder::AugmentEncodedImage(
.value_or(-1);
}
// Check if the encoded image has reached target quality.
const size_t simulcast_index = encoded_image.SimulcastIndex().value_or(0);
bool at_target_quality =
quality_convergence_controller_.AddSampleAndCheckTargetQuality(
simulcast_index, image_copy.qp_,
image_copy.IsSteadyStateRefreshFrame());
image_copy.SetAtTargetQuality(at_target_quality);
TRACE_EVENT2("webrtc", "VideoStreamEncoder::AugmentEncodedImage",
"stream_idx", stream_idx, "qp", image_copy.qp_);
TRACE_EVENT_INSTANT2("webrtc", "VideoStreamEncoder::AugmentEncodedImage",
TRACE_EVENT_SCOPE_GLOBAL, "simulcast_idx",
simulcast_index, "at_target_quality", at_target_quality);
RTC_LOG(LS_VERBOSE) << __func__ << " ntp time " << encoded_image.NtpTimeMs()
<< " stream_idx " << stream_idx << " qp "
<< image_copy.qp_ << " at target quality "
<< at_target_quality;
<< image_copy.qp_;
return image_copy;
}
@ -2128,11 +2117,16 @@ EncodedImageCallback::Result VideoStreamEncoder::OnEncodedImage(
unsigned int image_width = image_copy._encodedWidth;
unsigned int image_height = image_copy._encodedHeight;
encoder_queue_->PostTask([this, codec_type, image_width, image_height,
simulcast_index,
at_target_quality =
image_copy.IsAtTargetQuality()] {
simulcast_index, qp = image_copy.qp_,
is_steady_state_refresh_frame =
image_copy.IsSteadyStateRefreshFrame()] {
RTC_DCHECK_RUN_ON(encoder_queue_.get());
// Check if the encoded image has reached target quality.
bool at_target_quality =
quality_convergence_controller_.AddSampleAndCheckTargetQuality(
simulcast_index, qp, is_steady_state_refresh_frame);
// Let the frame cadence adapter know about quality convergence.
if (frame_cadence_adapter_)
frame_cadence_adapter_->UpdateLayerQualityConvergence(simulcast_index,

View File

@ -422,7 +422,8 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface,
// The quality convergence controller is used to determine if a codec has
// reached its target quality. This is used for screenshare to determine when
// there's no need to continue encoding the same repeated frame.
QualityConvergenceController quality_convergence_controller_;
QualityConvergenceController quality_convergence_controller_
RTC_GUARDED_BY(encoder_queue_);
// Enables encoder switching on initialization failures.
bool switch_encoder_on_init_failures_;