From 9a4410e9934578e84cc129b978a29e151d957994 Mon Sep 17 00:00:00 2001 From: "pbos@webrtc.org" Date: Thu, 26 Feb 2015 10:03:39 +0000 Subject: [PATCH] Implement adaptation stats in WebRtcVideoEngine2. BUG=1788 R=asapersson@webrtc.org Review URL: https://webrtc-codereview.appspot.com/42489004 Cr-Commit-Position: refs/heads/master@{#8510} git-svn-id: http://webrtc.googlecode.com/svn/trunk@8510 4adac7df-926f-26a2-2b94-8c16560cd09d --- talk/media/webrtc/webrtcvideoengine2.cc | 39 ++++++---- talk/media/webrtc/webrtcvideoengine2.h | 1 + .../webrtc/webrtcvideoengine2_unittest.cc | 75 +++++++++++++++++++ 3 files changed, 101 insertions(+), 14 deletions(-) diff --git a/talk/media/webrtc/webrtcvideoengine2.cc b/talk/media/webrtc/webrtcvideoengine2.cc index f2643c38b..baa091178 100644 --- a/talk/media/webrtc/webrtcvideoengine2.cc +++ b/talk/media/webrtc/webrtcvideoengine2.cc @@ -1330,7 +1330,8 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::WebRtcVideoSendStream( allocated_encoder_(NULL, webrtc::kVideoCodecUnknown, false), capturer_(NULL), sending_(false), - muted_(false) { + muted_(false), + old_adapt_changes_(0) { parameters_.config.rtp.max_packet_size = kVideoMtu; sp.GetPrimarySsrcs(¶meters_.config.rtp.ssrcs); @@ -1492,9 +1493,12 @@ bool WebRtcVideoChannel2::WebRtcVideoSendStream::DisconnectCapturer() { cricket::VideoCapturer* capturer; { rtc::CritScope cs(&lock_); - if (capturer_ == NULL) { + if (capturer_ == NULL) return false; - } + + if (capturer_->video_adapter() != nullptr) + old_adapt_changes_ += capturer_->video_adapter()->adaptation_changes(); + capturer = capturer_; capturer_ = NULL; } @@ -1750,13 +1754,22 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo() { stats = stream_->GetStats(); - if (capturer_ != NULL && !capturer_->IsMuted()) { - VideoFormat last_captured_frame_format; - capturer_->GetStats(&info.adapt_frame_drops, &info.effects_frame_drops, - &info.capturer_frame_time, - &last_captured_frame_format); - info.input_frame_width = last_captured_frame_format.width; - info.input_frame_height = last_captured_frame_format.height; + info.adapt_changes = old_adapt_changes_; + info.adapt_reason = CoordinatedVideoAdapter::ADAPTREASON_NONE; + + if (capturer_ != NULL) { + if (!capturer_->IsMuted()) { + VideoFormat last_captured_frame_format; + capturer_->GetStats(&info.adapt_frame_drops, &info.effects_frame_drops, + &info.capturer_frame_time, + &last_captured_frame_format); + 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(); + } } } info.framerate_input = stats.input_frame_rate; @@ -1818,12 +1831,10 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::OnCpuResolutionRequest( rtc::CritScope cs(&lock_); bool adapt_cpu; parameters_.options.cpu_overuse_detection.Get(&adapt_cpu); - if (!adapt_cpu) { + if (!adapt_cpu) return; - } - if (capturer_ == NULL || capturer_->video_adapter() == NULL) { + if (capturer_ == NULL || capturer_->video_adapter() == NULL) return; - } capturer_->video_adapter()->OnCpuResolutionRequest(adapt_request); } diff --git a/talk/media/webrtc/webrtcvideoengine2.h b/talk/media/webrtc/webrtcvideoengine2.h index 251093c0b..98fa8e657 100644 --- a/talk/media/webrtc/webrtcvideoengine2.h +++ b/talk/media/webrtc/webrtcvideoengine2.h @@ -379,6 +379,7 @@ class WebRtcVideoChannel2 : public rtc::MessageHandler, bool sending_ GUARDED_BY(lock_); bool muted_ GUARDED_BY(lock_); VideoFormat format_ GUARDED_BY(lock_); + int old_adapt_changes_ GUARDED_BY(lock_); rtc::CriticalSection frame_lock_; webrtc::I420VideoFrame video_frame_ GUARDED_BY(frame_lock_); diff --git a/talk/media/webrtc/webrtcvideoengine2_unittest.cc b/talk/media/webrtc/webrtcvideoengine2_unittest.cc index b4f58e22e..3fa220451 100644 --- a/talk/media/webrtc/webrtcvideoengine2_unittest.cc +++ b/talk/media/webrtc/webrtcvideoengine2_unittest.cc @@ -2056,6 +2056,81 @@ TEST_F(WebRtcVideoChannel2Test, GetStatsReportsUpperResolution) { EXPECT_EQ(90, info.senders[0].send_frame_height); } +TEST_F(WebRtcVideoChannel2Test, GetStatsTracksAdaptationStats) { + AddSendStream(cricket::CreateSimStreamParams("cname", MAKE_VECTOR(kSsrcs3))); + + // Capture format VGA. + cricket::FakeVideoCapturer video_capturer_vga; + const std::vector* formats = + video_capturer_vga.GetSupportedFormats(); + cricket::VideoFormat capture_format_vga = (*formats)[1]; + EXPECT_EQ(cricket::CS_RUNNING, video_capturer_vga.Start(capture_format_vga)); + EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], &video_capturer_vga)); + EXPECT_TRUE(video_capturer_vga.CaptureFrame()); + + cricket::VideoCodec send_codec(100, "VP8", 640, 480, 30, 0); + std::vector codecs; + codecs.push_back(send_codec); + EXPECT_TRUE(channel_->SetSendCodecs(codecs)); + EXPECT_TRUE(channel_->SetSend(true)); + + // Verify that the CpuOveruseObserver is registered and trigger downgrade. + cricket::VideoOptions options; + options.cpu_overuse_detection.Set(true); + EXPECT_TRUE(channel_->SetOptions(options)); + // Trigger overuse. + webrtc::LoadObserver* overuse_callback = + fake_call_->GetConfig().overuse_callback; + overuse_callback->OnLoadUpdate(webrtc::LoadObserver::kOveruse); + + // Capture format VGA -> adapt (OnCpuResolutionRequest downgrade) -> VGA/2. + EXPECT_TRUE(video_capturer_vga.CaptureFrame()); + cricket::VideoMediaInfo info; + EXPECT_TRUE(channel_->GetStats(cricket::StatsOptions(), &info)); + ASSERT_EQ(1U, info.senders.size()); + EXPECT_EQ(1, info.senders[0].adapt_changes); + EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU, + info.senders[0].adapt_reason); + + // Trigger upgrade and verify that we adapt back up to VGA. + overuse_callback->OnLoadUpdate(webrtc::LoadObserver::kUnderuse); + EXPECT_TRUE(video_capturer_vga.CaptureFrame()); + info.Clear(); + EXPECT_TRUE(channel_->GetStats(cricket::StatsOptions(), &info)); + ASSERT_EQ(1U, info.senders.size()); + EXPECT_EQ(2, info.senders[0].adapt_changes); + EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_NONE, + info.senders[0].adapt_reason); + + // No capturer (no adapter). Adapt changes from old adapter should be kept. + EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], NULL)); + info.Clear(); + EXPECT_TRUE(channel_->GetStats(cricket::StatsOptions(), &info)); + ASSERT_EQ(1U, info.senders.size()); + EXPECT_EQ(2, info.senders[0].adapt_changes); + EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_NONE, + info.senders[0].adapt_reason); + + // Set new capturer, capture format HD. + cricket::FakeVideoCapturer video_capturer_hd; + cricket::VideoFormat capture_format_hd = (*formats)[0]; + EXPECT_EQ(cricket::CS_RUNNING, video_capturer_hd.Start(capture_format_hd)); + EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], &video_capturer_hd)); + EXPECT_TRUE(video_capturer_hd.CaptureFrame()); + + // Trigger overuse, HD -> adapt (OnCpuResolutionRequest downgrade) -> HD/2. + overuse_callback->OnLoadUpdate(webrtc::LoadObserver::kOveruse); + EXPECT_TRUE(video_capturer_hd.CaptureFrame()); + info.Clear(); + EXPECT_TRUE(channel_->GetStats(cricket::StatsOptions(), &info)); + ASSERT_EQ(1U, info.senders.size()); + EXPECT_EQ(3, info.senders[0].adapt_changes); + EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU, + info.senders[0].adapt_reason); + + EXPECT_TRUE(channel_->SetCapturer(kSsrcs3[0], NULL)); +} + TEST_F(WebRtcVideoChannel2Test, GetStatsTranslatesSendRtcpPacketTypesCorrectly) { FakeVideoSendStream* stream = AddSendStream();