| Index: webrtc/video/full_stack.cc
|
| diff --git a/webrtc/video/full_stack.cc b/webrtc/video/full_stack.cc
|
| index ad1b5c6356557e3e4152b1dbd0f3c8c0f31ede2c..a03344e635516444ac2aaf40b09fb27f1bf58a6a 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<VideoAnalyzer*>(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<VideoAnalyzer*>(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<ThreadWrapper*> comparison_thread_pool_;
|
| + rtc::scoped_ptr<ThreadWrapper> stats_polling_thread_;
|
| const rtc::scoped_ptr<EventWrapper> comparison_available_event_;
|
| std::deque<FrameComparison> comparisons_ GUARDED_BY(comparison_lock_);
|
| const rtc::scoped_ptr<EventWrapper> 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<std::string> slides;
|
|
|