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

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: Removing a comment. 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
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 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 157
162 return transport_->SendRtp(packet, length); 158 return transport_->SendRtp(packet, length);
163 } 159 }
164 160
165 bool SendRtcp(const uint8_t* packet, size_t length) override { 161 bool SendRtcp(const uint8_t* packet, size_t length) override {
166 return transport_->SendRtcp(packet, length); 162 return transport_->SendRtcp(packet, length);
167 } 163 }
168 164
169 void EncodedFrameCallback(const EncodedFrame& frame) override { 165 void EncodedFrameCallback(const EncodedFrame& frame) override {
170 rtc::CritScope lock(&comparison_lock_); 166 rtc::CritScope lock(&comparison_lock_);
171 if (frames_recorded_ < frames_to_process_) 167 if (frames_recorded_ < frames_to_process_) {
pbos-webrtc 2015/09/16 12:02:33 Remove {}s
ivica 2015/09/16 12:51:21 Done.
172 encoded_frame_size_.AddSample(frame.length_); 168 encoded_frame_size_.AddSample(frame.length_);
169 }
173 } 170 }
174 171
175 void RenderFrame(const VideoFrame& video_frame, 172 void RenderFrame(const VideoFrame& video_frame,
176 int time_to_render_ms) override { 173 int time_to_render_ms) override {
177 int64_t render_time_ms = 174 int64_t render_time_ms =
178 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds(); 175 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds();
179 uint32_t send_timestamp = video_frame.timestamp() - rtp_timestamp_delta_; 176 uint32_t send_timestamp = video_frame.timestamp() - rtp_timestamp_delta_;
180 177
181 rtc::CritScope lock(&crit_); 178 rtc::CritScope lock(&crit_);
182 179
(...skipping 17 matching lines...) Expand all
200 bool IsTextureSupported() const override { return false; } 197 bool IsTextureSupported() const override { return false; }
201 198
202 void Wait() { 199 void Wait() {
203 // Frame comparisons can be very expensive. Wait for test to be done, but 200 // 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 201 // 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. 202 // time, otherwise fail. Hopefully this will reduce test flakiness.
206 203
207 int last_frames_processed = -1; 204 int last_frames_processed = -1;
208 EventTypeWrapper eventType; 205 EventTypeWrapper eventType;
209 int iteration = 0; 206 int iteration = 0;
210 while ((eventType = done_->Wait(FullStackTest::kDefaultTimeoutMs)) != 207 while ((eventType = done_->Wait(VideoQualityTest::kDefaultTimeoutMs)) !=
211 kEventSignaled) { 208 kEventSignaled) {
212 int frames_processed; 209 int frames_processed;
213 { 210 {
214 rtc::CritScope crit(&comparison_lock_); 211 rtc::CritScope crit(&comparison_lock_);
215 frames_processed = frames_processed_; 212 frames_processed = frames_processed_;
216 } 213 }
217 214
218 // Print some output so test infrastructure won't think we've crashed. 215 // Print some output so test infrastructure won't think we've crashed.
219 const char* kKeepAliveMessages[3] = { 216 const char* kKeepAliveMessages[3] = {
220 "Uh, I'm-I'm not quite dead, sir.", 217 "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(); 376 comparison_available_event_->Set();
380 return false; 377 return false;
381 } 378 }
382 return true; // Try again. 379 return true; // Try again.
383 } 380 }
384 381
385 PerformFrameComparison(comparison); 382 PerformFrameComparison(comparison);
386 383
387 if (FrameProcessed()) { 384 if (FrameProcessed()) {
388 PrintResults(); 385 PrintResults();
389 if (!graph_data_output_filename_.empty()) 386 if (graph_data_output_file_)
390 PrintSamplesToFile(); 387 PrintSamplesToFile();
391 done_->Set(); 388 done_->Set();
392 comparison_available_event_->Set(); 389 comparison_available_event_->Set();
393 return false; 390 return false;
394 } 391 }
395 392
396 return true; 393 return true;
397 } 394 }
398 395
399 bool PopComparison(FrameComparison* comparison) { 396 bool PopComparison(FrameComparison* comparison) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 ++frames_processed_; 430 ++frames_processed_;
434 assert(frames_processed_ <= frames_to_process_); 431 assert(frames_processed_ <= frames_to_process_);
435 return frames_processed_ == frames_to_process_; 432 return frames_processed_ == frames_to_process_;
436 } 433 }
437 434
438 void PrintResults() { 435 void PrintResults() {
439 rtc::CritScope crit(&comparison_lock_); 436 rtc::CritScope crit(&comparison_lock_);
440 PrintResult("psnr", psnr_, " dB"); 437 PrintResult("psnr", psnr_, " dB");
441 PrintResult("ssim", ssim_, ""); 438 PrintResult("ssim", ssim_, "");
442 PrintResult("sender_time", sender_time_, " ms"); 439 PrintResult("sender_time", sender_time_, " ms");
443 printf("RESULT dropped_frames: %s = %d frames\n", test_label_, 440 printf("RESULT dropped_frames: %s = %d frames\n", test_label_.c_str(),
444 dropped_frames_); 441 dropped_frames_);
445 PrintResult("receiver_time", receiver_time_, " ms"); 442 PrintResult("receiver_time", receiver_time_, " ms");
446 PrintResult("total_delay_incl_network", end_to_end_, " ms"); 443 PrintResult("total_delay_incl_network", end_to_end_, " ms");
447 PrintResult("time_between_rendered_frames", rendered_delta_, " ms"); 444 PrintResult("time_between_rendered_frames", rendered_delta_, " ms");
448 PrintResult("encoded_frame_size", encoded_frame_size_, " bytes"); 445 PrintResult("encoded_frame_size", encoded_frame_size_, " bytes");
449 PrintResult("encode_frame_rate", encode_frame_rate_, " fps"); 446 PrintResult("encode_frame_rate", encode_frame_rate_, " fps");
450 PrintResult("encode_time", encode_time_ms, " ms"); 447 PrintResult("encode_time", encode_time_ms, " ms");
451 PrintResult("encode_usage_percent", encode_usage_percent, " percent"); 448 PrintResult("encode_usage_percent", encode_usage_percent, " percent");
452 PrintResult("media_bitrate", media_bitrate_bps, " bps"); 449 PrintResult("media_bitrate", media_bitrate_bps, " bps");
453 450
454 EXPECT_GT(psnr_.Mean(), avg_psnr_threshold_); 451 EXPECT_GT(psnr_.Mean(), avg_psnr_threshold_);
455 EXPECT_GT(ssim_.Mean(), avg_ssim_threshold_); 452 EXPECT_GT(ssim_.Mean(), avg_ssim_threshold_);
456 } 453 }
457 454
458 void PerformFrameComparison(const FrameComparison& comparison) { 455 void PerformFrameComparison(const FrameComparison& comparison) {
459 // Perform expensive psnr and ssim calculations while not holding lock. 456 // Perform expensive psnr and ssim calculations while not holding lock.
460 double psnr = I420PSNR(&comparison.reference, &comparison.render); 457 double psnr = I420PSNR(&comparison.reference, &comparison.render);
461 double ssim = I420SSIM(&comparison.reference, &comparison.render); 458 double ssim = I420SSIM(&comparison.reference, &comparison.render);
462 459
463 int64_t input_time_ms = comparison.reference.ntp_time_ms(); 460 int64_t input_time_ms = comparison.reference.ntp_time_ms();
464 461
465 rtc::CritScope crit(&comparison_lock_); 462 rtc::CritScope crit(&comparison_lock_);
466 if (!graph_data_output_filename_.empty()) { 463 if (graph_data_output_file_) {
467 samples_.push_back(Sample( 464 samples_.push_back(Sample(
468 comparison.dropped, input_time_ms, comparison.send_time_ms, 465 comparison.dropped, input_time_ms, comparison.send_time_ms,
469 comparison.recv_time_ms, comparison.encoded_frame_size, psnr, ssim, 466 comparison.recv_time_ms, comparison.encoded_frame_size, psnr, ssim,
470 comparison.render_time_ms)); 467 comparison.render_time_ms));
471 } 468 }
472 psnr_.AddSample(psnr); 469 psnr_.AddSample(psnr);
473 ssim_.AddSample(ssim); 470 ssim_.AddSample(ssim);
474 471
475 if (comparison.dropped) { 472 if (comparison.dropped) {
476 ++dropped_frames_; 473 ++dropped_frames_;
477 return; 474 return;
478 } 475 }
479 if (last_render_time_ != 0) 476 if (last_render_time_ != 0)
480 rendered_delta_.AddSample(comparison.render_time_ms - last_render_time_); 477 rendered_delta_.AddSample(comparison.render_time_ms - last_render_time_);
481 last_render_time_ = comparison.render_time_ms; 478 last_render_time_ = comparison.render_time_ms;
482 479
483 sender_time_.AddSample(comparison.send_time_ms - input_time_ms); 480 sender_time_.AddSample(comparison.send_time_ms - input_time_ms);
484 receiver_time_.AddSample(comparison.render_time_ms - 481 receiver_time_.AddSample(comparison.render_time_ms -
485 comparison.recv_time_ms); 482 comparison.recv_time_ms);
486 end_to_end_.AddSample(comparison.render_time_ms - input_time_ms); 483 end_to_end_.AddSample(comparison.render_time_ms - input_time_ms);
487 encoded_frame_size_.AddSample(comparison.encoded_frame_size); 484 encoded_frame_size_.AddSample(comparison.encoded_frame_size);
488 } 485 }
489 486
490 void PrintResult(const char* result_type, 487 void PrintResult(const char* result_type,
491 test::Statistics stats, 488 test::Statistics stats,
492 const char* unit) { 489 const char* unit) {
493 printf("RESULT %s: %s = {%f, %f}%s\n", 490 printf("RESULT %s: %s = {%f, %f}%s\n",
494 result_type, 491 result_type,
495 test_label_, 492 test_label_.c_str(),
496 stats.Mean(), 493 stats.Mean(),
497 stats.StandardDeviation(), 494 stats.StandardDeviation(),
498 unit); 495 unit);
499 } 496 }
500 497
501 void PrintSamplesToFile(void) { 498 void PrintSamplesToFile(void) {
502 FILE* out = fopen(graph_data_output_filename_.c_str(), "w"); 499 FILE* out = graph_data_output_file_;
503 CHECK(out != nullptr)
504 << "Couldn't open file: " << graph_data_output_filename_;
505
506 rtc::CritScope crit(&comparison_lock_); 500 rtc::CritScope crit(&comparison_lock_);
507 std::sort(samples_.begin(), samples_.end(), 501 std::sort(samples_.begin(), samples_.end(),
508 [](const Sample& A, const Sample& B) 502 [](const Sample& A, const Sample& B) -> bool {
509 -> bool { return A.input_time_ms < B.input_time_ms; }); 503 return A.input_time_ms < B.input_time_ms;
504 });
510 505
511 fprintf(out, "%s\n", test_label_); 506 fprintf(out, "%s\n", test_label_.c_str());
512 fprintf(out, "%" PRIuS "\n", samples_.size()); 507 fprintf(out, "%" PRIuS "\n", samples_.size());
513 fprintf(out, 508 fprintf(out,
514 "dropped " 509 "dropped "
515 "input_time_ms " 510 "input_time_ms "
516 "send_time_ms " 511 "send_time_ms "
517 "recv_time_ms " 512 "recv_time_ms "
518 "encoded_frame_size " 513 "encoded_frame_size "
519 "psnr " 514 "psnr "
520 "ssim " 515 "ssim "
521 "render_time_ms\n"); 516 "render_time_ms\n");
522 for (const Sample& sample : samples_) { 517 for (const Sample& sample : samples_) {
523 fprintf(out, "%lf %lf %lf %lf %lf %lf %lf %lf\n", sample.dropped, 518 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, 519 sample.input_time_ms, sample.send_time_ms, sample.recv_time_ms,
525 sample.encoded_frame_size, sample.psnr, sample.ssim, 520 sample.encoded_frame_size, sample.psnr, sample.ssim,
526 sample.render_time_ms); 521 sample.render_time_ms);
527 } 522 }
528 fclose(out);
529 } 523 }
530 524
531 const char* const test_label_; 525 const std::string test_label_;
532 std::string graph_data_output_filename_; 526 FILE* const graph_data_output_file_;
533 std::vector<Sample> samples_ GUARDED_BY(comparison_lock_); 527 std::vector<Sample> samples_ GUARDED_BY(comparison_lock_);
534 test::Statistics sender_time_ GUARDED_BY(comparison_lock_); 528 test::Statistics sender_time_ GUARDED_BY(comparison_lock_);
535 test::Statistics receiver_time_ GUARDED_BY(comparison_lock_); 529 test::Statistics receiver_time_ GUARDED_BY(comparison_lock_);
536 test::Statistics psnr_ GUARDED_BY(comparison_lock_); 530 test::Statistics psnr_ GUARDED_BY(comparison_lock_);
537 test::Statistics ssim_ GUARDED_BY(comparison_lock_); 531 test::Statistics ssim_ GUARDED_BY(comparison_lock_);
538 test::Statistics end_to_end_ GUARDED_BY(comparison_lock_); 532 test::Statistics end_to_end_ GUARDED_BY(comparison_lock_);
539 test::Statistics rendered_delta_ GUARDED_BY(comparison_lock_); 533 test::Statistics rendered_delta_ GUARDED_BY(comparison_lock_);
540 test::Statistics encoded_frame_size_ GUARDED_BY(comparison_lock_); 534 test::Statistics encoded_frame_size_ GUARDED_BY(comparison_lock_);
541 test::Statistics encode_frame_rate_ GUARDED_BY(comparison_lock_); 535 test::Statistics encode_frame_rate_ GUARDED_BY(comparison_lock_);
542 test::Statistics encode_time_ms GUARDED_BY(comparison_lock_); 536 test::Statistics encode_time_ms GUARDED_BY(comparison_lock_);
543 test::Statistics encode_usage_percent GUARDED_BY(comparison_lock_); 537 test::Statistics encode_usage_percent GUARDED_BY(comparison_lock_);
544 test::Statistics media_bitrate_bps GUARDED_BY(comparison_lock_); 538 test::Statistics media_bitrate_bps GUARDED_BY(comparison_lock_);
545 539
546 const int frames_to_process_; 540 const int frames_to_process_;
547 int frames_recorded_; 541 int frames_recorded_;
548 int frames_processed_; 542 int frames_processed_;
549 int dropped_frames_; 543 int dropped_frames_;
550 int64_t last_render_time_; 544 int64_t last_render_time_;
551 uint32_t rtp_timestamp_delta_; 545 uint32_t rtp_timestamp_delta_;
552 546
553 rtc::CriticalSection crit_; 547 rtc::CriticalSection crit_;
554 std::deque<VideoFrame> frames_ GUARDED_BY(crit_); 548 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_); 549 VideoFrame last_rendered_frame_ GUARDED_BY(crit_);
557 std::map<uint32_t, int64_t> send_times_ GUARDED_BY(crit_); 550 std::map<uint32_t, int64_t> send_times_ GUARDED_BY(crit_);
558 std::map<uint32_t, int64_t> recv_times_ GUARDED_BY(crit_); 551 std::map<uint32_t, int64_t> recv_times_ GUARDED_BY(crit_);
559 std::map<uint32_t, size_t> encoded_frame_sizes_ GUARDED_BY(crit_); 552 std::map<uint32_t, size_t> encoded_frame_sizes_ GUARDED_BY(crit_);
560 VideoFrame first_send_frame_ GUARDED_BY(crit_); 553 VideoFrame first_send_frame_ GUARDED_BY(crit_);
561 const double avg_psnr_threshold_; 554 const double avg_psnr_threshold_;
562 const double avg_ssim_threshold_; 555 const double avg_ssim_threshold_;
563 556
564 rtc::CriticalSection comparison_lock_; 557 rtc::CriticalSection comparison_lock_;
565 std::vector<ThreadWrapper*> comparison_thread_pool_; 558 std::vector<ThreadWrapper*> comparison_thread_pool_;
566 rtc::scoped_ptr<ThreadWrapper> stats_polling_thread_; 559 rtc::scoped_ptr<ThreadWrapper> stats_polling_thread_;
567 const rtc::scoped_ptr<EventWrapper> comparison_available_event_; 560 const rtc::scoped_ptr<EventWrapper> comparison_available_event_;
568 std::deque<FrameComparison> comparisons_ GUARDED_BY(comparison_lock_); 561 std::deque<FrameComparison> comparisons_ GUARDED_BY(comparison_lock_);
569 const rtc::scoped_ptr<EventWrapper> done_; 562 const rtc::scoped_ptr<EventWrapper> done_;
570 }; 563 };
571 564
572 void FullStackTest::RunTest(const FullStackTestParams& params) {
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 565
577 test::DirectTransport send_transport(params.link); 566 VideoQualityTest::VideoQualityTest() : clock_(Clock::GetRealTimeClock()) {
578 test::DirectTransport recv_transport(params.link); 567 }
579 VideoAnalyzer analyzer(nullptr, &send_transport, params.test_label,
580 params.avg_psnr_threshold, params.avg_ssim_threshold,
581 params.test_durations_secs * params.clip.fps,
582 params.graph_data_output_filename);
583 568
584 CreateCalls(Call::Config(), Call::Config()); 569 void VideoQualityTest::ValidateParams(const Params& params) {
570 CHECK_GE(params.general.max_bitrate_bps, params.general.target_bitrate_bps);
571 CHECK_GE(params.general.target_bitrate_bps, params.general.min_bitrate_bps);
572 CHECK_LT(params.general.tl_discard_threshold,
573 params.general.num_temporal_layers);
574 }
575
576 void VideoQualityTest::TestBody() {
577 // Not used.
578 }
579
580 void VideoQualityTest::SetupFullStack(const Params& params,
581 newapi::Transport* send_transport,
582 newapi::Transport* recv_transport) {
583 if (params.logs)
584 trace_to_stderr_.reset(new test::TraceToStderr);
585
586 CreateSendConfig(1, send_transport);
587
588 int payload_type;
589 if (params.general.codec == "VP8") {
590 encoder_.reset(VideoEncoder::Create(VideoEncoder::kVp8));
591 payload_type = kPayloadTypeVP8;
592 } else if (params.general.codec == "VP9") {
593 encoder_.reset(VideoEncoder::Create(VideoEncoder::kVp9));
594 payload_type = kPayloadTypeVP9;
595 } else {
596 RTC_NOTREACHED() << "Codec not supported!";
597 return;
598 }
599 send_config_.encoder_settings.encoder = encoder_.get();
600 send_config_.encoder_settings.payload_name = params.general.codec;
601 send_config_.encoder_settings.payload_type = payload_type;
602
603 send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
604 send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
605 send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
606
607 // Automatically fill out streams[0] with params.
608 VideoStream* stream = &encoder_config_.streams[0];
609 stream->width = params.general.width;
610 stream->height = params.general.height;
611 stream->min_bitrate_bps = params.general.min_bitrate_bps;
612 stream->target_bitrate_bps = params.general.target_bitrate_bps;
613 stream->max_bitrate_bps = params.general.max_bitrate_bps;
614 stream->max_framerate = static_cast<int>(params.general.fps);
615
616 stream->temporal_layer_thresholds_bps.clear();
617 if (params.general.num_temporal_layers > 1) {
618 stream->temporal_layer_thresholds_bps.push_back(stream->target_bitrate_bps);
619 }
620
621 CreateMatchingReceiveConfigs(recv_transport);
622
623 receive_configs_[0].rtp.rtx[kSendRtxPayloadType].ssrc = kSendRtxSsrcs[0];
624 receive_configs_[0].rtp.rtx[kSendRtxPayloadType].payload_type =
625 kSendRtxPayloadType;
626
627 encoder_config_.min_transmit_bitrate_bps = params.general.min_transmit_bps;
628 }
629
630 void VideoQualityTest::SetupScreenshare(const Params& params) {
631 CHECK(params.screenshare.enabled);
632
633 // Fill out codec settings.
634 encoder_config_.content_type = VideoEncoderConfig::ContentType::kScreen;
635 if (params.general.codec == "VP8") {
636 codec_settings_.VP8 = VideoEncoder::GetDefaultVp8Settings();
637 codec_settings_.VP8.denoisingOn = false;
638 codec_settings_.VP8.frameDroppingOn = false;
639 codec_settings_.VP8.numberOfTemporalLayers =
640 static_cast<unsigned char>(params.general.num_temporal_layers);
641 encoder_config_.encoder_specific_settings = &codec_settings_.VP8;
642 } else if (params.general.codec == "VP9") {
643 codec_settings_.VP9 = VideoEncoder::GetDefaultVp9Settings();
644 codec_settings_.VP9.denoisingOn = false;
645 codec_settings_.VP9.frameDroppingOn = false;
646 codec_settings_.VP9.numberOfTemporalLayers =
647 static_cast<unsigned char>(params.general.num_temporal_layers);
648 encoder_config_.encoder_specific_settings = &codec_settings_.VP9;
649 }
650
651 // Setup frame generator.
652 const size_t kWidth = 1850;
653 const size_t kHeight = 1110;
654 std::vector<std::string> slides;
655 slides.push_back(test::ResourcePath("web_screenshot_1850_1110", "yuv"));
656 slides.push_back(test::ResourcePath("presentation_1850_1110", "yuv"));
657 slides.push_back(test::ResourcePath("photo_1850_1110", "yuv"));
658 slides.push_back(test::ResourcePath("difficult_photo_1850_1110", "yuv"));
659
660 if (params.screenshare.scroll_duration == 0) {
661 // Cycle image every slide_change_interval seconds.
662 frame_generator_.reset(test::FrameGenerator::CreateFromYuvFile(
663 slides, kWidth, kHeight,
664 params.screenshare.slide_change_interval * params.general.fps));
665 } else {
666 CHECK_LE(params.general.width, kWidth);
667 CHECK_LE(params.general.height, kHeight);
668 CHECK_GT(params.screenshare.slide_change_interval, 0);
669 const int kPauseDurationMs = (params.screenshare.slide_change_interval -
670 params.screenshare.scroll_duration) * 1000;
671 CHECK_LE(params.screenshare.scroll_duration,
672 params.screenshare.slide_change_interval);
673
674 frame_generator_.reset(
675 test::FrameGenerator::CreateScrollingInputFromYuvFiles(
676 clock_, slides, kWidth, kHeight, params.general.width,
677 params.general.height, params.screenshare.scroll_duration * 1000,
678 kPauseDurationMs));
679 }
680 }
681
682 void VideoQualityTest::CreateCapturer(const Params& params,
683 VideoCaptureInput* input) {
pbos-webrtc 2015/09/16 12:02:33 run git cl format
ivica 2015/09/16 12:51:21 Done only on video_quality_test.cc and .h, because
684 if (params.screenshare.enabled) {
685 frame_generator_capturer_.reset(new test::FrameGeneratorCapturer(
686 clock_, input, frame_generator_.release(), params.general.fps));
687 EXPECT_TRUE(frame_generator_capturer_->Init());
688 } else {
689 if (params.video.clip_name.empty()) {
690 frame_generator_capturer_.reset(
691 test::FrameGeneratorCapturer::Create(input, params.general.width,
692 params.general.height,
693 params.general.fps, clock_));
694 EXPECT_TRUE(frame_generator_capturer_->Init());
695 } else {
696 frame_generator_capturer_.reset(
697 test::FrameGeneratorCapturer::CreateFromYuvFile(
698 input, test::ResourcePath(params.video.clip_name, "yuv"),
699 params.general.width, params.general.height, params.general.fps,
700 clock_));
701 ASSERT_TRUE(frame_generator_capturer_.get() != nullptr)
702 << "Could not create capturer for " << params.video.clip_name
703 << ".yuv. Is this resource file present?";
704 }
705 }
706 }
707
708 void VideoQualityTest::RunWithAnalyzer(const Params& params) {
pbos-webrtc 2015/09/16 12:02:33 Can you do a TODO to consolidate these methods int
ivica 2015/09/16 12:51:21 Added a TODO for now. I suggest I do the merge in
709 ValidateParams(params);
710
711 FILE* graph_data_output_file = nullptr;
712 if (!params.analyzer.graph_data_output_filename.empty()) {
713 graph_data_output_file =
714 fopen(params.analyzer.graph_data_output_filename.c_str(), "w");
715 CHECK(graph_data_output_file != nullptr)
716 << "Can't open file "
717 << params.analyzer.graph_data_output_filename << "!";
718 }
719
720 test::LayerFilteringTransport send_transport(
721 params.pipe, kPayloadTypeVP8, kPayloadTypeVP9,
722 static_cast<uint8_t>(params.general.tl_discard_threshold), 0);
723 test::DirectTransport recv_transport(params.pipe);
724 VideoAnalyzer analyzer(
725 nullptr, &send_transport, params.analyzer.test_label,
726 params.analyzer.avg_psnr_threshold, params.analyzer.avg_ssim_threshold,
727 params.analyzer.test_durations_secs * params.general.fps,
728 graph_data_output_file);
729
730 Call::Config call_config;
731 call_config.bitrate_config = params.general.call_bitrate_config;
732 CreateCalls(call_config, call_config);
585 733
586 analyzer.SetReceiver(receiver_call_->Receiver()); 734 analyzer.SetReceiver(receiver_call_->Receiver());
587 send_transport.SetReceiver(&analyzer); 735 send_transport.SetReceiver(&analyzer);
588 recv_transport.SetReceiver(sender_call_->Receiver()); 736 recv_transport.SetReceiver(sender_call_->Receiver());
589 737
590 CreateSendConfig(1, &analyzer); 738 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; 739 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_) 740 for (auto& config : receive_configs_)
656 config.pre_decode_callback = &analyzer; 741 config.pre_decode_callback = &analyzer;
742
743 if (params.screenshare.enabled)
744 SetupScreenshare(params);
745
746 CreateCapturer(params, &analyzer);
747
657 CreateStreams(); 748 CreateStreams();
658 analyzer.input_ = send_stream_->Input(); 749 analyzer.input_ = send_stream_->Input();
659 analyzer.send_stream_ = send_stream_; 750 analyzer.send_stream_ = send_stream_;
660 751
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(); 752 Start();
699 753
700 analyzer.Wait(); 754 analyzer.Wait();
701 755
702 send_transport.StopSending(); 756 send_transport.StopSending();
703 recv_transport.StopSending(); 757 recv_transport.StopSending();
704 758
705 Stop(); 759 Stop();
706 760
707 DestroyStreams(); 761 DestroyStreams();
762
763 if (graph_data_output_file)
764 fclose(graph_data_output_file);
708 } 765 }
709 766
710 TEST_F(FullStackTest, ParisQcifWithoutPacketLoss) { 767 void VideoQualityTest::RunWithVideoRenderer(const Params& params) {
711 FullStackTestParams paris_qcif = {"net_delay_0_0_plr_0", 768 ValidateParams(params);
712 {"paris_qcif", 176, 144, 30}, 769
713 ContentMode::kRealTimeVideo, 770 rtc::scoped_ptr<test::VideoRenderer> local_preview(
714 300000, 771 test::VideoRenderer::Create("Local Preview", params.general.width,
715 300000, 772 params.general.height));
716 300000, 773 rtc::scoped_ptr<test::VideoRenderer> loopback_video(
717 36.0, 774 test::VideoRenderer::Create("Loopback Video", params.general.width,
718 0.96, 775 params.general.height));
719 kFullStackTestDurationSecs, 776
720 "VP8"}; 777 Call::Config call_config;
721 RunTest(paris_qcif); 778 call_config.bitrate_config = params.general.call_bitrate_config;
779 rtc::scoped_ptr<Call> call(Call::Create(call_config));
780
781 test::LayerFilteringTransport transport(
782 params.pipe, kPayloadTypeVP8, kPayloadTypeVP9,
783 static_cast<uint8_t>(params.general.tl_discard_threshold), 0);
784 // Loopback, call sends to itself.
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

Powered by Google App Engine
This is Rietveld 408576698