From 085856cd35c3ec7d5b73d6788465868bbd99ae26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Spr=C3=A5ng?= Date: Wed, 22 Jul 2015 17:17:58 +0200 Subject: [PATCH] Extend full stack tests with more stats BUG= R=pbos@webrtc.org Review URL: https://codereview.webrtc.org/1216613002 . Cr-Commit-Position: refs/heads/master@{#9612} --- webrtc/video/full_stack.cc | 85 ++++++++++++++++++++++++++++++++------ 1 file changed, 73 insertions(+), 12 deletions(-) diff --git a/webrtc/video/full_stack.cc b/webrtc/video/full_stack.cc index ad1b5c6356..a03344e635 100644 --- a/webrtc/video/full_stack.cc +++ b/webrtc/video/full_stack.cc @@ -18,6 +18,7 @@ #include "webrtc/base/thread_annotations.h" #include "webrtc/call.h" #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" +#include "webrtc/frame_callback.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" #include "webrtc/system_wrappers/interface/clock.h" #include "webrtc/system_wrappers/interface/cpu_info.h" @@ -37,6 +38,7 @@ namespace webrtc { static const int kFullStackTestDurationSecs = 60; +static const int kSendStatsPollingIntervalMs = 1000; struct FullStackTestParams { const char* test_label; @@ -63,7 +65,8 @@ class FullStackTest : public test::CallTest { class VideoAnalyzer : public PacketReceiver, public newapi::Transport, public VideoRenderer, - public VideoCaptureInput { + public VideoCaptureInput, + public EncodedFrameObserver { public: VideoAnalyzer(VideoCaptureInput* input, Transport* transport, @@ -74,6 +77,7 @@ class VideoAnalyzer : public PacketReceiver, : input_(input), transport_(transport), receiver_(nullptr), + send_stream_(nullptr), test_label_(test_label), frames_to_process_(duration_frames), frames_recorded_(0), @@ -110,6 +114,10 @@ class VideoAnalyzer : public PacketReceiver, EXPECT_TRUE(thread->Start()); comparison_thread_pool_.push_back(thread.release()); } + + stats_polling_thread_ = + ThreadWrapper::CreateThread(&PollStatsThread, this, "StatsPoller"); + EXPECT_TRUE(stats_polling_thread_->Start()); } ~VideoAnalyzer() { @@ -173,6 +181,12 @@ class VideoAnalyzer : public PacketReceiver, return transport_->SendRtcp(packet, length); } + void EncodedFrameCallback(const EncodedFrame& frame) override { + rtc::CritScope lock(&comparison_lock_); + if (frames_recorded_ < frames_to_process_) + encoded_frame_size_.AddSample(frame.length_); + } + void RenderFrame(const VideoFrame& video_frame, int time_to_render_ms) override { int64_t render_time_ms = @@ -222,11 +236,18 @@ class VideoAnalyzer : public PacketReceiver, << "Analyzer stalled while waiting for test to finish."; last_frames_processed = frames_processed; } + + // Signal stats polling thread if that is still waiting and stop it now, + // since it uses the send_stream_ reference that might be reclaimed after + // returning from this method. + done_->Set(); + EXPECT_TRUE(stats_polling_thread_->Stop()); } VideoCaptureInput* input_; Transport* transport_; PacketReceiver* receiver_; + VideoSendStream* send_stream_; private: struct FrameComparison { @@ -265,15 +286,39 @@ class VideoAnalyzer : public PacketReceiver, recv_times_.erase(reference.timestamp()); rtc::CritScope crit(&comparison_lock_); - comparisons_.push_back(FrameComparison(reference, - render, - dropped, - send_time_ms, - recv_time_ms, + comparisons_.push_back(FrameComparison(reference, render, dropped, + send_time_ms, recv_time_ms, render_time_ms)); comparison_available_event_->Set(); } + static bool PollStatsThread(void* obj) { + return static_cast(obj)->PollStats(); + } + + bool PollStats() { + switch (done_->Wait(kSendStatsPollingIntervalMs)) { + case kEventSignaled: + case kEventError: + done_->Set(); // Make sure main thread is also signaled. + return false; + case kEventTimeout: + break; + default: + RTC_NOTREACHED(); + } + + VideoSendStream::Stats stats = send_stream_->GetStats(); + + rtc::CritScope crit(&comparison_lock_); + encode_frame_rate_.AddSample(stats.encode_frame_rate); + encode_time_ms.AddSample(stats.avg_encode_time_ms); + encode_usage_percent.AddSample(stats.encode_usage_percent); + media_bitrate_bps.AddSample(stats.media_bitrate_bps); + + return true; + } + static bool FrameComparisonThread(void* obj) { return static_cast(obj)->CompareFrames(); } @@ -358,6 +403,12 @@ class VideoAnalyzer : public PacketReceiver, PrintResult("receiver_time", receiver_time_, " ms"); PrintResult("total_delay_incl_network", end_to_end_, " ms"); PrintResult("time_between_rendered_frames", rendered_delta_, " ms"); + PrintResult("encoded_frame_size", encoded_frame_size_, " bytes"); + PrintResult("encode_frame_rate", encode_frame_rate_, " fps"); + PrintResult("encode_time", encode_time_ms, " ms"); + PrintResult("encode_usage_percent", encode_usage_percent, " percent"); + PrintResult("media_bitrate", media_bitrate_bps, " bps"); + EXPECT_GT(psnr_.Mean(), avg_psnr_threshold_); EXPECT_GT(ssim_.Mean(), avg_ssim_threshold_); } @@ -397,12 +448,18 @@ class VideoAnalyzer : public PacketReceiver, } const char* const test_label_; - test::Statistics sender_time_; - test::Statistics receiver_time_; - test::Statistics psnr_; - test::Statistics ssim_; - test::Statistics end_to_end_; - test::Statistics rendered_delta_; + test::Statistics sender_time_ GUARDED_BY(comparison_lock_); + test::Statistics receiver_time_ GUARDED_BY(comparison_lock_); + test::Statistics psnr_ GUARDED_BY(comparison_lock_); + test::Statistics ssim_ GUARDED_BY(comparison_lock_); + test::Statistics end_to_end_ GUARDED_BY(comparison_lock_); + test::Statistics rendered_delta_ GUARDED_BY(comparison_lock_); + test::Statistics encoded_frame_size_ GUARDED_BY(comparison_lock_); + test::Statistics encode_frame_rate_ GUARDED_BY(comparison_lock_); + test::Statistics encode_time_ms GUARDED_BY(comparison_lock_); + test::Statistics encode_usage_percent GUARDED_BY(comparison_lock_); + test::Statistics media_bitrate_bps GUARDED_BY(comparison_lock_); + const int frames_to_process_; int frames_recorded_; int frames_processed_; @@ -421,6 +478,7 @@ class VideoAnalyzer : public PacketReceiver, rtc::CriticalSection comparison_lock_; std::vector comparison_thread_pool_; + rtc::scoped_ptr stats_polling_thread_; const rtc::scoped_ptr comparison_available_event_; std::deque comparisons_ GUARDED_BY(comparison_lock_); const rtc::scoped_ptr done_; @@ -478,8 +536,11 @@ void FullStackTest::RunTest(const FullStackTestParams& params) { receive_configs_[0].rtp.rtx[kSendRtxPayloadType].payload_type = kSendRtxPayloadType; + for (auto& config : receive_configs_) + config.pre_decode_callback = &analyzer; CreateStreams(); analyzer.input_ = send_stream_->Input(); + analyzer.send_stream_ = send_stream_; if (params.screenshare) { std::vector slides;