| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 #include <stdio.h> | 10 #include <stdio.h> |
| 11 | 11 |
| 12 #include <algorithm> | |
| 13 #include <deque> | 12 #include <deque> |
| 14 #include <map> | 13 #include <map> |
| 15 #include <vector> | |
| 16 | 14 |
| 17 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
| 18 | 16 |
| 19 #include "webrtc/base/checks.h" | |
| 20 #include "webrtc/base/format_macros.h" | 17 #include "webrtc/base/format_macros.h" |
| 21 #include "webrtc/base/scoped_ptr.h" | 18 #include "webrtc/base/scoped_ptr.h" |
| 19 #include "webrtc/base/thread_annotations.h" |
| 22 #include "webrtc/call.h" | 20 #include "webrtc/call.h" |
| 23 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" | 21 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" |
| 22 #include "webrtc/frame_callback.h" |
| 24 #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" | 23 #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" |
| 24 #include "webrtc/system_wrappers/interface/clock.h" |
| 25 #include "webrtc/system_wrappers/interface/cpu_info.h" | 25 #include "webrtc/system_wrappers/interface/cpu_info.h" |
| 26 #include "webrtc/test/layer_filtering_transport.h" | 26 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" |
| 27 #include "webrtc/test/run_loop.h" | 27 #include "webrtc/system_wrappers/interface/event_wrapper.h" |
| 28 #include "webrtc/system_wrappers/interface/sleep.h" |
| 29 #include "webrtc/test/call_test.h" |
| 30 #include "webrtc/test/direct_transport.h" |
| 31 #include "webrtc/test/encoder_settings.h" |
| 32 #include "webrtc/test/fake_encoder.h" |
| 33 #include "webrtc/test/frame_generator.h" |
| 34 #include "webrtc/test/frame_generator_capturer.h" |
| 28 #include "webrtc/test/statistics.h" | 35 #include "webrtc/test/statistics.h" |
| 29 #include "webrtc/test/testsupport/fileutils.h" | 36 #include "webrtc/test/testsupport/fileutils.h" |
| 30 #include "webrtc/test/video_renderer.h" | 37 #include "webrtc/typedefs.h" |
| 31 #include "webrtc/video/video_quality_test.h" | |
| 32 | 38 |
| 33 namespace webrtc { | 39 namespace webrtc { |
| 34 | 40 |
| 35 static const int kTransportSeqExtensionId = | 41 enum class ContentMode { |
| 36 VideoQualityTest::kAbsSendTimeExtensionId + 1; | 42 kRealTimeVideo, |
| 43 kScreensharingStaticImage, |
| 44 kScreensharingScrollingImage, |
| 45 }; |
| 46 |
| 47 struct FullStackTestBeforeParams { |
| 48 const char* test_label; |
| 49 struct { |
| 50 const char* name; |
| 51 size_t width, height; |
| 52 int fps; |
| 53 } clip; |
| 54 ContentMode mode; |
| 55 int min_bitrate_bps; |
| 56 int target_bitrate_bps; |
| 57 int max_bitrate_bps; |
| 58 double avg_psnr_threshold; |
| 59 double avg_ssim_threshold; |
| 60 int test_durations_secs; |
| 61 std::string codec; |
| 62 FakeNetworkPipe::Config link; |
| 63 std::string graph_data_output_filename; |
| 64 }; |
| 65 |
| 66 class FullStackTestBefore : public test::CallTest { |
| 67 protected: |
| 68 void RunTest(const FullStackTestBeforeParams& params); |
| 69 }; |
| 70 |
| 71 static const int kFullStackTestBeforeDurationSecs = 60; |
| 37 static const int kSendStatsPollingIntervalMs = 1000; | 72 static const int kSendStatsPollingIntervalMs = 1000; |
| 38 static const int kPayloadTypeVP8 = 123; | |
| 39 static const int kPayloadTypeVP9 = 124; | |
| 40 | 73 |
| 41 class VideoAnalyzer : public PacketReceiver, | 74 class VideoAnalyzerBefore : public PacketReceiver, |
| 42 public Transport, | 75 public Transport, |
| 43 public VideoRenderer, | 76 public VideoRenderer, |
| 44 public VideoCaptureInput, | 77 public VideoCaptureInput, |
| 45 public EncodedFrameObserver { | 78 public EncodedFrameObserver { |
| 46 public: | 79 public: |
| 47 VideoAnalyzer(VideoCaptureInput* input, | 80 VideoAnalyzerBefore(VideoCaptureInput* input, |
| 48 Transport* transport, | 81 Transport* transport, |
| 49 const std::string& test_label, | 82 const char* test_label, |
| 50 double avg_psnr_threshold, | 83 double avg_psnr_threshold, |
| 51 double avg_ssim_threshold, | 84 double avg_ssim_threshold, |
| 52 int duration_frames, | 85 int duration_frames, |
| 53 FILE* graph_data_output_file) | 86 const std::string& graph_data_output_filename) |
| 54 : input_(input), | 87 : input_(input), |
| 55 transport_(transport), | 88 transport_(transport), |
| 56 receiver_(nullptr), | 89 receiver_(nullptr), |
| 57 send_stream_(nullptr), | 90 send_stream_(nullptr), |
| 58 test_label_(test_label), | 91 test_label_(test_label), |
| 59 graph_data_output_file_(graph_data_output_file), | 92 graph_data_output_filename_(graph_data_output_filename), |
| 60 frames_to_process_(duration_frames), | 93 frames_to_process_(duration_frames), |
| 61 frames_recorded_(0), | 94 frames_recorded_(0), |
| 62 frames_processed_(0), | 95 frames_processed_(0), |
| 63 dropped_frames_(0), | 96 dropped_frames_(0), |
| 64 last_render_time_(0), | 97 last_render_time_(0), |
| 65 rtp_timestamp_delta_(0), | 98 rtp_timestamp_delta_(0), |
| 66 avg_psnr_threshold_(avg_psnr_threshold), | 99 avg_psnr_threshold_(avg_psnr_threshold), |
| 67 avg_ssim_threshold_(avg_ssim_threshold), | 100 avg_ssim_threshold_(avg_ssim_threshold), |
| 68 comparison_available_event_(EventWrapper::Create()), | 101 comparison_available_event_(EventWrapper::Create()), |
| 69 done_(EventWrapper::Create()) { | 102 done_(EventWrapper::Create()) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 91 ThreadWrapper::CreateThread(&FrameComparisonThread, this, "Analyzer"); | 124 ThreadWrapper::CreateThread(&FrameComparisonThread, this, "Analyzer"); |
| 92 EXPECT_TRUE(thread->Start()); | 125 EXPECT_TRUE(thread->Start()); |
| 93 comparison_thread_pool_.push_back(thread.release()); | 126 comparison_thread_pool_.push_back(thread.release()); |
| 94 } | 127 } |
| 95 | 128 |
| 96 stats_polling_thread_ = | 129 stats_polling_thread_ = |
| 97 ThreadWrapper::CreateThread(&PollStatsThread, this, "StatsPoller"); | 130 ThreadWrapper::CreateThread(&PollStatsThread, this, "StatsPoller"); |
| 98 EXPECT_TRUE(stats_polling_thread_->Start()); | 131 EXPECT_TRUE(stats_polling_thread_->Start()); |
| 99 } | 132 } |
| 100 | 133 |
| 101 ~VideoAnalyzer() { | 134 ~VideoAnalyzerBefore() { |
| 102 for (ThreadWrapper* thread : comparison_thread_pool_) { | 135 for (ThreadWrapper* thread : comparison_thread_pool_) { |
| 103 EXPECT_TRUE(thread->Stop()); | 136 EXPECT_TRUE(thread->Stop()); |
| 104 delete thread; | 137 delete thread; |
| 105 } | 138 } |
| 106 } | 139 } |
| 107 | 140 |
| 108 virtual void SetReceiver(PacketReceiver* receiver) { receiver_ = receiver; } | 141 virtual void SetReceiver(PacketReceiver* receiver) { receiver_ = receiver; } |
| 109 | 142 |
| 110 DeliveryStatus DeliverPacket(MediaType media_type, | 143 DeliveryStatus DeliverPacket(MediaType media_type, |
| 111 const uint8_t* packet, | 144 const uint8_t* packet, |
| (...skipping 29 matching lines...) Expand all Loading... |
| 141 bool SendRtp(const uint8_t* packet, | 174 bool SendRtp(const uint8_t* packet, |
| 142 size_t length, | 175 size_t length, |
| 143 const PacketOptions& options) override { | 176 const PacketOptions& options) override { |
| 144 rtc::scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create()); | 177 rtc::scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create()); |
| 145 RTPHeader header; | 178 RTPHeader header; |
| 146 parser->Parse(packet, length, &header); | 179 parser->Parse(packet, length, &header); |
| 147 | 180 |
| 148 { | 181 { |
| 149 rtc::CritScope lock(&crit_); | 182 rtc::CritScope lock(&crit_); |
| 150 if (rtp_timestamp_delta_ == 0) { | 183 if (rtp_timestamp_delta_ == 0) { |
| 151 rtp_timestamp_delta_ = header.timestamp - first_send_frame_.timestamp(); | 184 rtp_timestamp_delta_ = |
| 185 header.timestamp - first_send_frame_.timestamp(); |
| 152 first_send_frame_.Reset(); | 186 first_send_frame_.Reset(); |
| 153 } | 187 } |
| 154 uint32_t timestamp = header.timestamp - rtp_timestamp_delta_; | 188 uint32_t timestamp = header.timestamp - rtp_timestamp_delta_; |
| 155 send_times_[timestamp] = | 189 send_times_[timestamp] = |
| 156 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds(); | 190 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds(); |
| 157 encoded_frame_sizes_[timestamp] += | 191 encoded_frame_sizes_[timestamp] += |
| 158 length - (header.headerLength + header.paddingLength); | 192 length - (header.headerLength + header.paddingLength); |
| 159 } | 193 } |
| 160 | 194 |
| 161 return transport_->SendRtp(packet, length, options); | 195 return transport_->SendRtp(packet, length, options); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 bool IsTextureSupported() const override { return false; } | 233 bool IsTextureSupported() const override { return false; } |
| 200 | 234 |
| 201 void Wait() { | 235 void Wait() { |
| 202 // Frame comparisons can be very expensive. Wait for test to be done, but | 236 // Frame comparisons can be very expensive. Wait for test to be done, but |
| 203 // at time-out check if frames_processed is going up. If so, give it more | 237 // at time-out check if frames_processed is going up. If so, give it more |
| 204 // time, otherwise fail. Hopefully this will reduce test flakiness. | 238 // time, otherwise fail. Hopefully this will reduce test flakiness. |
| 205 | 239 |
| 206 int last_frames_processed = -1; | 240 int last_frames_processed = -1; |
| 207 EventTypeWrapper eventType; | 241 EventTypeWrapper eventType; |
| 208 int iteration = 0; | 242 int iteration = 0; |
| 209 while ((eventType = done_->Wait(VideoQualityTest::kDefaultTimeoutMs)) != | 243 while ((eventType = done_->Wait(FullStackTestBefore::kDefaultTimeoutMs)) != |
| 210 kEventSignaled) { | 244 kEventSignaled) { |
| 211 int frames_processed; | 245 int frames_processed; |
| 212 { | 246 { |
| 213 rtc::CritScope crit(&comparison_lock_); | 247 rtc::CritScope crit(&comparison_lock_); |
| 214 frames_processed = frames_processed_; | 248 frames_processed = frames_processed_; |
| 215 } | 249 } |
| 216 | 250 |
| 217 // Print some output so test infrastructure won't think we've crashed. | 251 // Print some output so test infrastructure won't think we've crashed. |
| 218 const char* kKeepAliveMessages[3] = { | 252 const char* kKeepAliveMessages[3] = { |
| 219 "Uh, I'm-I'm not quite dead, sir.", | 253 "Uh, I'm-I'm not quite dead, sir.", |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 325 render_copy.CopyFrame(render); | 359 render_copy.CopyFrame(render); |
| 326 | 360 |
| 327 rtc::CritScope crit(&comparison_lock_); | 361 rtc::CritScope crit(&comparison_lock_); |
| 328 comparisons_.push_back(FrameComparison(reference_copy, render_copy, dropped, | 362 comparisons_.push_back(FrameComparison(reference_copy, render_copy, dropped, |
| 329 send_time_ms, recv_time_ms, | 363 send_time_ms, recv_time_ms, |
| 330 render_time_ms, encoded_size)); | 364 render_time_ms, encoded_size)); |
| 331 comparison_available_event_->Set(); | 365 comparison_available_event_->Set(); |
| 332 } | 366 } |
| 333 | 367 |
| 334 static bool PollStatsThread(void* obj) { | 368 static bool PollStatsThread(void* obj) { |
| 335 return static_cast<VideoAnalyzer*>(obj)->PollStats(); | 369 return static_cast<VideoAnalyzerBefore*>(obj)->PollStats(); |
| 336 } | 370 } |
| 337 | 371 |
| 338 bool PollStats() { | 372 bool PollStats() { |
| 339 switch (done_->Wait(kSendStatsPollingIntervalMs)) { | 373 switch (done_->Wait(kSendStatsPollingIntervalMs)) { |
| 340 case kEventSignaled: | 374 case kEventSignaled: |
| 341 case kEventError: | 375 case kEventError: |
| 342 done_->Set(); // Make sure main thread is also signaled. | 376 done_->Set(); // Make sure main thread is also signaled. |
| 343 return false; | 377 return false; |
| 344 case kEventTimeout: | 378 case kEventTimeout: |
| 345 break; | 379 break; |
| 346 default: | 380 default: |
| 347 RTC_NOTREACHED(); | 381 RTC_NOTREACHED(); |
| 348 } | 382 } |
| 349 | 383 |
| 350 VideoSendStream::Stats stats = send_stream_->GetStats(); | 384 VideoSendStream::Stats stats = send_stream_->GetStats(); |
| 351 | 385 |
| 352 rtc::CritScope crit(&comparison_lock_); | 386 rtc::CritScope crit(&comparison_lock_); |
| 353 encode_frame_rate_.AddSample(stats.encode_frame_rate); | 387 encode_frame_rate_.AddSample(stats.encode_frame_rate); |
| 354 encode_time_ms.AddSample(stats.avg_encode_time_ms); | 388 encode_time_ms.AddSample(stats.avg_encode_time_ms); |
| 355 encode_usage_percent.AddSample(stats.encode_usage_percent); | 389 encode_usage_percent.AddSample(stats.encode_usage_percent); |
| 356 media_bitrate_bps.AddSample(stats.media_bitrate_bps); | 390 media_bitrate_bps.AddSample(stats.media_bitrate_bps); |
| 357 | 391 |
| 358 return true; | 392 return true; |
| 359 } | 393 } |
| 360 | 394 |
| 361 static bool FrameComparisonThread(void* obj) { | 395 static bool FrameComparisonThread(void* obj) { |
| 362 return static_cast<VideoAnalyzer*>(obj)->CompareFrames(); | 396 return static_cast<VideoAnalyzerBefore*>(obj)->CompareFrames(); |
| 363 } | 397 } |
| 364 | 398 |
| 365 bool CompareFrames() { | 399 bool CompareFrames() { |
| 366 if (AllFramesRecorded()) | 400 if (AllFramesRecorded()) |
| 367 return false; | 401 return false; |
| 368 | 402 |
| 369 VideoFrame reference; | 403 VideoFrame reference; |
| 370 VideoFrame render; | 404 VideoFrame render; |
| 371 FrameComparison comparison; | 405 FrameComparison comparison; |
| 372 | 406 |
| 373 if (!PopComparison(&comparison)) { | 407 if (!PopComparison(&comparison)) { |
| 374 // Wait until new comparison task is available, or test is done. | 408 // Wait until new comparison task is available, or test is done. |
| 375 // If done, wake up remaining threads waiting. | 409 // If done, wake up remaining threads waiting. |
| 376 comparison_available_event_->Wait(1000); | 410 comparison_available_event_->Wait(1000); |
| 377 if (AllFramesRecorded()) { | 411 if (AllFramesRecorded()) { |
| 378 comparison_available_event_->Set(); | 412 comparison_available_event_->Set(); |
| 379 return false; | 413 return false; |
| 380 } | 414 } |
| 381 return true; // Try again. | 415 return true; // Try again. |
| 382 } | 416 } |
| 383 | 417 |
| 384 PerformFrameComparison(comparison); | 418 PerformFrameComparison(comparison); |
| 385 | 419 |
| 386 if (FrameProcessed()) { | 420 if (FrameProcessed()) { |
| 387 PrintResults(); | 421 PrintResults(); |
| 388 if (graph_data_output_file_) | 422 if (!graph_data_output_filename_.empty()) |
| 389 PrintSamplesToFile(); | 423 PrintSamplesToFile(); |
| 390 done_->Set(); | 424 done_->Set(); |
| 391 comparison_available_event_->Set(); | 425 comparison_available_event_->Set(); |
| 392 return false; | 426 return false; |
| 393 } | 427 } |
| 394 | 428 |
| 395 return true; | 429 return true; |
| 396 } | 430 } |
| 397 | 431 |
| 398 bool PopComparison(FrameComparison* comparison) { | 432 bool PopComparison(FrameComparison* comparison) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 ++frames_processed_; | 466 ++frames_processed_; |
| 433 assert(frames_processed_ <= frames_to_process_); | 467 assert(frames_processed_ <= frames_to_process_); |
| 434 return frames_processed_ == frames_to_process_; | 468 return frames_processed_ == frames_to_process_; |
| 435 } | 469 } |
| 436 | 470 |
| 437 void PrintResults() { | 471 void PrintResults() { |
| 438 rtc::CritScope crit(&comparison_lock_); | 472 rtc::CritScope crit(&comparison_lock_); |
| 439 PrintResult("psnr", psnr_, " dB"); | 473 PrintResult("psnr", psnr_, " dB"); |
| 440 PrintResult("ssim", ssim_, ""); | 474 PrintResult("ssim", ssim_, ""); |
| 441 PrintResult("sender_time", sender_time_, " ms"); | 475 PrintResult("sender_time", sender_time_, " ms"); |
| 442 printf("RESULT dropped_frames: %s = %d frames\n", test_label_.c_str(), | 476 printf("RESULT dropped_frames: %s = %d frames\n", test_label_, |
| 443 dropped_frames_); | 477 dropped_frames_); |
| 444 PrintResult("receiver_time", receiver_time_, " ms"); | 478 PrintResult("receiver_time", receiver_time_, " ms"); |
| 445 PrintResult("total_delay_incl_network", end_to_end_, " ms"); | 479 PrintResult("total_delay_incl_network", end_to_end_, " ms"); |
| 446 PrintResult("time_between_rendered_frames", rendered_delta_, " ms"); | 480 PrintResult("time_between_rendered_frames", rendered_delta_, " ms"); |
| 447 PrintResult("encoded_frame_size", encoded_frame_size_, " bytes"); | 481 PrintResult("encoded_frame_size", encoded_frame_size_, " bytes"); |
| 448 PrintResult("encode_frame_rate", encode_frame_rate_, " fps"); | 482 PrintResult("encode_frame_rate", encode_frame_rate_, " fps"); |
| 449 PrintResult("encode_time", encode_time_ms, " ms"); | 483 PrintResult("encode_time", encode_time_ms, " ms"); |
| 450 PrintResult("encode_usage_percent", encode_usage_percent, " percent"); | 484 PrintResult("encode_usage_percent", encode_usage_percent, " percent"); |
| 451 PrintResult("media_bitrate", media_bitrate_bps, " bps"); | 485 PrintResult("media_bitrate", media_bitrate_bps, " bps"); |
| 452 | 486 |
| 453 EXPECT_GT(psnr_.Mean(), avg_psnr_threshold_); | 487 EXPECT_GT(psnr_.Mean(), avg_psnr_threshold_); |
| 454 EXPECT_GT(ssim_.Mean(), avg_ssim_threshold_); | 488 EXPECT_GT(ssim_.Mean(), avg_ssim_threshold_); |
| 455 } | 489 } |
| 456 | 490 |
| 457 void PerformFrameComparison(const FrameComparison& comparison) { | 491 void PerformFrameComparison(const FrameComparison& comparison) { |
| 458 // Perform expensive psnr and ssim calculations while not holding lock. | 492 // Perform expensive psnr and ssim calculations while not holding lock. |
| 459 double psnr = I420PSNR(&comparison.reference, &comparison.render); | 493 double psnr = I420PSNR(&comparison.reference, &comparison.render); |
| 460 double ssim = I420SSIM(&comparison.reference, &comparison.render); | 494 double ssim = I420SSIM(&comparison.reference, &comparison.render); |
| 461 | 495 |
| 462 int64_t input_time_ms = comparison.reference.ntp_time_ms(); | 496 int64_t input_time_ms = comparison.reference.ntp_time_ms(); |
| 463 | 497 |
| 464 rtc::CritScope crit(&comparison_lock_); | 498 rtc::CritScope crit(&comparison_lock_); |
| 465 if (graph_data_output_file_) { | 499 if (!graph_data_output_filename_.empty()) { |
| 466 samples_.push_back( | 500 samples_.push_back(Sample( |
| 467 Sample(comparison.dropped, input_time_ms, comparison.send_time_ms, | 501 comparison.dropped, input_time_ms, comparison.send_time_ms, |
| 468 comparison.recv_time_ms, comparison.encoded_frame_size, psnr, | 502 comparison.recv_time_ms, comparison.encoded_frame_size, psnr, ssim, |
| 469 ssim, comparison.render_time_ms)); | 503 comparison.render_time_ms)); |
| 470 } | 504 } |
| 471 psnr_.AddSample(psnr); | 505 psnr_.AddSample(psnr); |
| 472 ssim_.AddSample(ssim); | 506 ssim_.AddSample(ssim); |
| 473 | 507 |
| 474 if (comparison.dropped) { | 508 if (comparison.dropped) { |
| 475 ++dropped_frames_; | 509 ++dropped_frames_; |
| 476 return; | 510 return; |
| 477 } | 511 } |
| 478 if (last_render_time_ != 0) | 512 if (last_render_time_ != 0) |
| 479 rendered_delta_.AddSample(comparison.render_time_ms - last_render_time_); | 513 rendered_delta_.AddSample(comparison.render_time_ms - last_render_time_); |
| 480 last_render_time_ = comparison.render_time_ms; | 514 last_render_time_ = comparison.render_time_ms; |
| 481 | 515 |
| 482 sender_time_.AddSample(comparison.send_time_ms - input_time_ms); | 516 sender_time_.AddSample(comparison.send_time_ms - input_time_ms); |
| 483 receiver_time_.AddSample(comparison.render_time_ms - | 517 receiver_time_.AddSample(comparison.render_time_ms - |
| 484 comparison.recv_time_ms); | 518 comparison.recv_time_ms); |
| 485 end_to_end_.AddSample(comparison.render_time_ms - input_time_ms); | 519 end_to_end_.AddSample(comparison.render_time_ms - input_time_ms); |
| 486 encoded_frame_size_.AddSample(comparison.encoded_frame_size); | 520 encoded_frame_size_.AddSample(comparison.encoded_frame_size); |
| 487 } | 521 } |
| 488 | 522 |
| 489 void PrintResult(const char* result_type, | 523 void PrintResult(const char* result_type, |
| 490 test::Statistics stats, | 524 test::Statistics stats, |
| 491 const char* unit) { | 525 const char* unit) { |
| 492 printf("RESULT %s: %s = {%f, %f}%s\n", | 526 printf("RESULT %s: %s = {%f, %f}%s\n", |
| 493 result_type, | 527 result_type, |
| 494 test_label_.c_str(), | 528 test_label_, |
| 495 stats.Mean(), | 529 stats.Mean(), |
| 496 stats.StandardDeviation(), | 530 stats.StandardDeviation(), |
| 497 unit); | 531 unit); |
| 498 } | 532 } |
| 499 | 533 |
| 500 void PrintSamplesToFile(void) { | 534 void PrintSamplesToFile(void) { |
| 501 FILE* out = graph_data_output_file_; | 535 FILE* out = fopen(graph_data_output_filename_.c_str(), "w"); |
| 536 RTC_CHECK(out != nullptr) << "Couldn't open file: " |
| 537 << graph_data_output_filename_; |
| 538 |
| 502 rtc::CritScope crit(&comparison_lock_); | 539 rtc::CritScope crit(&comparison_lock_); |
| 503 std::sort(samples_.begin(), samples_.end(), | 540 std::sort(samples_.begin(), samples_.end(), |
| 504 [](const Sample& A, const Sample& B) -> bool { | 541 [](const Sample& A, const Sample& B) |
| 505 return A.input_time_ms < B.input_time_ms; | 542 -> bool { return A.input_time_ms < B.input_time_ms; }); |
| 506 }); | |
| 507 | 543 |
| 508 fprintf(out, "%s\n", test_label_.c_str()); | 544 fprintf(out, "%s\n", test_label_); |
| 509 fprintf(out, "%" PRIuS "\n", samples_.size()); | 545 fprintf(out, "%" PRIuS "\n", samples_.size()); |
| 510 fprintf(out, | 546 fprintf(out, |
| 511 "dropped " | 547 "dropped " |
| 512 "input_time_ms " | 548 "input_time_ms " |
| 513 "send_time_ms " | 549 "send_time_ms " |
| 514 "recv_time_ms " | 550 "recv_time_ms " |
| 515 "encoded_frame_size " | 551 "encoded_frame_size " |
| 516 "psnr " | 552 "psnr " |
| 517 "ssim " | 553 "ssim " |
| 518 "render_time_ms\n"); | 554 "render_time_ms\n"); |
| 519 for (const Sample& sample : samples_) { | 555 for (const Sample& sample : samples_) { |
| 520 fprintf(out, "%lf %lf %lf %lf %lf %lf %lf %lf\n", sample.dropped, | 556 fprintf(out, "%lf %lf %lf %lf %lf %lf %lf %lf\n", sample.dropped, |
| 521 sample.input_time_ms, sample.send_time_ms, sample.recv_time_ms, | 557 sample.input_time_ms, sample.send_time_ms, sample.recv_time_ms, |
| 522 sample.encoded_frame_size, sample.psnr, sample.ssim, | 558 sample.encoded_frame_size, sample.psnr, sample.ssim, |
| 523 sample.render_time_ms); | 559 sample.render_time_ms); |
| 524 } | 560 } |
| 561 fclose(out); |
| 525 } | 562 } |
| 526 | 563 |
| 527 const std::string test_label_; | 564 const char* const test_label_; |
| 528 FILE* const graph_data_output_file_; | 565 std::string graph_data_output_filename_; |
| 529 std::vector<Sample> samples_ GUARDED_BY(comparison_lock_); | 566 std::vector<Sample> samples_ GUARDED_BY(comparison_lock_); |
| 530 test::Statistics sender_time_ GUARDED_BY(comparison_lock_); | 567 test::Statistics sender_time_ GUARDED_BY(comparison_lock_); |
| 531 test::Statistics receiver_time_ GUARDED_BY(comparison_lock_); | 568 test::Statistics receiver_time_ GUARDED_BY(comparison_lock_); |
| 532 test::Statistics psnr_ GUARDED_BY(comparison_lock_); | 569 test::Statistics psnr_ GUARDED_BY(comparison_lock_); |
| 533 test::Statistics ssim_ GUARDED_BY(comparison_lock_); | 570 test::Statistics ssim_ GUARDED_BY(comparison_lock_); |
| 534 test::Statistics end_to_end_ GUARDED_BY(comparison_lock_); | 571 test::Statistics end_to_end_ GUARDED_BY(comparison_lock_); |
| 535 test::Statistics rendered_delta_ GUARDED_BY(comparison_lock_); | 572 test::Statistics rendered_delta_ GUARDED_BY(comparison_lock_); |
| 536 test::Statistics encoded_frame_size_ GUARDED_BY(comparison_lock_); | 573 test::Statistics encoded_frame_size_ GUARDED_BY(comparison_lock_); |
| 537 test::Statistics encode_frame_rate_ GUARDED_BY(comparison_lock_); | 574 test::Statistics encode_frame_rate_ GUARDED_BY(comparison_lock_); |
| 538 test::Statistics encode_time_ms GUARDED_BY(comparison_lock_); | 575 test::Statistics encode_time_ms GUARDED_BY(comparison_lock_); |
| 539 test::Statistics encode_usage_percent GUARDED_BY(comparison_lock_); | 576 test::Statistics encode_usage_percent GUARDED_BY(comparison_lock_); |
| 540 test::Statistics media_bitrate_bps GUARDED_BY(comparison_lock_); | 577 test::Statistics media_bitrate_bps GUARDED_BY(comparison_lock_); |
| 541 | 578 |
| 542 const int frames_to_process_; | 579 const int frames_to_process_; |
| 543 int frames_recorded_; | 580 int frames_recorded_; |
| 544 int frames_processed_; | 581 int frames_processed_; |
| 545 int dropped_frames_; | 582 int dropped_frames_; |
| 546 int64_t last_render_time_; | 583 int64_t last_render_time_; |
| 547 uint32_t rtp_timestamp_delta_; | 584 uint32_t rtp_timestamp_delta_; |
| 548 | 585 |
| 549 rtc::CriticalSection crit_; | 586 rtc::CriticalSection crit_; |
| 550 std::deque<VideoFrame> frames_ GUARDED_BY(crit_); | 587 std::deque<VideoFrame> frames_ GUARDED_BY(crit_); |
| 588 std::deque<VideoSendStream::Stats> send_stats_ GUARDED_BY(crit_); |
| 551 VideoFrame last_rendered_frame_ GUARDED_BY(crit_); | 589 VideoFrame last_rendered_frame_ GUARDED_BY(crit_); |
| 552 std::map<uint32_t, int64_t> send_times_ GUARDED_BY(crit_); | 590 std::map<uint32_t, int64_t> send_times_ GUARDED_BY(crit_); |
| 553 std::map<uint32_t, int64_t> recv_times_ GUARDED_BY(crit_); | 591 std::map<uint32_t, int64_t> recv_times_ GUARDED_BY(crit_); |
| 554 std::map<uint32_t, size_t> encoded_frame_sizes_ GUARDED_BY(crit_); | 592 std::map<uint32_t, size_t> encoded_frame_sizes_ GUARDED_BY(crit_); |
| 555 VideoFrame first_send_frame_ GUARDED_BY(crit_); | 593 VideoFrame first_send_frame_ GUARDED_BY(crit_); |
| 556 const double avg_psnr_threshold_; | 594 const double avg_psnr_threshold_; |
| 557 const double avg_ssim_threshold_; | 595 const double avg_ssim_threshold_; |
| 558 | 596 |
| 559 rtc::CriticalSection comparison_lock_; | 597 rtc::CriticalSection comparison_lock_; |
| 560 std::vector<ThreadWrapper*> comparison_thread_pool_; | 598 std::vector<ThreadWrapper*> comparison_thread_pool_; |
| 561 rtc::scoped_ptr<ThreadWrapper> stats_polling_thread_; | 599 rtc::scoped_ptr<ThreadWrapper> stats_polling_thread_; |
| 562 const rtc::scoped_ptr<EventWrapper> comparison_available_event_; | 600 const rtc::scoped_ptr<EventWrapper> comparison_available_event_; |
| 563 std::deque<FrameComparison> comparisons_ GUARDED_BY(comparison_lock_); | 601 std::deque<FrameComparison> comparisons_ GUARDED_BY(comparison_lock_); |
| 564 const rtc::scoped_ptr<EventWrapper> done_; | 602 const rtc::scoped_ptr<EventWrapper> done_; |
| 565 }; | 603 }; |
| 566 | 604 |
| 567 VideoQualityTest::VideoQualityTest() : clock_(Clock::GetRealTimeClock()) {} | 605 void FullStackTestBefore::RunTest(const FullStackTestBeforeParams& params) { |
| 568 | 606 // TODO(ivica): Add num_temporal_layers as a param. |
| 569 void VideoQualityTest::ValidateParams(const Params& params) { | 607 unsigned char num_temporal_layers = |
| 570 RTC_CHECK_GE(params.common.max_bitrate_bps, params.common.target_bitrate_bps); | 608 params.graph_data_output_filename.empty() ? 2 : 1; |
| 571 RTC_CHECK_GE(params.common.target_bitrate_bps, params.common.min_bitrate_bps); | 609 |
| 572 RTC_CHECK_LT(params.common.tl_discard_threshold, | 610 test::DirectTransport send_transport(params.link); |
| 573 params.common.num_temporal_layers); | 611 test::DirectTransport recv_transport(params.link); |
| 574 } | 612 VideoAnalyzerBefore analyzer(nullptr, &send_transport, params.test_label, |
| 575 | 613 params.avg_psnr_threshold, params.avg_ssim_threshold, |
| 576 void VideoQualityTest::TestBody() {} | 614 params.test_durations_secs * params.clip.fps, |
| 577 | 615 params.graph_data_output_filename); |
| 578 void VideoQualityTest::SetupFullStack(const Params& params, | 616 |
| 579 Transport* send_transport, | 617 CreateCalls(Call::Config(), Call::Config()); |
| 580 Transport* recv_transport) { | 618 |
| 581 if (params.logs) | 619 analyzer.SetReceiver(receiver_call_->Receiver()); |
| 582 trace_to_stderr_.reset(new test::TraceToStderr); | 620 send_transport.SetReceiver(&analyzer); |
| 583 | 621 recv_transport.SetReceiver(sender_call_->Receiver()); |
| 584 CreateSendConfig(1, send_transport); | 622 |
| 585 | 623 CreateSendConfig(1, &analyzer); |
| 586 int payload_type; | 624 |
| 587 if (params.common.codec == "VP8") { | 625 rtc::scoped_ptr<VideoEncoder> encoder; |
| 588 encoder_.reset(VideoEncoder::Create(VideoEncoder::kVp8)); | 626 if (params.codec == "VP8") { |
| 589 payload_type = kPayloadTypeVP8; | 627 encoder = |
| 590 } else if (params.common.codec == "VP9") { | 628 rtc::scoped_ptr<VideoEncoder>(VideoEncoder::Create(VideoEncoder::kVp8)); |
| 591 encoder_.reset(VideoEncoder::Create(VideoEncoder::kVp9)); | 629 send_config_.encoder_settings.encoder = encoder.get(); |
| 592 payload_type = kPayloadTypeVP9; | 630 send_config_.encoder_settings.payload_name = "VP8"; |
| 631 } else if (params.codec == "VP9") { |
| 632 encoder = |
| 633 rtc::scoped_ptr<VideoEncoder>(VideoEncoder::Create(VideoEncoder::kVp9)); |
| 634 send_config_.encoder_settings.encoder = encoder.get(); |
| 635 send_config_.encoder_settings.payload_name = "VP9"; |
| 593 } else { | 636 } else { |
| 594 RTC_NOTREACHED() << "Codec not supported!"; | 637 RTC_NOTREACHED() << "Codec not supported!"; |
| 595 return; | 638 return; |
| 596 } | 639 } |
| 597 send_config_.encoder_settings.encoder = encoder_.get(); | 640 send_config_.encoder_settings.payload_type = 124; |
| 598 send_config_.encoder_settings.payload_name = params.common.codec; | |
| 599 send_config_.encoder_settings.payload_type = payload_type; | |
| 600 | 641 |
| 601 send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs; | 642 send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs; |
| 602 send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]); | 643 send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]); |
| 603 send_config_.rtp.rtx.payload_type = kSendRtxPayloadType; | 644 send_config_.rtp.rtx.payload_type = kSendRtxPayloadType; |
| 604 | 645 |
| 605 send_config_.rtp.extensions.clear(); | 646 VideoStream* stream = &encoder_config_.streams[0]; |
| 606 if (params.common.send_side_bwe) { | 647 stream->width = params.clip.width; |
| 607 send_config_.rtp.extensions.push_back(RtpExtension( | 648 stream->height = params.clip.height; |
| 608 RtpExtension::kTransportSequenceNumber, kTransportSeqExtensionId)); | 649 stream->min_bitrate_bps = params.min_bitrate_bps; |
| 609 } else { | 650 stream->target_bitrate_bps = params.target_bitrate_bps; |
| 610 send_config_.rtp.extensions.push_back( | 651 stream->max_bitrate_bps = params.max_bitrate_bps; |
| 611 RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId)); | 652 stream->max_framerate = params.clip.fps; |
| 653 |
| 654 VideoCodecVP8 vp8_settings; |
| 655 VideoCodecVP9 vp9_settings; |
| 656 if (params.mode == ContentMode::kScreensharingStaticImage || |
| 657 params.mode == ContentMode::kScreensharingScrollingImage) { |
| 658 encoder_config_.content_type = VideoEncoderConfig::ContentType::kScreen; |
| 659 encoder_config_.min_transmit_bitrate_bps = 400 * 1000; |
| 660 if (params.codec == "VP8") { |
| 661 vp8_settings = VideoEncoder::GetDefaultVp8Settings(); |
| 662 vp8_settings.denoisingOn = false; |
| 663 vp8_settings.frameDroppingOn = false; |
| 664 vp8_settings.numberOfTemporalLayers = num_temporal_layers; |
| 665 encoder_config_.encoder_specific_settings = &vp8_settings; |
| 666 } else if (params.codec == "VP9") { |
| 667 vp9_settings = VideoEncoder::GetDefaultVp9Settings(); |
| 668 vp9_settings.denoisingOn = false; |
| 669 vp9_settings.frameDroppingOn = false; |
| 670 vp9_settings.numberOfTemporalLayers = num_temporal_layers; |
| 671 encoder_config_.encoder_specific_settings = &vp9_settings; |
| 672 } |
| 673 |
| 674 stream->temporal_layer_thresholds_bps.clear(); |
| 675 if (num_temporal_layers > 1) { |
| 676 stream->temporal_layer_thresholds_bps.push_back( |
| 677 stream->target_bitrate_bps); |
| 678 } |
| 612 } | 679 } |
| 613 | 680 |
| 614 // Automatically fill out streams[0] with params. | 681 CreateMatchingReceiveConfigs(&recv_transport); |
| 615 VideoStream* stream = &encoder_config_.streams[0]; | 682 receive_configs_[0].renderer = &analyzer; |
| 616 stream->width = params.common.width; | |
| 617 stream->height = params.common.height; | |
| 618 stream->min_bitrate_bps = params.common.min_bitrate_bps; | |
| 619 stream->target_bitrate_bps = params.common.target_bitrate_bps; | |
| 620 stream->max_bitrate_bps = params.common.max_bitrate_bps; | |
| 621 stream->max_framerate = static_cast<int>(params.common.fps); | |
| 622 | |
| 623 stream->temporal_layer_thresholds_bps.clear(); | |
| 624 if (params.common.num_temporal_layers > 1) { | |
| 625 stream->temporal_layer_thresholds_bps.push_back(stream->target_bitrate_bps); | |
| 626 } | |
| 627 | |
| 628 CreateMatchingReceiveConfigs(recv_transport); | |
| 629 | |
| 630 receive_configs_[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs; | 683 receive_configs_[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs; |
| 631 receive_configs_[0].rtp.rtx[kSendRtxPayloadType].ssrc = kSendRtxSsrcs[0]; | 684 receive_configs_[0].rtp.rtx[kSendRtxPayloadType].ssrc = kSendRtxSsrcs[0]; |
| 632 receive_configs_[0].rtp.rtx[kSendRtxPayloadType].payload_type = | 685 receive_configs_[0].rtp.rtx[kSendRtxPayloadType].payload_type = |
| 633 kSendRtxPayloadType; | 686 kSendRtxPayloadType; |
| 634 | 687 |
| 635 encoder_config_.min_transmit_bitrate_bps = params.common.min_transmit_bps; | 688 for (auto& config : receive_configs_) |
| 636 } | 689 config.pre_decode_callback = &analyzer; |
| 637 | 690 CreateStreams(); |
| 638 void VideoQualityTest::SetupScreenshare(const Params& params) { | 691 analyzer.input_ = send_stream_->Input(); |
| 639 RTC_CHECK(params.screenshare.enabled); | 692 analyzer.send_stream_ = send_stream_; |
| 640 | 693 |
| 641 // Fill out codec settings. | |
| 642 encoder_config_.content_type = VideoEncoderConfig::ContentType::kScreen; | |
| 643 if (params.common.codec == "VP8") { | |
| 644 codec_settings_.VP8 = VideoEncoder::GetDefaultVp8Settings(); | |
| 645 codec_settings_.VP8.denoisingOn = false; | |
| 646 codec_settings_.VP8.frameDroppingOn = false; | |
| 647 codec_settings_.VP8.numberOfTemporalLayers = | |
| 648 static_cast<unsigned char>(params.common.num_temporal_layers); | |
| 649 encoder_config_.encoder_specific_settings = &codec_settings_.VP8; | |
| 650 } else if (params.common.codec == "VP9") { | |
| 651 codec_settings_.VP9 = VideoEncoder::GetDefaultVp9Settings(); | |
| 652 codec_settings_.VP9.denoisingOn = false; | |
| 653 codec_settings_.VP9.frameDroppingOn = false; | |
| 654 codec_settings_.VP9.numberOfTemporalLayers = | |
| 655 static_cast<unsigned char>(params.common.num_temporal_layers); | |
| 656 encoder_config_.encoder_specific_settings = &codec_settings_.VP9; | |
| 657 } | |
| 658 | |
| 659 // Setup frame generator. | |
| 660 const size_t kWidth = 1850; | |
| 661 const size_t kHeight = 1110; | |
| 662 std::vector<std::string> slides; | 694 std::vector<std::string> slides; |
| 663 slides.push_back(test::ResourcePath("web_screenshot_1850_1110", "yuv")); | 695 slides.push_back(test::ResourcePath("web_screenshot_1850_1110", "yuv")); |
| 664 slides.push_back(test::ResourcePath("presentation_1850_1110", "yuv")); | 696 slides.push_back(test::ResourcePath("presentation_1850_1110", "yuv")); |
| 665 slides.push_back(test::ResourcePath("photo_1850_1110", "yuv")); | 697 slides.push_back(test::ResourcePath("photo_1850_1110", "yuv")); |
| 666 slides.push_back(test::ResourcePath("difficult_photo_1850_1110", "yuv")); | 698 slides.push_back(test::ResourcePath("difficult_photo_1850_1110", "yuv")); |
| 667 | 699 size_t kSlidesWidth = 1850; |
| 668 if (params.screenshare.scroll_duration == 0) { | 700 size_t kSlidesHeight = 1110; |
| 669 // Cycle image every slide_change_interval seconds. | 701 |
| 670 frame_generator_.reset(test::FrameGenerator::CreateFromYuvFile( | 702 Clock* clock = Clock::GetRealTimeClock(); |
| 671 slides, kWidth, kHeight, | 703 rtc::scoped_ptr<test::FrameGenerator> frame_generator; |
| 672 params.screenshare.slide_change_interval * params.common.fps)); | 704 |
| 673 } else { | 705 switch (params.mode) { |
| 674 RTC_CHECK_LE(params.common.width, kWidth); | 706 case ContentMode::kRealTimeVideo: |
| 675 RTC_CHECK_LE(params.common.height, kHeight); | 707 frame_generator.reset(test::FrameGenerator::CreateFromYuvFile( |
| 676 RTC_CHECK_GT(params.screenshare.slide_change_interval, 0); | 708 std::vector<std::string>(1, |
| 677 const int kPauseDurationMs = (params.screenshare.slide_change_interval - | 709 test::ResourcePath(params.clip.name, "yuv")), |
| 678 params.screenshare.scroll_duration) * 1000; | 710 params.clip.width, params.clip.height, 1)); |
| 679 RTC_CHECK_LE(params.screenshare.scroll_duration, | 711 break; |
| 680 params.screenshare.slide_change_interval); | 712 case ContentMode::kScreensharingScrollingImage: |
| 681 | 713 frame_generator.reset( |
| 682 if (params.screenshare.scroll_duration) { | |
| 683 frame_generator_.reset( | |
| 684 test::FrameGenerator::CreateScrollingInputFromYuvFiles( | 714 test::FrameGenerator::CreateScrollingInputFromYuvFiles( |
| 685 clock_, slides, kWidth, kHeight, params.common.width, | 715 clock, slides, kSlidesWidth, kSlidesHeight, params.clip.width, |
| 686 params.common.height, params.screenshare.scroll_duration * 1000, | 716 params.clip.height, 2000, |
| 687 kPauseDurationMs)); | 717 8000)); // Scroll for 2 seconds, then pause for 8. |
| 688 } else { | 718 break; |
| 689 frame_generator_.reset(test::FrameGenerator::CreateFromYuvFile( | 719 case ContentMode::kScreensharingStaticImage: |
| 690 slides, kWidth, kHeight, | 720 frame_generator.reset(test::FrameGenerator::CreateFromYuvFile( |
| 691 params.screenshare.slide_change_interval * params.common.fps)); | 721 slides, kSlidesWidth, kSlidesHeight, |
| 692 } | 722 10 * params.clip.fps)); // Cycle image every 10 seconds. |
| 723 break; |
| 693 } | 724 } |
| 694 } | 725 |
| 695 | 726 ASSERT_TRUE(frame_generator.get() != nullptr); |
| 696 void VideoQualityTest::CreateCapturer(const Params& params, | 727 frame_generator_capturer_.reset(new test::FrameGeneratorCapturer( |
| 697 VideoCaptureInput* input) { | 728 clock, &analyzer, frame_generator.release(), params.clip.fps)); |
| 698 if (params.screenshare.enabled) { | 729 ASSERT_TRUE(frame_generator_capturer_->Init()); |
| 699 test::FrameGeneratorCapturer *frame_generator_capturer = | 730 |
| 700 new test::FrameGeneratorCapturer( | 731 Start(); |
| 701 clock_, input, frame_generator_.release(), params.common.fps); | |
| 702 EXPECT_TRUE(frame_generator_capturer->Init()); | |
| 703 capturer_.reset(frame_generator_capturer); | |
| 704 } else { | |
| 705 if (params.video.clip_name.empty()) { | |
| 706 capturer_.reset(test::VideoCapturer::Create( | |
| 707 input, params.common.width, params.common.height, params.common.fps, | |
| 708 clock_)); | |
| 709 } else { | |
| 710 capturer_.reset(test::FrameGeneratorCapturer::CreateFromYuvFile( | |
| 711 input, test::ResourcePath(params.video.clip_name, "yuv"), | |
| 712 params.common.width, params.common.height, params.common.fps, | |
| 713 clock_)); | |
| 714 ASSERT_TRUE(capturer_.get() != nullptr) | |
| 715 << "Could not create capturer for " << params.video.clip_name | |
| 716 << ".yuv. Is this resource file present?"; | |
| 717 } | |
| 718 } | |
| 719 } | |
| 720 | |
| 721 void VideoQualityTest::RunWithAnalyzer(const Params& params) { | |
| 722 // TODO(ivica): Merge with RunWithRenderer and use a flag / argument to | |
| 723 // differentiate between the analyzer and the renderer case. | |
| 724 ValidateParams(params); | |
| 725 | |
| 726 FILE* graph_data_output_file = nullptr; | |
| 727 if (!params.analyzer.graph_data_output_filename.empty()) { | |
| 728 graph_data_output_file = | |
| 729 fopen(params.analyzer.graph_data_output_filename.c_str(), "w"); | |
| 730 RTC_CHECK(graph_data_output_file != nullptr) | |
| 731 << "Can't open the file " | |
| 732 << params.analyzer.graph_data_output_filename << "!"; | |
| 733 } | |
| 734 | |
| 735 test::LayerFilteringTransport send_transport( | |
| 736 params.pipe, kPayloadTypeVP8, kPayloadTypeVP9, | |
| 737 static_cast<uint8_t>(params.common.tl_discard_threshold), 0); | |
| 738 test::DirectTransport recv_transport(params.pipe); | |
| 739 VideoAnalyzer analyzer( | |
| 740 nullptr, &send_transport, params.analyzer.test_label, | |
| 741 params.analyzer.avg_psnr_threshold, params.analyzer.avg_ssim_threshold, | |
| 742 params.analyzer.test_durations_secs * params.common.fps, | |
| 743 graph_data_output_file); | |
| 744 | |
| 745 Call::Config call_config; | |
| 746 call_config.bitrate_config = params.common.call_bitrate_config; | |
| 747 CreateCalls(call_config, call_config); | |
| 748 | |
| 749 analyzer.SetReceiver(receiver_call_->Receiver()); | |
| 750 send_transport.SetReceiver(&analyzer); | |
| 751 recv_transport.SetReceiver(sender_call_->Receiver()); | |
| 752 | |
| 753 SetupFullStack(params, &analyzer, &recv_transport); | |
| 754 receive_configs_[0].renderer = &analyzer; | |
| 755 for (auto& config : receive_configs_) | |
| 756 config.pre_decode_callback = &analyzer; | |
| 757 | |
| 758 if (params.screenshare.enabled) | |
| 759 SetupScreenshare(params); | |
| 760 | |
| 761 CreateCapturer(params, &analyzer); | |
| 762 | |
| 763 CreateStreams(); | |
| 764 analyzer.input_ = send_stream_->Input(); | |
| 765 analyzer.send_stream_ = send_stream_; | |
| 766 | |
| 767 send_stream_->Start(); | |
| 768 for (size_t i = 0; i < receive_streams_.size(); ++i) | |
| 769 receive_streams_[i]->Start(); | |
| 770 capturer_->Start(); | |
| 771 | 732 |
| 772 analyzer.Wait(); | 733 analyzer.Wait(); |
| 773 | 734 |
| 774 send_transport.StopSending(); | 735 send_transport.StopSending(); |
| 775 recv_transport.StopSending(); | 736 recv_transport.StopSending(); |
| 776 | 737 |
| 777 capturer_->Stop(); | 738 Stop(); |
| 778 for (size_t i = 0; i < receive_streams_.size(); ++i) | |
| 779 receive_streams_[i]->Stop(); | |
| 780 send_stream_->Stop(); | |
| 781 | 739 |
| 782 DestroyStreams(); | 740 DestroyStreams(); |
| 783 | |
| 784 if (graph_data_output_file) | |
| 785 fclose(graph_data_output_file); | |
| 786 } | 741 } |
| 787 | 742 |
| 788 void VideoQualityTest::RunWithVideoRenderer(const Params& params) { | 743 // TEST_F(FullStackTestBefore, ParisQcifWithoutPacketLoss) { |
| 789 ValidateParams(params); | 744 // FullStackTestBeforeParams paris_qcif = {"net_delay_0_0_plr_0", |
| 790 | 745 // {"paris_qcif", 176, 144, 30}, |
| 791 rtc::scoped_ptr<test::VideoRenderer> local_preview( | 746 // ContentMode::kRealTimeVideo, |
| 792 test::VideoRenderer::Create("Local Preview", params.common.width, | 747 // 300000, |
| 793 params.common.height)); | 748 // 300000, |
| 794 rtc::scoped_ptr<test::VideoRenderer> loopback_video( | 749 // 300000, |
| 795 test::VideoRenderer::Create("Loopback Video", params.common.width, | 750 // 36.0, |
| 796 params.common.height)); | 751 // 0.96, |
| 797 | 752 // kFullStackTestBeforeDurationSecs, |
| 798 // TODO(ivica): Remove bitrate_config and use the default Call::Config(), to | 753 // "VP8"}; |
| 799 // match the full stack tests. | 754 // RunTest(paris_qcif); |
| 800 Call::Config call_config; | 755 // } |
| 801 call_config.bitrate_config = params.common.call_bitrate_config; | 756 // |
| 802 rtc::scoped_ptr<Call> call(Call::Create(call_config)); | 757 // TEST_F(FullStackTestBefore, ForemanCifWithoutPacketLoss) { |
| 803 | 758 // // TODO(pbos): Decide on psnr/ssim thresholds for foreman_cif. |
| 804 test::LayerFilteringTransport transport( | 759 // FullStackTestBeforeParams foreman_cif = {"foreman_cif_net_delay_0_0_plr_0", |
| 805 params.pipe, kPayloadTypeVP8, kPayloadTypeVP9, | 760 // {"foreman_cif", 352, 288, 30}, |
| 806 static_cast<uint8_t>(params.common.tl_discard_threshold), 0); | 761 // ContentMode::kRealTimeVideo, |
| 807 // TODO(ivica): Use two calls to be able to merge with RunWithAnalyzer or at | 762 // 700000, |
| 808 // least share as much code as possible. That way this test would also match | 763 // 700000, |
| 809 // the full stack tests better. | 764 // 700000, |
| 810 transport.SetReceiver(call->Receiver()); | 765 // 0.0, |
| 811 | 766 // 0.0, |
| 812 SetupFullStack(params, &transport, &transport); | 767 // kFullStackTestBeforeDurationSecs, |
| 813 send_config_.local_renderer = local_preview.get(); | 768 // "VP8"}; |
| 814 receive_configs_[0].renderer = loopback_video.get(); | 769 // RunTest(foreman_cif); |
| 815 | 770 // } |
| 816 if (params.screenshare.enabled) | 771 // |
| 817 SetupScreenshare(params); | 772 // TEST_F(FullStackTestBefore, ForemanCifPlr5) { |
| 818 | 773 // FullStackTestBeforeParams foreman_cif = {"foreman_cif_delay_50_0_plr_5", |
| 819 send_stream_ = call->CreateVideoSendStream(send_config_, encoder_config_); | 774 // {"foreman_cif", 352, 288, 30}, |
| 820 CreateCapturer(params, send_stream_->Input()); | 775 // ContentMode::kRealTimeVideo, |
| 821 | 776 // 30000, |
| 822 VideoReceiveStream* receive_stream = | 777 // 500000, |
| 823 call->CreateVideoReceiveStream(receive_configs_[0]); | 778 // 2000000, |
| 824 | 779 // 0.0, |
| 825 receive_stream->Start(); | 780 // 0.0, |
| 826 send_stream_->Start(); | 781 // kFullStackTestBeforeDurationSecs, |
| 827 capturer_->Start(); | 782 // "VP8"}; |
| 828 | 783 // foreman_cif.link.loss_percent = 5; |
| 829 test::PressEnterToContinue(); | 784 // foreman_cif.link.queue_delay_ms = 50; |
| 830 | 785 // RunTest(foreman_cif); |
| 831 capturer_->Stop(); | 786 // } |
| 832 send_stream_->Stop(); | 787 // |
| 833 receive_stream->Stop(); | 788 // TEST_F(FullStackTestBefore, ForemanCif500kbps) { |
| 834 | 789 // FullStackTestBeforeParams foreman_cif = {"foreman_cif_500kbps", |
| 835 call->DestroyVideoReceiveStream(receive_stream); | 790 // {"foreman_cif", 352, 288, 30}, |
| 836 call->DestroyVideoSendStream(send_stream_); | 791 // ContentMode::kRealTimeVideo, |
| 837 | 792 // 30000, |
| 838 transport.StopSending(); | 793 // 500000, |
| 794 // 2000000, |
| 795 // 0.0, |
| 796 // 0.0, |
| 797 // kFullStackTestBeforeDurationSecs, |
| 798 // "VP8"}; |
| 799 // foreman_cif.link.queue_length_packets = 0; |
| 800 // foreman_cif.link.queue_delay_ms = 0; |
| 801 // foreman_cif.link.link_capacity_kbps = 500; |
| 802 // RunTest(foreman_cif); |
| 803 // } |
| 804 // |
| 805 // TEST_F(FullStackTestBefore, ForemanCif500kbpsLimitedQueue) { |
| 806 // FullStackTestBeforeParams foreman_cif = {"foreman_cif_500kbps_32pkts_queue"
, |
| 807 // {"foreman_cif", 352, 288, 30}, |
| 808 // ContentMode::kRealTimeVideo, |
| 809 // 30000, |
| 810 // 500000, |
| 811 // 2000000, |
| 812 // 0.0, |
| 813 // 0.0, |
| 814 // kFullStackTestBeforeDurationSecs, |
| 815 // "VP8"}; |
| 816 // foreman_cif.link.queue_length_packets = 32; |
| 817 // foreman_cif.link.queue_delay_ms = 0; |
| 818 // foreman_cif.link.link_capacity_kbps = 500; |
| 819 // RunTest(foreman_cif); |
| 820 // } |
| 821 // |
| 822 // TEST_F(FullStackTestBefore, ForemanCif500kbps100ms) { |
| 823 // FullStackTestBeforeParams foreman_cif = {"foreman_cif_500kbps_100ms", |
| 824 // {"foreman_cif", 352, 288, 30}, |
| 825 // ContentMode::kRealTimeVideo, |
| 826 // 30000, |
| 827 // 500000, |
| 828 // 2000000, |
| 829 // 0.0, |
| 830 // 0.0, |
| 831 // kFullStackTestBeforeDurationSecs, |
| 832 // "VP8"}; |
| 833 // foreman_cif.link.queue_length_packets = 0; |
| 834 // foreman_cif.link.queue_delay_ms = 100; |
| 835 // foreman_cif.link.link_capacity_kbps = 500; |
| 836 // RunTest(foreman_cif); |
| 837 // } |
| 838 // |
| 839 // TEST_F(FullStackTestBefore, ForemanCif500kbps100msLimitedQueue) { |
| 840 // FullStackTestBeforeParams foreman_cif = {"foreman_cif_500kbps_100ms_32pkts_
queue", |
| 841 // {"foreman_cif", 352, 288, 30}, |
| 842 // ContentMode::kRealTimeVideo, |
| 843 // 30000, |
| 844 // 500000, |
| 845 // 2000000, |
| 846 // 0.0, |
| 847 // 0.0, |
| 848 // kFullStackTestBeforeDurationSecs, |
| 849 // "VP8"}; |
| 850 // foreman_cif.link.queue_length_packets = 32; |
| 851 // foreman_cif.link.queue_delay_ms = 100; |
| 852 // foreman_cif.link.link_capacity_kbps = 500; |
| 853 // RunTest(foreman_cif); |
| 854 // } |
| 855 // |
| 856 // TEST_F(FullStackTestBefore, ForemanCif1000kbps100msLimitedQueue) { |
| 857 // FullStackTestBeforeParams foreman_cif = {"foreman_cif_1000kbps_100ms_32pkts
_queue", |
| 858 // {"foreman_cif", 352, 288, 30}, |
| 859 // ContentMode::kRealTimeVideo, |
| 860 // 30000, |
| 861 // 2000000, |
| 862 // 2000000, |
| 863 // 0.0, |
| 864 // 0.0, |
| 865 // kFullStackTestBeforeDurationSecs, |
| 866 // "VP8"}; |
| 867 // foreman_cif.link.queue_length_packets = 32; |
| 868 // foreman_cif.link.queue_delay_ms = 100; |
| 869 // foreman_cif.link.link_capacity_kbps = 1000; |
| 870 // RunTest(foreman_cif); |
| 871 // } |
| 872 // |
| 873 // // Temporarily disabled on Android due to low test timeouts. |
| 874 // // https://code.google.com/p/chromium/issues/detail?id=513170 |
| 875 // #include "webrtc/test/testsupport/gtest_disable.h" |
| 876 // TEST_F(FullStackTestBefore, DISABLED_ON_ANDROID(ScreenshareSlidesVP8_2TL)) { |
| 877 // FullStackTestBeforeParams screenshare_params = { |
| 878 // "screenshare_slides", |
| 879 // {"screenshare_slides", 1850, 1110, 5}, |
| 880 // ContentMode::kScreensharingStaticImage, |
| 881 // 50000, |
| 882 // 200000, |
| 883 // 2000000, |
| 884 // 0.0, |
| 885 // 0.0, |
| 886 // kFullStackTestBeforeDurationSecs, |
| 887 // "VP8"}; |
| 888 // RunTest(screenshare_params); |
| 889 // } |
| 890 // |
| 891 // TEST_F(FullStackTestBefore, DISABLED_ON_ANDROID(ScreenshareSlidesVP8_2TL_Scro
ll)) { |
| 892 // FullStackTestBeforeParams screenshare_params = { |
| 893 // "screenshare_slides_scrolling", |
| 894 // // Crop height by two, scrolling vertically only. |
| 895 // {"screenshare_slides_scrolling", 1850, 1110 / 2, 5}, |
| 896 // ContentMode::kScreensharingScrollingImage, |
| 897 // 50000, |
| 898 // 200000, |
| 899 // 2000000, |
| 900 // 0.0, |
| 901 // 0.0, |
| 902 // kFullStackTestBeforeDurationSecs, |
| 903 // "VP8"}; |
| 904 // RunTest(screenshare_params); |
| 905 // } |
| 906 |
| 907 #define SCREENSHARE_VP8_2TL { \ |
| 908 FullStackTestBeforeParams screenshare_params = { \ |
| 909 "screenshare_slides", \ |
| 910 {"screenshare_slides", 1850, 1110, 5}, \ |
| 911 ContentMode::kScreensharingStaticImage, \ |
| 912 50000, \ |
| 913 200000, \ |
| 914 2000000, \ |
| 915 0.0, \ |
| 916 0.0, \ |
| 917 kFullStackTestBeforeDurationSecs, \ |
| 918 "VP8"}; \ |
| 919 RunTest(screenshare_params); \ |
| 839 } | 920 } |
| 840 | 921 |
| 922 #define SCREENSHARE_VP9_2TL { \ |
| 923 FullStackTestBeforeParams screenshare_params = { \ |
| 924 "screenshare_slides_vp9_2tl", \ |
| 925 {"screenshare_slides", 1850, 1110, 5}, \ |
| 926 ContentMode::kScreensharingStaticImage, \ |
| 927 50000, \ |
| 928 200000, \ |
| 929 2000000, \ |
| 930 0.0, \ |
| 931 0.0, \ |
| 932 kFullStackTestBeforeDurationSecs, \ |
| 933 "VP9"}; \ |
| 934 RunTest(screenshare_params); \ |
| 935 } |
| 936 |
| 937 TEST_F(FullStackTestBefore, ScreenshareSlidesVP8_2TL_Before_0) SCREENSHARE_VP8_2
TL; |
| 938 TEST_F(FullStackTestBefore, ScreenshareSlidesVP8_2TL_Before_1) SCREENSHARE_VP8_2
TL; |
| 939 TEST_F(FullStackTestBefore, ScreenshareSlidesVP8_2TL_Before_2) SCREENSHARE_VP8_2
TL; |
| 940 TEST_F(FullStackTestBefore, ScreenshareSlidesVP8_2TL_Before_3) SCREENSHARE_VP8_2
TL; |
| 941 TEST_F(FullStackTestBefore, ScreenshareSlidesVP8_2TL_Before_4) SCREENSHARE_VP8_2
TL; |
| 942 TEST_F(FullStackTestBefore, ScreenshareSlidesVP8_2TL_Before_5) SCREENSHARE_VP8_2
TL; |
| 943 TEST_F(FullStackTestBefore, ScreenshareSlidesVP8_2TL_Before_6) SCREENSHARE_VP8_2
TL; |
| 944 TEST_F(FullStackTestBefore, ScreenshareSlidesVP8_2TL_Before_7) SCREENSHARE_VP8_2
TL; |
| 945 TEST_F(FullStackTestBefore, ScreenshareSlidesVP8_2TL_Before_8) SCREENSHARE_VP8_2
TL; |
| 946 TEST_F(FullStackTestBefore, ScreenshareSlidesVP8_2TL_Before_9) SCREENSHARE_VP8_2
TL; |
| 841 } // namespace webrtc | 947 } // namespace webrtc |
| OLD | NEW |