Index: webrtc/media/engine/webrtcvideoengine2.cc |
diff --git a/webrtc/media/engine/webrtcvideoengine2.cc b/webrtc/media/engine/webrtcvideoengine2.cc |
index 0dd8938dc3451758fb0441cb4df457baa6832abe..7e754a789fea5cd4aa3f0f3ea3e35a1ee4fc68e2 100644 |
--- a/webrtc/media/engine/webrtcvideoengine2.cc |
+++ b/webrtc/media/engine/webrtcvideoengine2.cc |
@@ -14,6 +14,7 @@ |
#include <set> |
#include <string> |
+#include "webrtc/base/asyncinvoker.h" |
#include "webrtc/base/buffer.h" |
#include "webrtc/base/logging.h" |
#include "webrtc/base/stringutils.h" |
@@ -314,6 +315,7 @@ static int GetMaxDefaultVideoBitrateKbps(int width, int height) { |
return 2500; |
} |
} |
+ |
} // namespace |
// Constants defined in webrtc/media/engine/constants.h |
@@ -332,6 +334,8 @@ static const int kDefaultQpMax = 56; |
static const int kDefaultRtcpReceiverReportSsrc = 1; |
+static const int kMaxCpuDowngrades = 2; // Downgrade at most 2 times for CPU. |
+ |
std::vector<VideoCodec> DefaultVideoCodecList() { |
std::vector<VideoCodec> codecs; |
codecs.push_back(MakeVideoCodecWithDefaultFeedbackParams(kDefaultVp8PlType, |
@@ -994,13 +998,10 @@ bool WebRtcVideoChannel2::AddSendStream(const StreamParams& sp) { |
send_ssrcs_.insert(used_ssrc); |
webrtc::VideoSendStream::Config config(this); |
- config.overuse_callback = this; |
- |
WebRtcVideoSendStream* stream = new WebRtcVideoSendStream( |
call_, sp, config, external_encoder_factory_, options_, |
- bitrate_config_.max_bitrate_bps, send_codec_, send_rtp_extensions_, |
- send_params_); |
- |
+ signal_cpu_adaptation_, bitrate_config_.max_bitrate_bps, send_codec_, |
+ send_rtp_extensions_, send_params_); |
uint32_t ssrc = sp.first_ssrc(); |
RTC_DCHECK(ssrc != 0); |
send_streams_[ssrc] = stream; |
@@ -1398,26 +1399,6 @@ void WebRtcVideoChannel2::SetInterface(NetworkInterface* iface) { |
kVideoRtpBufferSize); |
} |
-void WebRtcVideoChannel2::OnLoadUpdate(Load load) { |
- // OnLoadUpdate can not take any locks that are held while creating streams |
- // etc. Doing so establishes lock-order inversions between the webrtc process |
- // thread on stream creation and locks such as stream_crit_ while calling out. |
- rtc::CritScope stream_lock(&capturer_crit_); |
- if (!signal_cpu_adaptation_) |
- return; |
- // Do not adapt resolution for screen content as this will likely result in |
- // blurry and unreadable text. |
- for (auto& kv : capturers_) { |
- if (kv.second != nullptr |
- && !kv.second->IsScreencast() |
- && kv.second->video_adapter() != nullptr) { |
- kv.second->video_adapter()->OnCpuResolutionRequest( |
- load == kOveruse ? CoordinatedVideoAdapter::DOWNGRADE |
- : CoordinatedVideoAdapter::UPGRADE); |
- } |
- } |
-} |
- |
bool WebRtcVideoChannel2::SendRtp(const uint8_t* data, |
size_t len, |
const webrtc::PacketOptions& options) { |
@@ -1476,12 +1457,56 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder::AllocatedEncoder( |
} |
} |
+class WebRtcVideoChannel2::WebRtcVideoSendStream::LoadObserverProxy { |
+ public: |
+ explicit LoadObserverProxy(webrtc::LoadObserver* observer) { |
+ helper_ = new rtc::RefCountedObject<Helper>(observer); |
+ } |
+ ~LoadObserverProxy() { helper_->Detach(); } |
+ |
+ webrtc::LoadObserver* proxy() { return helper_; } |
+ |
+ private: |
+ class Helper : public webrtc::LoadObserver, public rtc::RefCountInterface { |
+ public: |
+ explicit Helper(webrtc::LoadObserver* observer) |
+ : thread_(rtc::Thread::Current()), observer_(observer) {} |
+ void Detach() { |
+ RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
+ observer_ = nullptr; |
+ } |
+ void OnLoadUpdate(webrtc::LoadObserver::Load load) override { |
+ if (rtc::Thread::Current() == thread_) { |
+ observer_->OnLoadUpdate(load); |
+ return; |
+ } |
+ invoker_.AsyncInvoke<void>( |
+ thread_, rtc::Bind(&Helper::OnLoadUpdateOnCorrectThread, this, load)); |
+ } |
+ void OnLoadUpdateOnCorrectThread(webrtc::LoadObserver::Load load) { |
+ RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
+ if (observer_) { |
+ observer_->OnLoadUpdate(load); |
+ } |
+ } |
+ |
+ private: |
+ rtc::ThreadChecker thread_checker_; |
+ rtc::AsyncInvoker invoker_; |
+ rtc::Thread* thread_; |
+ webrtc::LoadObserver* observer_; |
+ }; |
+ |
+ rtc::scoped_refptr<Helper> helper_; |
+}; |
+ |
pthatcher1
2016/02/17 23:05:56
Can you explain why this proxy is necessary?
perkj_webrtc
2016/02/18 13:22:46
OnLoad is called on a media engine thread. Not the
pthatcher1
2016/02/19 06:08:39
It seems like a lot of complexity to add.
And I t
perkj_webrtc
2016/02/19 14:57:52
I agreee with OnFrame as said before.
I don't s
|
WebRtcVideoChannel2::WebRtcVideoSendStream::WebRtcVideoSendStream( |
webrtc::Call* call, |
const StreamParams& sp, |
const webrtc::VideoSendStream::Config& config, |
WebRtcVideoEncoderFactory* external_encoder_factory, |
const VideoOptions& options, |
+ bool enable_cpu_overuse_detection, |
int max_bitrate_bps, |
const rtc::Optional<VideoCodecSettings>& codec_settings, |
const std::vector<webrtc::RtpExtension>& rtp_extensions, |
@@ -1491,6 +1516,7 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::WebRtcVideoSendStream( |
: ssrcs_(sp.ssrcs), |
ssrc_groups_(sp.ssrc_groups), |
call_(call), |
+ load_proxy_(new LoadObserverProxy(this)), |
external_encoder_factory_(external_encoder_factory), |
stream_(NULL), |
parameters_(config, options, max_bitrate_bps, codec_settings), |
@@ -1512,6 +1538,8 @@ 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 ? load_proxy_->proxy() : nullptr; |
if (codec_settings) { |
SetCodecAndOptions(*codec_settings, parameters_.options); |
@@ -1635,9 +1663,6 @@ bool WebRtcVideoChannel2::WebRtcVideoSendStream::DisconnectCapturer() { |
if (capturer_ == NULL) |
return false; |
- if (capturer_->video_adapter() != nullptr) |
- old_adapt_changes_ += capturer_->video_adapter()->adaptation_changes(); |
- |
capturer = capturer_; |
capturer_ = NULL; |
} |
@@ -1929,6 +1954,30 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::Stop() { |
sending_ = false; |
} |
+void WebRtcVideoChannel2::WebRtcVideoSendStream::OnLoadUpdate(Load load) { |
+ RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
+ LOG(LS_INFO) << "OnLoadUpdate " << load; |
+ rtc::CritScope cs(&lock_); |
+ if (!capturer_) { |
+ return; |
+ } |
+ |
+ if (load == kOveruse) { |
+ if (cpu_downgrade_count_ < kMaxCpuDowngrades) { |
+ cpu_downgrade_count_++; |
+ sink_wants_.max_number_of_pixels = |
+ (last_dimensions_.height * last_dimensions_.width) / 2; |
+ } |
+ } else { |
+ if (cpu_downgrade_count_ > 0) { |
+ cpu_downgrade_count_--; |
+ sink_wants_.max_number_of_pixels = |
+ (last_dimensions_.height * last_dimensions_.width) * 2; |
+ } |
pthatcher1
2016/02/17 23:05:56
This doesn't seem to work right for situations whe
perkj_webrtc
2016/02/18 13:22:46
Currently - CPU adaptation is not done for screen
perkj_webrtc
2016/02/18 14:30:54
So back to your example- pbos convinced me of your
|
+ } |
+ capturer_->AddOrUpdateSink(this, sink_wants_); |
+} |
+ |
VideoSenderInfo |
WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo() { |
VideoSenderInfo info; |
@@ -1967,10 +2016,6 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo() { |
info.input_frame_width = last_captured_frame_format.width; |
info.input_frame_height = last_captured_frame_format.height; |
} |
- if (capturer_->video_adapter() != nullptr) { |
- info.adapt_changes += capturer_->video_adapter()->adaptation_changes(); |
- info.adapt_reason = capturer_->video_adapter()->adapt_reason(); |
- } |
} |
} |