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:
parent
e50b7305e0
commit
b47cd6fbe3
@ -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();
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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_;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user