| 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();
|
| }
|
|
|