Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(123)

Side by Side Diff: webrtc/video/video_quality_test.cc

Issue 1308403003: Refactoring full stack and loopback tests (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: rebase updates Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/video/video_quality_test.h ('k') | webrtc/webrtc_tests.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2015 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>
12 #include <deque> 13 #include <deque>
13 #include <map> 14 #include <map>
15 #include <vector>
14 16
15 #include "testing/gtest/include/gtest/gtest.h" 17 #include "testing/gtest/include/gtest/gtest.h"
16 18
19 #include "webrtc/base/checks.h"
17 #include "webrtc/base/format_macros.h" 20 #include "webrtc/base/format_macros.h"
18 #include "webrtc/base/scoped_ptr.h" 21 #include "webrtc/base/scoped_ptr.h"
19 #include "webrtc/base/thread_annotations.h"
20 #include "webrtc/call.h" 22 #include "webrtc/call.h"
21 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" 23 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
22 #include "webrtc/frame_callback.h"
23 #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" 24 #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/system_wrappers/interface/critical_section_wrapper.h" 26 #include "webrtc/test/layer_filtering_transport.h"
27 #include "webrtc/system_wrappers/interface/event_wrapper.h" 27 #include "webrtc/test/run_loop.h"
28 #include "webrtc/system_wrappers/interface/sleep.h"
29 #include "webrtc/test/encoder_settings.h"
30 #include "webrtc/test/fake_encoder.h"
31 #include "webrtc/test/frame_generator.h"
32 #include "webrtc/test/frame_generator_capturer.h"
33 #include "webrtc/test/statistics.h" 28 #include "webrtc/test/statistics.h"
34 #include "webrtc/test/testsupport/fileutils.h" 29 #include "webrtc/test/testsupport/fileutils.h"
35 #include "webrtc/typedefs.h" 30 #include "webrtc/test/video_renderer.h"
36 #include "webrtc/video/full_stack.h" 31 #include "webrtc/video/video_quality_test.h"
37 32
38 namespace webrtc { 33 namespace webrtc {
39 34
40 static const int kFullStackTestDurationSecs = 60;
41 static const int kSendStatsPollingIntervalMs = 1000; 35 static const int kSendStatsPollingIntervalMs = 1000;
36 static const int kPayloadTypeVP8 = 123;
37 static const int kPayloadTypeVP9 = 124;
42 38
43 class VideoAnalyzer : public PacketReceiver, 39 class VideoAnalyzer : public PacketReceiver,
44 public newapi::Transport, 40 public newapi::Transport,
45 public VideoRenderer, 41 public VideoRenderer,
46 public VideoCaptureInput, 42 public VideoCaptureInput,
47 public EncodedFrameObserver { 43 public EncodedFrameObserver {
48 public: 44 public:
49 VideoAnalyzer(VideoCaptureInput* input, 45 VideoAnalyzer(VideoCaptureInput* input,
50 Transport* transport, 46 Transport* transport,
51 const char* test_label, 47 const std::string& test_label,
52 double avg_psnr_threshold, 48 double avg_psnr_threshold,
53 double avg_ssim_threshold, 49 double avg_ssim_threshold,
54 int duration_frames, 50 int duration_frames,
55 const std::string& graph_data_output_filename) 51 FILE* graph_data_output_file)
56 : input_(input), 52 : input_(input),
57 transport_(transport), 53 transport_(transport),
58 receiver_(nullptr), 54 receiver_(nullptr),
59 send_stream_(nullptr), 55 send_stream_(nullptr),
60 test_label_(test_label), 56 test_label_(test_label),
61 graph_data_output_filename_(graph_data_output_filename), 57 graph_data_output_file_(graph_data_output_file),
62 frames_to_process_(duration_frames), 58 frames_to_process_(duration_frames),
63 frames_recorded_(0), 59 frames_recorded_(0),
64 frames_processed_(0), 60 frames_processed_(0),
65 dropped_frames_(0), 61 dropped_frames_(0),
66 last_render_time_(0), 62 last_render_time_(0),
67 rtp_timestamp_delta_(0), 63 rtp_timestamp_delta_(0),
68 avg_psnr_threshold_(avg_psnr_threshold), 64 avg_psnr_threshold_(avg_psnr_threshold),
69 avg_ssim_threshold_(avg_ssim_threshold), 65 avg_ssim_threshold_(avg_ssim_threshold),
70 comparison_available_event_(EventWrapper::Create()), 66 comparison_available_event_(EventWrapper::Create()),
71 done_(EventWrapper::Create()) { 67 done_(EventWrapper::Create()) {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 } 137 }
142 138
143 bool SendRtp(const uint8_t* packet, size_t length) override { 139 bool SendRtp(const uint8_t* packet, size_t length) override {
144 rtc::scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create()); 140 rtc::scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
145 RTPHeader header; 141 RTPHeader header;
146 parser->Parse(packet, length, &header); 142 parser->Parse(packet, length, &header);
147 143
148 { 144 {
149 rtc::CritScope lock(&crit_); 145 rtc::CritScope lock(&crit_);
150 if (rtp_timestamp_delta_ == 0) { 146 if (rtp_timestamp_delta_ == 0) {
151 rtp_timestamp_delta_ = 147 rtp_timestamp_delta_ = header.timestamp - first_send_frame_.timestamp();
152 header.timestamp - first_send_frame_.timestamp();
153 first_send_frame_.Reset(); 148 first_send_frame_.Reset();
154 } 149 }
155 uint32_t timestamp = header.timestamp - rtp_timestamp_delta_; 150 uint32_t timestamp = header.timestamp - rtp_timestamp_delta_;
156 send_times_[timestamp] = 151 send_times_[timestamp] =
157 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds(); 152 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds();
158 encoded_frame_sizes_[timestamp] += 153 encoded_frame_sizes_[timestamp] +=
159 length - (header.headerLength + header.paddingLength); 154 length - (header.headerLength + header.paddingLength);
160 } 155 }
161 156
162 return transport_->SendRtp(packet, length); 157 return transport_->SendRtp(packet, length);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 bool IsTextureSupported() const override { return false; } 195 bool IsTextureSupported() const override { return false; }
201 196
202 void Wait() { 197 void Wait() {
203 // Frame comparisons can be very expensive. Wait for test to be done, but 198 // Frame comparisons can be very expensive. Wait for test to be done, but
204 // at time-out check if frames_processed is going up. If so, give it more 199 // at time-out check if frames_processed is going up. If so, give it more
205 // time, otherwise fail. Hopefully this will reduce test flakiness. 200 // time, otherwise fail. Hopefully this will reduce test flakiness.
206 201
207 int last_frames_processed = -1; 202 int last_frames_processed = -1;
208 EventTypeWrapper eventType; 203 EventTypeWrapper eventType;
209 int iteration = 0; 204 int iteration = 0;
210 while ((eventType = done_->Wait(FullStackTest::kDefaultTimeoutMs)) != 205 while ((eventType = done_->Wait(VideoQualityTest::kDefaultTimeoutMs)) !=
211 kEventSignaled) { 206 kEventSignaled) {
212 int frames_processed; 207 int frames_processed;
213 { 208 {
214 rtc::CritScope crit(&comparison_lock_); 209 rtc::CritScope crit(&comparison_lock_);
215 frames_processed = frames_processed_; 210 frames_processed = frames_processed_;
216 } 211 }
217 212
218 // Print some output so test infrastructure won't think we've crashed. 213 // Print some output so test infrastructure won't think we've crashed.
219 const char* kKeepAliveMessages[3] = { 214 const char* kKeepAliveMessages[3] = {
220 "Uh, I'm-I'm not quite dead, sir.", 215 "Uh, I'm-I'm not quite dead, sir.",
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 comparison_available_event_->Set(); 374 comparison_available_event_->Set();
380 return false; 375 return false;
381 } 376 }
382 return true; // Try again. 377 return true; // Try again.
383 } 378 }
384 379
385 PerformFrameComparison(comparison); 380 PerformFrameComparison(comparison);
386 381
387 if (FrameProcessed()) { 382 if (FrameProcessed()) {
388 PrintResults(); 383 PrintResults();
389 if (!graph_data_output_filename_.empty()) 384 if (graph_data_output_file_)
390 PrintSamplesToFile(); 385 PrintSamplesToFile();
391 done_->Set(); 386 done_->Set();
392 comparison_available_event_->Set(); 387 comparison_available_event_->Set();
393 return false; 388 return false;
394 } 389 }
395 390
396 return true; 391 return true;
397 } 392 }
398 393
399 bool PopComparison(FrameComparison* comparison) { 394 bool PopComparison(FrameComparison* comparison) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 ++frames_processed_; 428 ++frames_processed_;
434 assert(frames_processed_ <= frames_to_process_); 429 assert(frames_processed_ <= frames_to_process_);
435 return frames_processed_ == frames_to_process_; 430 return frames_processed_ == frames_to_process_;
436 } 431 }
437 432
438 void PrintResults() { 433 void PrintResults() {
439 rtc::CritScope crit(&comparison_lock_); 434 rtc::CritScope crit(&comparison_lock_);
440 PrintResult("psnr", psnr_, " dB"); 435 PrintResult("psnr", psnr_, " dB");
441 PrintResult("ssim", ssim_, ""); 436 PrintResult("ssim", ssim_, "");
442 PrintResult("sender_time", sender_time_, " ms"); 437 PrintResult("sender_time", sender_time_, " ms");
443 printf("RESULT dropped_frames: %s = %d frames\n", test_label_, 438 printf("RESULT dropped_frames: %s = %d frames\n", test_label_.c_str(),
444 dropped_frames_); 439 dropped_frames_);
445 PrintResult("receiver_time", receiver_time_, " ms"); 440 PrintResult("receiver_time", receiver_time_, " ms");
446 PrintResult("total_delay_incl_network", end_to_end_, " ms"); 441 PrintResult("total_delay_incl_network", end_to_end_, " ms");
447 PrintResult("time_between_rendered_frames", rendered_delta_, " ms"); 442 PrintResult("time_between_rendered_frames", rendered_delta_, " ms");
448 PrintResult("encoded_frame_size", encoded_frame_size_, " bytes"); 443 PrintResult("encoded_frame_size", encoded_frame_size_, " bytes");
449 PrintResult("encode_frame_rate", encode_frame_rate_, " fps"); 444 PrintResult("encode_frame_rate", encode_frame_rate_, " fps");
450 PrintResult("encode_time", encode_time_ms, " ms"); 445 PrintResult("encode_time", encode_time_ms, " ms");
451 PrintResult("encode_usage_percent", encode_usage_percent, " percent"); 446 PrintResult("encode_usage_percent", encode_usage_percent, " percent");
452 PrintResult("media_bitrate", media_bitrate_bps, " bps"); 447 PrintResult("media_bitrate", media_bitrate_bps, " bps");
453 448
454 EXPECT_GT(psnr_.Mean(), avg_psnr_threshold_); 449 EXPECT_GT(psnr_.Mean(), avg_psnr_threshold_);
455 EXPECT_GT(ssim_.Mean(), avg_ssim_threshold_); 450 EXPECT_GT(ssim_.Mean(), avg_ssim_threshold_);
456 } 451 }
457 452
458 void PerformFrameComparison(const FrameComparison& comparison) { 453 void PerformFrameComparison(const FrameComparison& comparison) {
459 // Perform expensive psnr and ssim calculations while not holding lock. 454 // Perform expensive psnr and ssim calculations while not holding lock.
460 double psnr = I420PSNR(&comparison.reference, &comparison.render); 455 double psnr = I420PSNR(&comparison.reference, &comparison.render);
461 double ssim = I420SSIM(&comparison.reference, &comparison.render); 456 double ssim = I420SSIM(&comparison.reference, &comparison.render);
462 457
463 int64_t input_time_ms = comparison.reference.ntp_time_ms(); 458 int64_t input_time_ms = comparison.reference.ntp_time_ms();
464 459
465 rtc::CritScope crit(&comparison_lock_); 460 rtc::CritScope crit(&comparison_lock_);
466 if (!graph_data_output_filename_.empty()) { 461 if (graph_data_output_file_) {
467 samples_.push_back(Sample( 462 samples_.push_back(
468 comparison.dropped, input_time_ms, comparison.send_time_ms, 463 Sample(comparison.dropped, input_time_ms, comparison.send_time_ms,
469 comparison.recv_time_ms, comparison.encoded_frame_size, psnr, ssim, 464 comparison.recv_time_ms, comparison.encoded_frame_size, psnr,
470 comparison.render_time_ms)); 465 ssim, comparison.render_time_ms));
471 } 466 }
472 psnr_.AddSample(psnr); 467 psnr_.AddSample(psnr);
473 ssim_.AddSample(ssim); 468 ssim_.AddSample(ssim);
474 469
475 if (comparison.dropped) { 470 if (comparison.dropped) {
476 ++dropped_frames_; 471 ++dropped_frames_;
477 return; 472 return;
478 } 473 }
479 if (last_render_time_ != 0) 474 if (last_render_time_ != 0)
480 rendered_delta_.AddSample(comparison.render_time_ms - last_render_time_); 475 rendered_delta_.AddSample(comparison.render_time_ms - last_render_time_);
481 last_render_time_ = comparison.render_time_ms; 476 last_render_time_ = comparison.render_time_ms;
482 477
483 sender_time_.AddSample(comparison.send_time_ms - input_time_ms); 478 sender_time_.AddSample(comparison.send_time_ms - input_time_ms);
484 receiver_time_.AddSample(comparison.render_time_ms - 479 receiver_time_.AddSample(comparison.render_time_ms -
485 comparison.recv_time_ms); 480 comparison.recv_time_ms);
486 end_to_end_.AddSample(comparison.render_time_ms - input_time_ms); 481 end_to_end_.AddSample(comparison.render_time_ms - input_time_ms);
487 encoded_frame_size_.AddSample(comparison.encoded_frame_size); 482 encoded_frame_size_.AddSample(comparison.encoded_frame_size);
488 } 483 }
489 484
490 void PrintResult(const char* result_type, 485 void PrintResult(const char* result_type,
491 test::Statistics stats, 486 test::Statistics stats,
492 const char* unit) { 487 const char* unit) {
493 printf("RESULT %s: %s = {%f, %f}%s\n", 488 printf("RESULT %s: %s = {%f, %f}%s\n",
494 result_type, 489 result_type,
495 test_label_, 490 test_label_.c_str(),
496 stats.Mean(), 491 stats.Mean(),
497 stats.StandardDeviation(), 492 stats.StandardDeviation(),
498 unit); 493 unit);
499 } 494 }
500 495
501 void PrintSamplesToFile(void) { 496 void PrintSamplesToFile(void) {
502 FILE* out = fopen(graph_data_output_filename_.c_str(), "w"); 497 FILE* out = graph_data_output_file_;
503 RTC_CHECK(out != nullptr) << "Couldn't open file: "
504 << graph_data_output_filename_;
505
506 rtc::CritScope crit(&comparison_lock_); 498 rtc::CritScope crit(&comparison_lock_);
507 std::sort(samples_.begin(), samples_.end(), 499 std::sort(samples_.begin(), samples_.end(),
508 [](const Sample& A, const Sample& B) 500 [](const Sample& A, const Sample& B) -> bool {
509 -> bool { return A.input_time_ms < B.input_time_ms; }); 501 return A.input_time_ms < B.input_time_ms;
502 });
510 503
511 fprintf(out, "%s\n", test_label_); 504 fprintf(out, "%s\n", test_label_.c_str());
512 fprintf(out, "%" PRIuS "\n", samples_.size()); 505 fprintf(out, "%" PRIuS "\n", samples_.size());
513 fprintf(out, 506 fprintf(out,
514 "dropped " 507 "dropped "
515 "input_time_ms " 508 "input_time_ms "
516 "send_time_ms " 509 "send_time_ms "
517 "recv_time_ms " 510 "recv_time_ms "
518 "encoded_frame_size " 511 "encoded_frame_size "
519 "psnr " 512 "psnr "
520 "ssim " 513 "ssim "
521 "render_time_ms\n"); 514 "render_time_ms\n");
522 for (const Sample& sample : samples_) { 515 for (const Sample& sample : samples_) {
523 fprintf(out, "%lf %lf %lf %lf %lf %lf %lf %lf\n", sample.dropped, 516 fprintf(out, "%lf %lf %lf %lf %lf %lf %lf %lf\n", sample.dropped,
524 sample.input_time_ms, sample.send_time_ms, sample.recv_time_ms, 517 sample.input_time_ms, sample.send_time_ms, sample.recv_time_ms,
525 sample.encoded_frame_size, sample.psnr, sample.ssim, 518 sample.encoded_frame_size, sample.psnr, sample.ssim,
526 sample.render_time_ms); 519 sample.render_time_ms);
527 } 520 }
528 fclose(out);
529 } 521 }
530 522
531 const char* const test_label_; 523 const std::string test_label_;
532 std::string graph_data_output_filename_; 524 FILE* const graph_data_output_file_;
533 std::vector<Sample> samples_ GUARDED_BY(comparison_lock_); 525 std::vector<Sample> samples_ GUARDED_BY(comparison_lock_);
534 test::Statistics sender_time_ GUARDED_BY(comparison_lock_); 526 test::Statistics sender_time_ GUARDED_BY(comparison_lock_);
535 test::Statistics receiver_time_ GUARDED_BY(comparison_lock_); 527 test::Statistics receiver_time_ GUARDED_BY(comparison_lock_);
536 test::Statistics psnr_ GUARDED_BY(comparison_lock_); 528 test::Statistics psnr_ GUARDED_BY(comparison_lock_);
537 test::Statistics ssim_ GUARDED_BY(comparison_lock_); 529 test::Statistics ssim_ GUARDED_BY(comparison_lock_);
538 test::Statistics end_to_end_ GUARDED_BY(comparison_lock_); 530 test::Statistics end_to_end_ GUARDED_BY(comparison_lock_);
539 test::Statistics rendered_delta_ GUARDED_BY(comparison_lock_); 531 test::Statistics rendered_delta_ GUARDED_BY(comparison_lock_);
540 test::Statistics encoded_frame_size_ GUARDED_BY(comparison_lock_); 532 test::Statistics encoded_frame_size_ GUARDED_BY(comparison_lock_);
541 test::Statistics encode_frame_rate_ GUARDED_BY(comparison_lock_); 533 test::Statistics encode_frame_rate_ GUARDED_BY(comparison_lock_);
542 test::Statistics encode_time_ms GUARDED_BY(comparison_lock_); 534 test::Statistics encode_time_ms GUARDED_BY(comparison_lock_);
543 test::Statistics encode_usage_percent GUARDED_BY(comparison_lock_); 535 test::Statistics encode_usage_percent GUARDED_BY(comparison_lock_);
544 test::Statistics media_bitrate_bps GUARDED_BY(comparison_lock_); 536 test::Statistics media_bitrate_bps GUARDED_BY(comparison_lock_);
545 537
546 const int frames_to_process_; 538 const int frames_to_process_;
547 int frames_recorded_; 539 int frames_recorded_;
548 int frames_processed_; 540 int frames_processed_;
549 int dropped_frames_; 541 int dropped_frames_;
550 int64_t last_render_time_; 542 int64_t last_render_time_;
551 uint32_t rtp_timestamp_delta_; 543 uint32_t rtp_timestamp_delta_;
552 544
553 rtc::CriticalSection crit_; 545 rtc::CriticalSection crit_;
554 std::deque<VideoFrame> frames_ GUARDED_BY(crit_); 546 std::deque<VideoFrame> frames_ GUARDED_BY(crit_);
555 std::deque<VideoSendStream::Stats> send_stats_ GUARDED_BY(crit_);
556 VideoFrame last_rendered_frame_ GUARDED_BY(crit_); 547 VideoFrame last_rendered_frame_ GUARDED_BY(crit_);
557 std::map<uint32_t, int64_t> send_times_ GUARDED_BY(crit_); 548 std::map<uint32_t, int64_t> send_times_ GUARDED_BY(crit_);
558 std::map<uint32_t, int64_t> recv_times_ GUARDED_BY(crit_); 549 std::map<uint32_t, int64_t> recv_times_ GUARDED_BY(crit_);
559 std::map<uint32_t, size_t> encoded_frame_sizes_ GUARDED_BY(crit_); 550 std::map<uint32_t, size_t> encoded_frame_sizes_ GUARDED_BY(crit_);
560 VideoFrame first_send_frame_ GUARDED_BY(crit_); 551 VideoFrame first_send_frame_ GUARDED_BY(crit_);
561 const double avg_psnr_threshold_; 552 const double avg_psnr_threshold_;
562 const double avg_ssim_threshold_; 553 const double avg_ssim_threshold_;
563 554
564 rtc::CriticalSection comparison_lock_; 555 rtc::CriticalSection comparison_lock_;
565 std::vector<ThreadWrapper*> comparison_thread_pool_; 556 std::vector<ThreadWrapper*> comparison_thread_pool_;
566 rtc::scoped_ptr<ThreadWrapper> stats_polling_thread_; 557 rtc::scoped_ptr<ThreadWrapper> stats_polling_thread_;
567 const rtc::scoped_ptr<EventWrapper> comparison_available_event_; 558 const rtc::scoped_ptr<EventWrapper> comparison_available_event_;
568 std::deque<FrameComparison> comparisons_ GUARDED_BY(comparison_lock_); 559 std::deque<FrameComparison> comparisons_ GUARDED_BY(comparison_lock_);
569 const rtc::scoped_ptr<EventWrapper> done_; 560 const rtc::scoped_ptr<EventWrapper> done_;
570 }; 561 };
571 562
572 void FullStackTest::RunTest(const FullStackTestParams& params) { 563 VideoQualityTest::VideoQualityTest() : clock_(Clock::GetRealTimeClock()) {}
573 // TODO(ivica): Add num_temporal_layers as a param.
574 unsigned char num_temporal_layers =
575 params.graph_data_output_filename.empty() ? 2 : 1;
576 564
577 test::DirectTransport send_transport(params.link); 565 void VideoQualityTest::ValidateParams(const Params& params) {
578 test::DirectTransport recv_transport(params.link); 566 RTC_CHECK_GE(params.common.max_bitrate_bps, params.common.target_bitrate_bps);
579 VideoAnalyzer analyzer(nullptr, &send_transport, params.test_label, 567 RTC_CHECK_GE(params.common.target_bitrate_bps, params.common.min_bitrate_bps);
580 params.avg_psnr_threshold, params.avg_ssim_threshold, 568 RTC_CHECK_LT(params.common.tl_discard_threshold,
581 params.test_durations_secs * params.clip.fps, 569 params.common.num_temporal_layers);
582 params.graph_data_output_filename); 570 }
583 571
584 CreateCalls(Call::Config(), Call::Config()); 572 void VideoQualityTest::TestBody() {}
573
574 void VideoQualityTest::SetupFullStack(const Params& params,
575 newapi::Transport* send_transport,
576 newapi::Transport* recv_transport) {
577 if (params.logs)
578 trace_to_stderr_.reset(new test::TraceToStderr);
579
580 CreateSendConfig(1, send_transport);
581
582 int payload_type;
583 if (params.common.codec == "VP8") {
584 encoder_.reset(VideoEncoder::Create(VideoEncoder::kVp8));
585 payload_type = kPayloadTypeVP8;
586 } else if (params.common.codec == "VP9") {
587 encoder_.reset(VideoEncoder::Create(VideoEncoder::kVp9));
588 payload_type = kPayloadTypeVP9;
589 } else {
590 RTC_NOTREACHED() << "Codec not supported!";
591 return;
592 }
593 send_config_.encoder_settings.encoder = encoder_.get();
594 send_config_.encoder_settings.payload_name = params.common.codec;
595 send_config_.encoder_settings.payload_type = payload_type;
596
597 send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
598 send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
599 send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
600
601 // Automatically fill out streams[0] with params.
602 VideoStream* stream = &encoder_config_.streams[0];
603 stream->width = params.common.width;
604 stream->height = params.common.height;
605 stream->min_bitrate_bps = params.common.min_bitrate_bps;
606 stream->target_bitrate_bps = params.common.target_bitrate_bps;
607 stream->max_bitrate_bps = params.common.max_bitrate_bps;
608 stream->max_framerate = static_cast<int>(params.common.fps);
609
610 stream->temporal_layer_thresholds_bps.clear();
611 if (params.common.num_temporal_layers > 1) {
612 stream->temporal_layer_thresholds_bps.push_back(stream->target_bitrate_bps);
613 }
614
615 CreateMatchingReceiveConfigs(recv_transport);
616
617 receive_configs_[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
618 receive_configs_[0].rtp.rtx[kSendRtxPayloadType].ssrc = kSendRtxSsrcs[0];
619 receive_configs_[0].rtp.rtx[kSendRtxPayloadType].payload_type =
620 kSendRtxPayloadType;
621
622 encoder_config_.min_transmit_bitrate_bps = params.common.min_transmit_bps;
623 }
624
625 void VideoQualityTest::SetupScreenshare(const Params& params) {
626 RTC_CHECK(params.screenshare.enabled);
627
628 // Fill out codec settings.
629 encoder_config_.content_type = VideoEncoderConfig::ContentType::kScreen;
630 if (params.common.codec == "VP8") {
631 codec_settings_.VP8 = VideoEncoder::GetDefaultVp8Settings();
632 codec_settings_.VP8.denoisingOn = false;
633 codec_settings_.VP8.frameDroppingOn = false;
634 codec_settings_.VP8.numberOfTemporalLayers =
635 static_cast<unsigned char>(params.common.num_temporal_layers);
636 encoder_config_.encoder_specific_settings = &codec_settings_.VP8;
637 } else if (params.common.codec == "VP9") {
638 codec_settings_.VP9 = VideoEncoder::GetDefaultVp9Settings();
639 codec_settings_.VP9.denoisingOn = false;
640 codec_settings_.VP9.frameDroppingOn = false;
641 codec_settings_.VP9.numberOfTemporalLayers =
642 static_cast<unsigned char>(params.common.num_temporal_layers);
643 encoder_config_.encoder_specific_settings = &codec_settings_.VP9;
644 }
645
646 // Setup frame generator.
647 const size_t kWidth = 1850;
648 const size_t kHeight = 1110;
649 std::vector<std::string> slides;
650 slides.push_back(test::ResourcePath("web_screenshot_1850_1110", "yuv"));
651 slides.push_back(test::ResourcePath("presentation_1850_1110", "yuv"));
652 slides.push_back(test::ResourcePath("photo_1850_1110", "yuv"));
653 slides.push_back(test::ResourcePath("difficult_photo_1850_1110", "yuv"));
654
655 if (params.screenshare.scroll_duration == 0) {
656 // Cycle image every slide_change_interval seconds.
657 frame_generator_.reset(test::FrameGenerator::CreateFromYuvFile(
658 slides, kWidth, kHeight,
659 params.screenshare.slide_change_interval * params.common.fps));
660 } else {
661 RTC_CHECK_LE(params.common.width, kWidth);
662 RTC_CHECK_LE(params.common.height, kHeight);
663 RTC_CHECK_GT(params.screenshare.slide_change_interval, 0);
664 const int kPauseDurationMs = (params.screenshare.slide_change_interval -
665 params.screenshare.scroll_duration) * 1000;
666 RTC_CHECK_LE(params.screenshare.scroll_duration,
667 params.screenshare.slide_change_interval);
668
669 frame_generator_.reset(
670 test::FrameGenerator::CreateScrollingInputFromYuvFiles(
671 clock_, slides, kWidth, kHeight, params.common.width,
672 params.common.height, params.screenshare.scroll_duration * 1000,
673 kPauseDurationMs));
674 }
675 }
676
677 void VideoQualityTest::CreateCapturer(const Params& params,
678 VideoCaptureInput* input) {
679 if (params.screenshare.enabled) {
680 frame_generator_capturer_.reset(new test::FrameGeneratorCapturer(
681 clock_, input, frame_generator_.release(), params.common.fps));
682 EXPECT_TRUE(frame_generator_capturer_->Init());
683 } else {
684 if (params.video.clip_name.empty()) {
685 frame_generator_capturer_.reset(test::FrameGeneratorCapturer::Create(
686 input, params.common.width, params.common.height, params.common.fps,
687 clock_));
688 EXPECT_TRUE(frame_generator_capturer_->Init());
689 } else {
690 frame_generator_capturer_.reset(
691 test::FrameGeneratorCapturer::CreateFromYuvFile(
692 input, test::ResourcePath(params.video.clip_name, "yuv"),
693 params.common.width, params.common.height, params.common.fps,
694 clock_));
695 ASSERT_TRUE(frame_generator_capturer_.get() != nullptr)
696 << "Could not create capturer for " << params.video.clip_name
697 << ".yuv. Is this resource file present?";
698 }
699 }
700 }
701
702 void VideoQualityTest::RunWithAnalyzer(const Params& params) {
703 // TODO(ivica): Merge with RunWithRenderer and use a flag / argument to
704 // differentiate between the analyzer and the renderer case.
705 ValidateParams(params);
706
707 FILE* graph_data_output_file = nullptr;
708 if (!params.analyzer.graph_data_output_filename.empty()) {
709 graph_data_output_file =
710 fopen(params.analyzer.graph_data_output_filename.c_str(), "w");
711 RTC_CHECK(graph_data_output_file != nullptr)
712 << "Can't open the file "
713 << params.analyzer.graph_data_output_filename << "!";
714 }
715
716 test::LayerFilteringTransport send_transport(
717 params.pipe, kPayloadTypeVP8, kPayloadTypeVP9,
718 static_cast<uint8_t>(params.common.tl_discard_threshold), 0);
719 test::DirectTransport recv_transport(params.pipe);
720 VideoAnalyzer analyzer(
721 nullptr, &send_transport, params.analyzer.test_label,
722 params.analyzer.avg_psnr_threshold, params.analyzer.avg_ssim_threshold,
723 params.analyzer.test_durations_secs * params.common.fps,
724 graph_data_output_file);
725
726 Call::Config call_config;
727 call_config.bitrate_config = params.common.call_bitrate_config;
728 CreateCalls(call_config, call_config);
585 729
586 analyzer.SetReceiver(receiver_call_->Receiver()); 730 analyzer.SetReceiver(receiver_call_->Receiver());
587 send_transport.SetReceiver(&analyzer); 731 send_transport.SetReceiver(&analyzer);
588 recv_transport.SetReceiver(sender_call_->Receiver()); 732 recv_transport.SetReceiver(sender_call_->Receiver());
589 733
590 CreateSendConfig(1, &analyzer); 734 SetupFullStack(params, &analyzer, &recv_transport);
591
592 rtc::scoped_ptr<VideoEncoder> encoder;
593 if (params.codec == "VP8") {
594 encoder =
595 rtc::scoped_ptr<VideoEncoder>(VideoEncoder::Create(VideoEncoder::kVp8));
596 send_config_.encoder_settings.encoder = encoder.get();
597 send_config_.encoder_settings.payload_name = "VP8";
598 } else if (params.codec == "VP9") {
599 encoder =
600 rtc::scoped_ptr<VideoEncoder>(VideoEncoder::Create(VideoEncoder::kVp9));
601 send_config_.encoder_settings.encoder = encoder.get();
602 send_config_.encoder_settings.payload_name = "VP9";
603 } else {
604 RTC_NOTREACHED() << "Codec not supported!";
605 return;
606 }
607 send_config_.encoder_settings.payload_type = 124;
608
609 send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
610 send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
611 send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
612
613 VideoStream* stream = &encoder_config_.streams[0];
614 stream->width = params.clip.width;
615 stream->height = params.clip.height;
616 stream->min_bitrate_bps = params.min_bitrate_bps;
617 stream->target_bitrate_bps = params.target_bitrate_bps;
618 stream->max_bitrate_bps = params.max_bitrate_bps;
619 stream->max_framerate = params.clip.fps;
620
621 VideoCodecVP8 vp8_settings;
622 VideoCodecVP9 vp9_settings;
623 if (params.mode == ContentMode::kScreensharingStaticImage ||
624 params.mode == ContentMode::kScreensharingScrollingImage) {
625 encoder_config_.content_type = VideoEncoderConfig::ContentType::kScreen;
626 encoder_config_.min_transmit_bitrate_bps = 400 * 1000;
627 if (params.codec == "VP8") {
628 vp8_settings = VideoEncoder::GetDefaultVp8Settings();
629 vp8_settings.denoisingOn = false;
630 vp8_settings.frameDroppingOn = false;
631 vp8_settings.numberOfTemporalLayers = num_temporal_layers;
632 encoder_config_.encoder_specific_settings = &vp8_settings;
633 } else if (params.codec == "VP9") {
634 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
635 vp9_settings.denoisingOn = false;
636 vp9_settings.frameDroppingOn = false;
637 vp9_settings.numberOfTemporalLayers = num_temporal_layers;
638 encoder_config_.encoder_specific_settings = &vp9_settings;
639 }
640
641 stream->temporal_layer_thresholds_bps.clear();
642 if (num_temporal_layers > 1) {
643 stream->temporal_layer_thresholds_bps.push_back(
644 stream->target_bitrate_bps);
645 }
646 }
647
648 CreateMatchingReceiveConfigs(&recv_transport);
649 receive_configs_[0].renderer = &analyzer; 735 receive_configs_[0].renderer = &analyzer;
650 receive_configs_[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
651 receive_configs_[0].rtp.rtx[kSendRtxPayloadType].ssrc = kSendRtxSsrcs[0];
652 receive_configs_[0].rtp.rtx[kSendRtxPayloadType].payload_type =
653 kSendRtxPayloadType;
654
655 for (auto& config : receive_configs_) 736 for (auto& config : receive_configs_)
656 config.pre_decode_callback = &analyzer; 737 config.pre_decode_callback = &analyzer;
738
739 if (params.screenshare.enabled)
740 SetupScreenshare(params);
741
742 CreateCapturer(params, &analyzer);
743
657 CreateStreams(); 744 CreateStreams();
658 analyzer.input_ = send_stream_->Input(); 745 analyzer.input_ = send_stream_->Input();
659 analyzer.send_stream_ = send_stream_; 746 analyzer.send_stream_ = send_stream_;
660 747
661 std::vector<std::string> slides;
662 slides.push_back(test::ResourcePath("web_screenshot_1850_1110", "yuv"));
663 slides.push_back(test::ResourcePath("presentation_1850_1110", "yuv"));
664 slides.push_back(test::ResourcePath("photo_1850_1110", "yuv"));
665 slides.push_back(test::ResourcePath("difficult_photo_1850_1110", "yuv"));
666 size_t kSlidesWidth = 1850;
667 size_t kSlidesHeight = 1110;
668
669 Clock* clock = Clock::GetRealTimeClock();
670 rtc::scoped_ptr<test::FrameGenerator> frame_generator;
671
672 switch (params.mode) {
673 case ContentMode::kRealTimeVideo:
674 frame_generator.reset(test::FrameGenerator::CreateFromYuvFile(
675 std::vector<std::string>(1,
676 test::ResourcePath(params.clip.name, "yuv")),
677 params.clip.width, params.clip.height, 1));
678 break;
679 case ContentMode::kScreensharingScrollingImage:
680 frame_generator.reset(
681 test::FrameGenerator::CreateScrollingInputFromYuvFiles(
682 clock, slides, kSlidesWidth, kSlidesHeight, params.clip.width,
683 params.clip.height, 2000,
684 8000)); // Scroll for 2 seconds, then pause for 8.
685 break;
686 case ContentMode::kScreensharingStaticImage:
687 frame_generator.reset(test::FrameGenerator::CreateFromYuvFile(
688 slides, kSlidesWidth, kSlidesHeight,
689 10 * params.clip.fps)); // Cycle image every 10 seconds.
690 break;
691 }
692
693 ASSERT_TRUE(frame_generator.get() != nullptr);
694 frame_generator_capturer_.reset(new test::FrameGeneratorCapturer(
695 clock, &analyzer, frame_generator.release(), params.clip.fps));
696 ASSERT_TRUE(frame_generator_capturer_->Init());
697
698 Start(); 748 Start();
699 749
700 analyzer.Wait(); 750 analyzer.Wait();
701 751
702 send_transport.StopSending(); 752 send_transport.StopSending();
703 recv_transport.StopSending(); 753 recv_transport.StopSending();
704 754
705 Stop(); 755 Stop();
706 756
707 DestroyStreams(); 757 DestroyStreams();
758
759 if (graph_data_output_file)
760 fclose(graph_data_output_file);
708 } 761 }
709 762
710 TEST_F(FullStackTest, ParisQcifWithoutPacketLoss) { 763 void VideoQualityTest::RunWithVideoRenderer(const Params& params) {
711 FullStackTestParams paris_qcif = {"net_delay_0_0_plr_0", 764 ValidateParams(params);
712 {"paris_qcif", 176, 144, 30}, 765
713 ContentMode::kRealTimeVideo, 766 rtc::scoped_ptr<test::VideoRenderer> local_preview(
714 300000, 767 test::VideoRenderer::Create("Local Preview", params.common.width,
715 300000, 768 params.common.height));
716 300000, 769 rtc::scoped_ptr<test::VideoRenderer> loopback_video(
717 36.0, 770 test::VideoRenderer::Create("Loopback Video", params.common.width,
718 0.96, 771 params.common.height));
719 kFullStackTestDurationSecs, 772
720 "VP8"}; 773 // TODO(ivica): Remove bitrate_config and use the default Call::Config(), to
721 RunTest(paris_qcif); 774 // match the full stack tests.
775 Call::Config call_config;
776 call_config.bitrate_config = params.common.call_bitrate_config;
777 rtc::scoped_ptr<Call> call(Call::Create(call_config));
778
779 test::LayerFilteringTransport transport(
780 params.pipe, kPayloadTypeVP8, kPayloadTypeVP9,
781 static_cast<uint8_t>(params.common.tl_discard_threshold), 0);
782 // TODO(ivica): Use two calls to be able to merge with RunWithAnalyzer or at
783 // least share as much code as possible. That way this test would also match
784 // the full stack tests better.
785 transport.SetReceiver(call->Receiver());
786
787 SetupFullStack(params, &transport, &transport);
788 send_config_.local_renderer = local_preview.get();
789 receive_configs_[0].renderer = loopback_video.get();
790
791 if (params.screenshare.enabled)
792 SetupScreenshare(params);
793
794 send_stream_ = call->CreateVideoSendStream(send_config_, encoder_config_);
795 CreateCapturer(params, send_stream_->Input());
796
797 VideoReceiveStream* receive_stream =
798 call->CreateVideoReceiveStream(receive_configs_[0]);
799
800 receive_stream->Start();
801 send_stream_->Start();
802 frame_generator_capturer_->Start();
803
804 test::PressEnterToContinue();
805
806 frame_generator_capturer_->Stop();
807 send_stream_->Stop();
808 receive_stream->Stop();
809
810 call->DestroyVideoReceiveStream(receive_stream);
811 call->DestroyVideoSendStream(send_stream_);
812
813 transport.StopSending();
722 } 814 }
723 815
724 TEST_F(FullStackTest, ForemanCifWithoutPacketLoss) {
725 // TODO(pbos): Decide on psnr/ssim thresholds for foreman_cif.
726 FullStackTestParams foreman_cif = {"foreman_cif_net_delay_0_0_plr_0",
727 {"foreman_cif", 352, 288, 30},
728 ContentMode::kRealTimeVideo,
729 700000,
730 700000,
731 700000,
732 0.0,
733 0.0,
734 kFullStackTestDurationSecs,
735 "VP8"};
736 RunTest(foreman_cif);
737 }
738
739 TEST_F(FullStackTest, ForemanCifPlr5) {
740 FullStackTestParams foreman_cif = {"foreman_cif_delay_50_0_plr_5",
741 {"foreman_cif", 352, 288, 30},
742 ContentMode::kRealTimeVideo,
743 30000,
744 500000,
745 2000000,
746 0.0,
747 0.0,
748 kFullStackTestDurationSecs,
749 "VP8"};
750 foreman_cif.link.loss_percent = 5;
751 foreman_cif.link.queue_delay_ms = 50;
752 RunTest(foreman_cif);
753 }
754
755 TEST_F(FullStackTest, ForemanCif500kbps) {
756 FullStackTestParams foreman_cif = {"foreman_cif_500kbps",
757 {"foreman_cif", 352, 288, 30},
758 ContentMode::kRealTimeVideo,
759 30000,
760 500000,
761 2000000,
762 0.0,
763 0.0,
764 kFullStackTestDurationSecs,
765 "VP8"};
766 foreman_cif.link.queue_length_packets = 0;
767 foreman_cif.link.queue_delay_ms = 0;
768 foreman_cif.link.link_capacity_kbps = 500;
769 RunTest(foreman_cif);
770 }
771
772 TEST_F(FullStackTest, ForemanCif500kbpsLimitedQueue) {
773 FullStackTestParams foreman_cif = {"foreman_cif_500kbps_32pkts_queue",
774 {"foreman_cif", 352, 288, 30},
775 ContentMode::kRealTimeVideo,
776 30000,
777 500000,
778 2000000,
779 0.0,
780 0.0,
781 kFullStackTestDurationSecs,
782 "VP8"};
783 foreman_cif.link.queue_length_packets = 32;
784 foreman_cif.link.queue_delay_ms = 0;
785 foreman_cif.link.link_capacity_kbps = 500;
786 RunTest(foreman_cif);
787 }
788
789 TEST_F(FullStackTest, ForemanCif500kbps100ms) {
790 FullStackTestParams foreman_cif = {"foreman_cif_500kbps_100ms",
791 {"foreman_cif", 352, 288, 30},
792 ContentMode::kRealTimeVideo,
793 30000,
794 500000,
795 2000000,
796 0.0,
797 0.0,
798 kFullStackTestDurationSecs,
799 "VP8"};
800 foreman_cif.link.queue_length_packets = 0;
801 foreman_cif.link.queue_delay_ms = 100;
802 foreman_cif.link.link_capacity_kbps = 500;
803 RunTest(foreman_cif);
804 }
805
806 TEST_F(FullStackTest, ForemanCif500kbps100msLimitedQueue) {
807 FullStackTestParams foreman_cif = {"foreman_cif_500kbps_100ms_32pkts_queue",
808 {"foreman_cif", 352, 288, 30},
809 ContentMode::kRealTimeVideo,
810 30000,
811 500000,
812 2000000,
813 0.0,
814 0.0,
815 kFullStackTestDurationSecs,
816 "VP8"};
817 foreman_cif.link.queue_length_packets = 32;
818 foreman_cif.link.queue_delay_ms = 100;
819 foreman_cif.link.link_capacity_kbps = 500;
820 RunTest(foreman_cif);
821 }
822
823 TEST_F(FullStackTest, ForemanCif1000kbps100msLimitedQueue) {
824 FullStackTestParams foreman_cif = {"foreman_cif_1000kbps_100ms_32pkts_queue",
825 {"foreman_cif", 352, 288, 30},
826 ContentMode::kRealTimeVideo,
827 30000,
828 2000000,
829 2000000,
830 0.0,
831 0.0,
832 kFullStackTestDurationSecs,
833 "VP8"};
834 foreman_cif.link.queue_length_packets = 32;
835 foreman_cif.link.queue_delay_ms = 100;
836 foreman_cif.link.link_capacity_kbps = 1000;
837 RunTest(foreman_cif);
838 }
839
840 // Temporarily disabled on Android due to low test timeouts.
841 // https://code.google.com/p/chromium/issues/detail?id=513170
842 #include "webrtc/test/testsupport/gtest_disable.h"
843 TEST_F(FullStackTest, DISABLED_ON_ANDROID(ScreenshareSlidesVP8_2TL)) {
844 FullStackTestParams screenshare_params = {
845 "screenshare_slides",
846 {"screenshare_slides", 1850, 1110, 5},
847 ContentMode::kScreensharingStaticImage,
848 50000,
849 200000,
850 2000000,
851 0.0,
852 0.0,
853 kFullStackTestDurationSecs,
854 "VP8"};
855 RunTest(screenshare_params);
856 }
857
858 TEST_F(FullStackTest, DISABLED_ON_ANDROID(ScreenshareSlidesVP8_2TL_Scroll)) {
859 FullStackTestParams screenshare_params = {
860 "screenshare_slides_scrolling",
861 // Crop height by two, scrolling vertically only.
862 {"screenshare_slides_scrolling", 1850, 1110 / 2, 5},
863 ContentMode::kScreensharingScrollingImage,
864 50000,
865 200000,
866 2000000,
867 0.0,
868 0.0,
869 kFullStackTestDurationSecs,
870 "VP8"};
871 RunTest(screenshare_params);
872 }
873
874 // Disabled on Android along with VP8 screenshare above.
875 TEST_F(FullStackTest, DISABLED_ON_ANDROID(ScreenshareSlidesVP9_2TL)) {
876 FullStackTestParams screenshare_params = {
877 "screenshare_slides_vp9_2tl",
878 {"screenshare_slides", 1850, 1110, 5},
879 ContentMode::kScreensharingStaticImage,
880 50000,
881 200000,
882 2000000,
883 0.0,
884 0.0,
885 kFullStackTestDurationSecs,
886 "VP9"};
887 RunTest(screenshare_params);
888 }
889 } // namespace webrtc 816 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/video/video_quality_test.h ('k') | webrtc/webrtc_tests.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698