Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Unified Diff: webrtc/media/engine/webrtcvideoengine2.cc

Issue 2304363002: Let ViEEncoder express resolution requests as Sinkwants (Closed)
Patch Set: Rebased. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/media/engine/webrtcvideoengine2.h ('k') | webrtc/media/engine/webrtcvideoengine2_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/media/engine/webrtcvideoengine2.cc
diff --git a/webrtc/media/engine/webrtcvideoengine2.cc b/webrtc/media/engine/webrtcvideoengine2.cc
index fcc92546ddf170123ecd084256c28689082ef007..d3e71a381f795ec286202c0bd6c034a9d3a72155 100644
--- a/webrtc/media/engine/webrtcvideoengine2.cc
+++ b/webrtc/media/engine/webrtcvideoengine2.cc
@@ -31,7 +31,6 @@
#include "webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.h"
#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
#include "webrtc/system_wrappers/include/field_trial.h"
-#include "webrtc/system_wrappers/include/metrics.h"
#include "webrtc/video_decoder.h"
#include "webrtc/video_encoder.h"
@@ -237,17 +236,6 @@ static bool ValidateStreamParams(const StreamParams& sp) {
return true;
}
-inline bool ContainsHeaderExtension(
- const std::vector<webrtc::RtpExtension>& extensions,
- const std::string& uri) {
- for (const auto& kv : extensions) {
- if (kv.uri == uri) {
- return true;
- }
- }
- return false;
-}
-
// Returns true if the given codec is disallowed from doing simulcast.
bool IsCodecBlacklistedForSimulcast(const std::string& codec_name) {
return CodecNamesEq(codec_name, kH264CodecName) ||
@@ -395,9 +383,6 @@ static const int kDefaultQpMax = 56;
static const int kDefaultRtcpReceiverReportSsrc = 1;
-// Down grade resolution at most 2 times for CPU reasons.
-static const int kMaxCpuDowngrades = 2;
-
// Minimum time interval for logging stats.
static const int64_t kStatsLogIntervalMs = 10000;
@@ -1567,10 +1552,7 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::WebRtcVideoSendStream(
ssrcs_(sp.ssrcs),
ssrc_groups_(sp.ssrc_groups),
call_(call),
- cpu_restricted_counter_(0),
- number_of_cpu_adapt_changes_(0),
- frame_count_(0),
- cpu_restricted_frame_count_(0),
+ enable_cpu_overuse_detection_(enable_cpu_overuse_detection),
source_(nullptr),
external_encoder_factory_(external_encoder_factory),
stream_(nullptr),
@@ -1593,38 +1575,16 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::WebRtcVideoSendStream(
parameters_.config.rtp.rtcp_mode = send_params.rtcp.reduced_size
? webrtc::RtcpMode::kReducedSize
: webrtc::RtcpMode::kCompound;
- parameters_.config.overuse_callback =
- enable_cpu_overuse_detection ? this : nullptr;
-
- // Only request rotation at the source when we positively know that the remote
- // side doesn't support the rotation extension. This allows us to prepare the
- // encoder in the expectation that rotation is supported - which is the common
- // case.
- sink_wants_.rotation_applied =
- rtp_extensions &&
- !ContainsHeaderExtension(*rtp_extensions,
- webrtc::RtpExtension::kVideoRotationUri);
-
if (codec_settings) {
SetCodec(*codec_settings);
}
}
WebRtcVideoChannel2::WebRtcVideoSendStream::~WebRtcVideoSendStream() {
- DisconnectSource();
if (stream_ != NULL) {
call_->DestroyVideoSendStream(stream_);
}
DestroyVideoEncoder(&allocated_encoder_);
- UpdateHistograms();
-}
-
-void WebRtcVideoChannel2::WebRtcVideoSendStream::UpdateHistograms() const {
- const int kMinRequiredFrames = 200;
- if (frame_count_ > kMinRequiredFrames) {
- RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.CpuLimitedResolutionInPercent",
- cpu_restricted_frame_count_ * 100 / frame_count_);
- }
}
void WebRtcVideoChannel2::WebRtcVideoSendStream::OnFrame(
@@ -1658,10 +1618,6 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::OnFrame(
last_frame_timestamp_us_ = video_frame.timestamp_us();
- ++frame_count_;
- if (cpu_restricted_counter_ > 0)
- ++cpu_restricted_frame_count_;
-
// Forward frame to the encoder regardless if we are sending or not. This is
// to ensure that the encoder can be reconfigured with the correct frame size
// as quickly as possible.
@@ -1678,9 +1634,6 @@ bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoSend(
// Ignore |options| pointer if |enable| is false.
bool options_present = enable && options;
bool source_changing = source_ != source;
- if (source_changing) {
- DisconnectSource();
- }
if (options_present) {
VideoOptions old_options = parameters_.options;
@@ -1692,8 +1645,7 @@ bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoSend(
if (source_changing) {
rtc::CritScope cs(&lock_);
- if (source == nullptr && encoder_sink_ != nullptr &&
- last_frame_info_.width > 0) {
+ if (source == nullptr && last_frame_info_.width > 0 && encoder_sink_) {
LOG(LS_VERBOSE) << "Disabling capturer, sending black frame.";
// Force this black frame not to be dropped due to timestamp order
// check. As IncomingCapturedFrame will drop the frame if this frame's
@@ -1709,34 +1661,30 @@ bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoSend(
encoder_sink_->OnFrame(webrtc::VideoFrame(
black_buffer, last_frame_info_.rotation, last_frame_timestamp_us_));
}
- source_ = source;
}
- if (source_changing && source_) {
- // |source_->AddOrUpdateSink| may not be called while holding |lock_| since
- // that might cause a lock order inversion.
- source_->AddOrUpdateSink(this, sink_wants_);
+ // TODO(perkj, nisse): Remove |source_| and directly call
+ // |stream_|->SetSource(source) once the video frame types have been
+ // merged.
+ if (source_ && stream_) {
+ stream_->SetSource(
+ nullptr, webrtc::VideoSendStream::DegradationPreference::kBalanced);
+ }
+ // Switch to the new source.
+ source_ = source;
+ if (source && stream_) {
+ // Do not adapt resolution for screen content as this will likely
+ // result in blurry and unreadable text.
+ stream_->SetSource(
+ this, enable_cpu_overuse_detection_ &&
+ !parameters_.options.is_screencast.value_or(false)
+ ? webrtc::VideoSendStream::DegradationPreference::kBalanced
+ : webrtc::VideoSendStream::DegradationPreference::
+ kMaintainResolution);
}
return true;
}
-void WebRtcVideoChannel2::WebRtcVideoSendStream::DisconnectSource() {
- RTC_DCHECK_RUN_ON(&thread_checker_);
- if (source_ == nullptr) {
- return;
- }
-
- // |source_->RemoveSink| may not be called while holding |lock_| since
- // that might cause a lock order inversion.
- source_->RemoveSink(this);
- source_ = nullptr;
- // Reset |cpu_restricted_counter_| if the source is changed. It is not
- // possible to know if the video resolution is restricted by CPU usage after
- // the source is changed since the next source might be screen capture
- // with another resolution and frame rate.
- cpu_restricted_counter_ = 0;
-}
-
const std::vector<uint32_t>&
WebRtcVideoChannel2::WebRtcVideoSendStream::GetSsrcs() const {
return ssrcs_;
@@ -1864,16 +1812,6 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetSendParameters(
LOG(LS_INFO) << "RecreateWebRtcStream (send) because of SetSendParameters";
RecreateWebRtcStream();
}
-
- // |source_->AddOrUpdateSink| may not be called while holding |lock_| since
- // that might cause a lock order inversion.
- if (params.rtp_header_extensions) {
- sink_wants_.rotation_applied = !ContainsHeaderExtension(
- *params.rtp_header_extensions, webrtc::RtpExtension::kVideoRotationUri);
- if (source_) {
- source_->AddOrUpdateSink(this, sink_wants_);
- }
- }
}
bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpParameters(
@@ -2002,90 +1940,47 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetSend(bool send) {
UpdateSendState();
}
-void WebRtcVideoChannel2::WebRtcVideoSendStream::AddOrUpdateSink(
- VideoSinkInterface<webrtc::VideoFrame>* sink,
- const rtc::VideoSinkWants& wants) {
- // TODO(perkj): Actually consider the encoder |wants| and remove
- // WebRtcVideoSendStream::OnLoadUpdate(Load load).
- rtc::CritScope cs(&lock_);
- RTC_DCHECK(!encoder_sink_ || encoder_sink_ == sink);
- encoder_sink_ = sink;
-}
-
void WebRtcVideoChannel2::WebRtcVideoSendStream::RemoveSink(
VideoSinkInterface<webrtc::VideoFrame>* sink) {
- rtc::CritScope cs(&lock_);
- RTC_DCHECK_EQ(encoder_sink_, sink);
- encoder_sink_ = nullptr;
-}
-
-void WebRtcVideoChannel2::WebRtcVideoSendStream::OnLoadUpdate(Load load) {
- if (worker_thread_ != rtc::Thread::Current()) {
- invoker_.AsyncInvoke<void>(
- RTC_FROM_HERE, worker_thread_,
- rtc::Bind(&WebRtcVideoChannel2::WebRtcVideoSendStream::OnLoadUpdate,
- this, load));
- return;
- }
RTC_DCHECK_RUN_ON(&thread_checker_);
- if (!source_) {
- return;
+ {
+ rtc::CritScope cs(&lock_);
+ RTC_DCHECK(encoder_sink_ == sink);
+ encoder_sink_ = nullptr;
}
+ source_->RemoveSink(this);
+}
- LOG(LS_INFO) << "OnLoadUpdate " << load << ", is_screencast: "
- << (parameters_.options.is_screencast
- ? (*parameters_.options.is_screencast ? "true" : "false")
- : "unset");
- // Do not adapt resolution for screen content as this will likely result in
- // blurry and unreadable text.
- if (parameters_.options.is_screencast.value_or(false))
- return;
-
- rtc::Optional<int> max_pixel_count;
- rtc::Optional<int> max_pixel_count_step_up;
- if (load == kOveruse) {
- rtc::CritScope cs(&lock_);
- if (cpu_restricted_counter_ >= kMaxCpuDowngrades) {
- return;
- }
- // The input video frame size will have a resolution with less than or
- // equal to |max_pixel_count| depending on how the source can scale the
- // input frame size.
- max_pixel_count = rtc::Optional<int>(
- (last_frame_info_.height * last_frame_info_.width * 3) / 5);
- // Increase |number_of_cpu_adapt_changes_| if
- // sink_wants_.max_pixel_count will be changed since
- // last time |source_->AddOrUpdateSink| was called. That is, this will
- // result in a new request for the source to change resolution.
- if (!sink_wants_.max_pixel_count ||
- *sink_wants_.max_pixel_count > *max_pixel_count) {
- ++number_of_cpu_adapt_changes_;
- ++cpu_restricted_counter_;
+void WebRtcVideoChannel2::WebRtcVideoSendStream::AddOrUpdateSink(
+ VideoSinkInterface<webrtc::VideoFrame>* sink,
+ const rtc::VideoSinkWants& wants) {
+ if (worker_thread_ == rtc::Thread::Current()) {
+ // AddOrUpdateSink is called on |worker_thread_| if this is the first
+ // registration of |sink|.
+ RTC_DCHECK_RUN_ON(&thread_checker_);
+ {
+ rtc::CritScope cs(&lock_);
+ encoder_sink_ = sink;
}
+ source_->AddOrUpdateSink(this, wants);
} else {
- RTC_DCHECK(load == kUnderuse);
- rtc::CritScope cs(&lock_);
- // The input video frame size will have a resolution with "one step up"
- // pixels than |max_pixel_count_step_up| where "one step up" depends on
- // how the source can scale the input frame size.
- max_pixel_count_step_up =
- rtc::Optional<int>(last_frame_info_.height * last_frame_info_.width);
- // Increase |number_of_cpu_adapt_changes_| if
- // sink_wants_.max_pixel_count_step_up will be changed since
- // last time |source_->AddOrUpdateSink| was called. That is, this will
- // result in a new request for the source to change resolution.
- if (sink_wants_.max_pixel_count ||
- (sink_wants_.max_pixel_count_step_up &&
- *sink_wants_.max_pixel_count_step_up < *max_pixel_count_step_up)) {
- ++number_of_cpu_adapt_changes_;
- --cpu_restricted_counter_;
- }
+ // Subsequent calls to AddOrUpdateSink will happen on the encoder task
+ // queue.
+ invoker_.AsyncInvoke<void>(RTC_FROM_HERE, worker_thread_, [this, wants] {
+ RTC_DCHECK_RUN_ON(&thread_checker_);
+ bool encoder_sink_valid = true;
+ {
+ rtc::CritScope cs(&lock_);
+ encoder_sink_valid = encoder_sink_ != nullptr;
+ }
+ // Since |source_| is still valid after a call to RemoveSink, check if
+ // |encoder_sink_| is still valid to check if this call should be
+ // cancelled.
+ if (source_ && encoder_sink_valid) {
+ source_->AddOrUpdateSink(this, wants);
+ }
+ });
}
- sink_wants_.max_pixel_count = max_pixel_count;
- sink_wants_.max_pixel_count_step_up = max_pixel_count_step_up;
- // |source_->AddOrUpdateSink| may not be called while holding |lock_| since
- // that might cause a lock order inversion.
- source_->AddOrUpdateSink(this, sink_wants_);
}
VideoSenderInfo WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo(
@@ -2106,9 +2001,9 @@ VideoSenderInfo WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo(
if (log_stats)
LOG(LS_INFO) << stats.ToString(rtc::TimeMillis());
- info.adapt_changes = number_of_cpu_adapt_changes_;
+ info.adapt_changes = stats.number_of_cpu_adapt_changes;
info.adapt_reason =
- cpu_restricted_counter_ <= 0 ? ADAPTREASON_NONE : ADAPTREASON_CPU;
+ stats.cpu_limited_resolution ? ADAPTREASON_CPU : ADAPTREASON_NONE;
// Get bandwidth limitation info from stream_->GetStats().
// Input resolution (output from video_adapter) can be further scaled down or
@@ -2201,10 +2096,24 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() {
}
stream_ = call_->CreateVideoSendStream(std::move(config),
parameters_.encoder_config.Copy());
- stream_->SetSource(this);
parameters_.encoder_config.encoder_specific_settings = NULL;
+ if (source_) {
+ // TODO(perkj, nisse): Remove |source_| and directly call
+ // |stream_|->SetSource(source) once the video frame types have been
+ // merged and |stream_| internally reconfigure the encoder on frame
+ // resolution change.
+ // Do not adapt resolution for screen content as this will likely result in
+ // blurry and unreadable text.
+ stream_->SetSource(
+ this, enable_cpu_overuse_detection_ &&
+ !parameters_.options.is_screencast.value_or(false)
+ ? webrtc::VideoSendStream::DegradationPreference::kBalanced
+ : webrtc::VideoSendStream::DegradationPreference::
+ kMaintainResolution);
+ }
+
// Call stream_->Start() if necessary conditions are met.
UpdateSendState();
}
« no previous file with comments | « webrtc/media/engine/webrtcvideoengine2.h ('k') | webrtc/media/engine/webrtcvideoengine2_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698