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

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

Issue 1412233003: Support simulcast and spatial layers in VideoQualityTest (PERF NOTE) (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Rebase + suppress log spamming Created 5 years, 1 month 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/video/video_send_stream.cc » ('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) 2015 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 <algorithm>
13 #include <deque> 13 #include <deque>
14 #include <map> 14 #include <map>
15 #include <sstream>
15 #include <vector> 16 #include <vector>
16 17
17 #include "testing/gtest/include/gtest/gtest.h" 18 #include "testing/gtest/include/gtest/gtest.h"
18 19
19 #include "webrtc/base/checks.h" 20 #include "webrtc/base/checks.h"
20 #include "webrtc/base/format_macros.h" 21 #include "webrtc/base/format_macros.h"
21 #include "webrtc/base/scoped_ptr.h" 22 #include "webrtc/base/scoped_ptr.h"
22 #include "webrtc/call.h" 23 #include "webrtc/call.h"
23 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" 24 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
24 #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" 25 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
25 #include "webrtc/system_wrappers/include/cpu_info.h" 26 #include "webrtc/system_wrappers/include/cpu_info.h"
26 #include "webrtc/test/layer_filtering_transport.h" 27 #include "webrtc/test/layer_filtering_transport.h"
27 #include "webrtc/test/run_loop.h" 28 #include "webrtc/test/run_loop.h"
28 #include "webrtc/test/statistics.h" 29 #include "webrtc/test/statistics.h"
29 #include "webrtc/test/testsupport/fileutils.h" 30 #include "webrtc/test/testsupport/fileutils.h"
30 #include "webrtc/test/video_renderer.h" 31 #include "webrtc/test/video_renderer.h"
31 #include "webrtc/video/video_quality_test.h" 32 #include "webrtc/video/video_quality_test.h"
32 33
33 namespace webrtc { 34 namespace webrtc {
34 35
35 static const int kSendStatsPollingIntervalMs = 1000; 36 static const int kSendStatsPollingIntervalMs = 1000;
36 static const int kPayloadTypeVP8 = 123; 37 static const int kPayloadTypeVP8 = 123;
37 static const int kPayloadTypeVP9 = 124; 38 static const int kPayloadTypeVP9 = 124;
38 39
39 class VideoAnalyzer : public PacketReceiver, 40 class VideoAnalyzer : public PacketReceiver,
40 public Transport, 41 public Transport,
41 public VideoRenderer, 42 public VideoRenderer,
42 public VideoCaptureInput, 43 public VideoCaptureInput,
43 public EncodedFrameObserver, 44 public EncodedFrameObserver,
44 public EncodingTimeObserver { 45 public EncodingTimeObserver {
45 public: 46 public:
46 VideoAnalyzer(Transport* transport, 47 VideoAnalyzer(test::LayerFilteringTransport* transport,
47 const std::string& test_label, 48 const std::string& test_label,
48 double avg_psnr_threshold, 49 double avg_psnr_threshold,
49 double avg_ssim_threshold, 50 double avg_ssim_threshold,
50 int duration_frames, 51 int duration_frames,
51 FILE* graph_data_output_file) 52 FILE* graph_data_output_file,
53 const std::string& graph_title,
54 uint32_t ssrc_to_analyze)
52 : input_(nullptr), 55 : input_(nullptr),
53 transport_(transport), 56 transport_(transport),
54 receiver_(nullptr), 57 receiver_(nullptr),
55 send_stream_(nullptr), 58 send_stream_(nullptr),
56 test_label_(test_label), 59 test_label_(test_label),
57 graph_data_output_file_(graph_data_output_file), 60 graph_data_output_file_(graph_data_output_file),
61 graph_title_(graph_title),
62 ssrc_to_analyze_(ssrc_to_analyze),
58 frames_to_process_(duration_frames), 63 frames_to_process_(duration_frames),
59 frames_recorded_(0), 64 frames_recorded_(0),
60 frames_processed_(0), 65 frames_processed_(0),
61 dropped_frames_(0), 66 dropped_frames_(0),
62 last_render_time_(0), 67 last_render_time_(0),
63 rtp_timestamp_delta_(0), 68 rtp_timestamp_delta_(0),
64 avg_psnr_threshold_(avg_psnr_threshold), 69 avg_psnr_threshold_(avg_psnr_threshold),
65 avg_ssim_threshold_(avg_ssim_threshold), 70 avg_ssim_threshold_(avg_ssim_threshold),
66 comparison_available_event_(EventWrapper::Create()), 71 comparison_available_event_(EventWrapper::Create()),
67 done_(EventWrapper::Create()) { 72 done_(EventWrapper::Create()) {
(...skipping 18 matching lines...) Expand all
86 91
87 for (uint32_t i = 0; i < num_cores; ++i) { 92 for (uint32_t i = 0; i < num_cores; ++i) {
88 rtc::scoped_ptr<ThreadWrapper> thread = 93 rtc::scoped_ptr<ThreadWrapper> thread =
89 ThreadWrapper::CreateThread(&FrameComparisonThread, this, "Analyzer"); 94 ThreadWrapper::CreateThread(&FrameComparisonThread, this, "Analyzer");
90 EXPECT_TRUE(thread->Start()); 95 EXPECT_TRUE(thread->Start());
91 comparison_thread_pool_.push_back(thread.release()); 96 comparison_thread_pool_.push_back(thread.release());
92 } 97 }
93 98
94 stats_polling_thread_ = 99 stats_polling_thread_ =
95 ThreadWrapper::CreateThread(&PollStatsThread, this, "StatsPoller"); 100 ThreadWrapper::CreateThread(&PollStatsThread, this, "StatsPoller");
96 EXPECT_TRUE(stats_polling_thread_->Start());
97 } 101 }
98 102
99 ~VideoAnalyzer() { 103 ~VideoAnalyzer() {
100 for (ThreadWrapper* thread : comparison_thread_pool_) { 104 for (ThreadWrapper* thread : comparison_thread_pool_) {
101 EXPECT_TRUE(thread->Stop()); 105 EXPECT_TRUE(thread->Stop());
102 delete thread; 106 delete thread;
103 } 107 }
104 } 108 }
105 109
106 virtual void SetReceiver(PacketReceiver* receiver) { receiver_ = receiver; } 110 virtual void SetReceiver(PacketReceiver* receiver) { receiver_ = receiver; }
107 111
108 DeliveryStatus DeliverPacket(MediaType media_type, 112 DeliveryStatus DeliverPacket(MediaType media_type,
109 const uint8_t* packet, 113 const uint8_t* packet,
110 size_t length, 114 size_t length,
111 const PacketTime& packet_time) override { 115 const PacketTime& packet_time) override {
112 rtc::scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create()); 116 RtpUtility::RtpHeaderParser parser(packet, length);
113 RTPHeader header; 117 RTPHeader header;
114 parser->Parse(packet, length, &header); 118 parser.Parse(header);
115 { 119 {
116 rtc::CritScope lock(&crit_); 120 rtc::CritScope lock(&crit_);
117 recv_times_[header.timestamp - rtp_timestamp_delta_] = 121 recv_times_[header.timestamp - rtp_timestamp_delta_] =
118 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds(); 122 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds();
119 } 123 }
120 124
121 return receiver_->DeliverPacket(media_type, packet, length, packet_time); 125 return receiver_->DeliverPacket(media_type, packet, length, packet_time);
122 } 126 }
123 127
124 // EncodingTimeObserver. 128 // EncodingTimeObserver.
(...skipping 13 matching lines...) Expand all
138 142
139 frames_.push_back(copy); 143 frames_.push_back(copy);
140 } 144 }
141 145
142 input_->IncomingCapturedFrame(video_frame); 146 input_->IncomingCapturedFrame(video_frame);
143 } 147 }
144 148
145 bool SendRtp(const uint8_t* packet, 149 bool SendRtp(const uint8_t* packet,
146 size_t length, 150 size_t length,
147 const PacketOptions& options) override { 151 const PacketOptions& options) override {
148 rtc::scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create()); 152 RtpUtility::RtpHeaderParser parser(packet, length);
149 RTPHeader header; 153 RTPHeader header;
150 parser->Parse(packet, length, &header); 154 parser.Parse(header);
151 155
156 int64_t current_time =
157 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds();
158 bool result = transport_->SendRtp(packet, length, options);
152 { 159 {
153 rtc::CritScope lock(&crit_); 160 rtc::CritScope lock(&crit_);
154 if (rtp_timestamp_delta_ == 0) { 161 if (rtp_timestamp_delta_ == 0) {
155 rtp_timestamp_delta_ = header.timestamp - first_send_frame_.timestamp(); 162 rtp_timestamp_delta_ = header.timestamp - first_send_frame_.timestamp();
156 first_send_frame_.Reset(); 163 first_send_frame_.Reset();
157 } 164 }
158 uint32_t timestamp = header.timestamp - rtp_timestamp_delta_; 165 uint32_t timestamp = header.timestamp - rtp_timestamp_delta_;
159 send_times_[timestamp] = 166 send_times_[timestamp] = current_time;
160 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds(); 167 if (!transport_->DiscardedLastPacket() &&
161 encoded_frame_sizes_[timestamp] += 168 header.ssrc == ssrc_to_analyze_) {
162 length - (header.headerLength + header.paddingLength); 169 encoded_frame_sizes_[timestamp] +=
170 length - (header.headerLength + header.paddingLength);
171 }
163 } 172 }
164 173 return result;
165 return transport_->SendRtp(packet, length, options);
166 } 174 }
167 175
168 bool SendRtcp(const uint8_t* packet, size_t length) override { 176 bool SendRtcp(const uint8_t* packet, size_t length) override {
169 return transport_->SendRtcp(packet, length); 177 return transport_->SendRtcp(packet, length);
170 } 178 }
171 179
172 void EncodedFrameCallback(const EncodedFrame& frame) override { 180 void EncodedFrameCallback(const EncodedFrame& frame) override {
173 rtc::CritScope lock(&comparison_lock_); 181 rtc::CritScope lock(&comparison_lock_);
174 if (frames_recorded_ < frames_to_process_) 182 if (frames_recorded_ < frames_to_process_)
175 encoded_frame_size_.AddSample(frame.length_); 183 encoded_frame_size_.AddSample(frame.length_);
176 } 184 }
177 185
178 void RenderFrame(const VideoFrame& video_frame, 186 void RenderFrame(const VideoFrame& video_frame,
179 int time_to_render_ms) override { 187 int time_to_render_ms) override {
180 int64_t render_time_ms = 188 int64_t render_time_ms =
181 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds(); 189 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds();
182 uint32_t send_timestamp = video_frame.timestamp() - rtp_timestamp_delta_; 190 uint32_t send_timestamp = video_frame.timestamp() - rtp_timestamp_delta_;
183 191
184 rtc::CritScope lock(&crit_); 192 rtc::CritScope lock(&crit_);
185 193
186 while (frames_.front().timestamp() < send_timestamp) { 194 while (frames_.front().timestamp() < send_timestamp) {
187 AddFrameComparison(frames_.front(), last_rendered_frame_, true, 195 AddFrameComparison(frames_.front(), last_rendered_frame_, true,
188 render_time_ms); 196 render_time_ms);
189 frames_.pop_front(); 197 frames_.pop_front();
190 } 198 }
191 199
192 VideoFrame reference_frame = frames_.front(); 200 VideoFrame reference_frame = frames_.front();
193 frames_.pop_front(); 201 frames_.pop_front();
194 assert(!reference_frame.IsZeroSize()); 202 assert(!reference_frame.IsZeroSize());
203 if (send_timestamp == reference_frame.timestamp() - 1) {
204 // TODO(ivica): Make this work for > 2 streams.
205 // Look at rtp_sender.c:RTPSender::BuildRTPHeader.
206 ++send_timestamp;
207 }
195 EXPECT_EQ(reference_frame.timestamp(), send_timestamp); 208 EXPECT_EQ(reference_frame.timestamp(), send_timestamp);
196 assert(reference_frame.timestamp() == send_timestamp); 209 assert(reference_frame.timestamp() == send_timestamp);
197 210
198 AddFrameComparison(reference_frame, video_frame, false, render_time_ms); 211 AddFrameComparison(reference_frame, video_frame, false, render_time_ms);
199 212
200 last_rendered_frame_ = video_frame; 213 last_rendered_frame_ = video_frame;
201 } 214 }
202 215
203 bool IsTextureSupported() const override { return false; } 216 bool IsTextureSupported() const override { return false; }
204 217
205 void Wait() { 218 void Wait() {
206 // Frame comparisons can be very expensive. Wait for test to be done, but 219 // Frame comparisons can be very expensive. Wait for test to be done, but
207 // at time-out check if frames_processed is going up. If so, give it more 220 // at time-out check if frames_processed is going up. If so, give it more
208 // time, otherwise fail. Hopefully this will reduce test flakiness. 221 // time, otherwise fail. Hopefully this will reduce test flakiness.
209 222
223 EXPECT_TRUE(stats_polling_thread_->Start());
224
210 int last_frames_processed = -1; 225 int last_frames_processed = -1;
211 EventTypeWrapper eventType; 226 EventTypeWrapper eventType;
212 int iteration = 0; 227 int iteration = 0;
213 while ((eventType = done_->Wait(VideoQualityTest::kDefaultTimeoutMs)) != 228 while ((eventType = done_->Wait(VideoQualityTest::kDefaultTimeoutMs)) !=
214 kEventSignaled) { 229 kEventSignaled) {
215 int frames_processed; 230 int frames_processed;
216 { 231 {
217 rtc::CritScope crit(&comparison_lock_); 232 rtc::CritScope crit(&comparison_lock_);
218 frames_processed = frames_processed_; 233 frames_processed = frames_processed_;
219 } 234 }
(...skipping 18 matching lines...) Expand all
238 printf("- Farewell, sweet Concorde!\n"); 253 printf("- Farewell, sweet Concorde!\n");
239 254
240 // Signal stats polling thread if that is still waiting and stop it now, 255 // Signal stats polling thread if that is still waiting and stop it now,
241 // since it uses the send_stream_ reference that might be reclaimed after 256 // since it uses the send_stream_ reference that might be reclaimed after
242 // returning from this method. 257 // returning from this method.
243 done_->Set(); 258 done_->Set();
244 EXPECT_TRUE(stats_polling_thread_->Stop()); 259 EXPECT_TRUE(stats_polling_thread_->Stop());
245 } 260 }
246 261
247 VideoCaptureInput* input_; 262 VideoCaptureInput* input_;
248 Transport* const transport_; 263 test::LayerFilteringTransport* const transport_;
249 PacketReceiver* receiver_; 264 PacketReceiver* receiver_;
250 VideoSendStream* send_stream_; 265 VideoSendStream* send_stream_;
251 266
252 private: 267 private:
253 struct FrameComparison { 268 struct FrameComparison {
254 FrameComparison() 269 FrameComparison()
255 : dropped(false), 270 : dropped(false),
256 send_time_ms(0), 271 send_time_ms(0),
257 recv_time_ms(0), 272 recv_time_ms(0),
258 render_time_ms(0), 273 render_time_ms(0),
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 void AddFrameComparison(const VideoFrame& reference, 328 void AddFrameComparison(const VideoFrame& reference,
314 const VideoFrame& render, 329 const VideoFrame& render,
315 bool dropped, 330 bool dropped,
316 int64_t render_time_ms) 331 int64_t render_time_ms)
317 EXCLUSIVE_LOCKS_REQUIRED(crit_) { 332 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
318 int64_t send_time_ms = send_times_[reference.timestamp()]; 333 int64_t send_time_ms = send_times_[reference.timestamp()];
319 send_times_.erase(reference.timestamp()); 334 send_times_.erase(reference.timestamp());
320 int64_t recv_time_ms = recv_times_[reference.timestamp()]; 335 int64_t recv_time_ms = recv_times_[reference.timestamp()];
321 recv_times_.erase(reference.timestamp()); 336 recv_times_.erase(reference.timestamp());
322 337
323 size_t encoded_size = encoded_frame_sizes_[reference.timestamp()]; 338 // TODO(ivica): Make this work for > 2 streams.
324 encoded_frame_sizes_.erase(reference.timestamp()); 339 auto it = encoded_frame_sizes_.find(reference.timestamp());
340 if (it == encoded_frame_sizes_.end())
341 it = encoded_frame_sizes_.find(reference.timestamp() - 1);
342 size_t encoded_size = it == encoded_frame_sizes_.end() ? 0 : it->second;
343 if (it != encoded_frame_sizes_.end())
344 encoded_frame_sizes_.erase(it);
325 345
326 VideoFrame reference_copy; 346 VideoFrame reference_copy;
327 VideoFrame render_copy; 347 VideoFrame render_copy;
328 reference_copy.CopyFrame(reference); 348 reference_copy.CopyFrame(reference);
329 render_copy.CopyFrame(render); 349 render_copy.CopyFrame(render);
330 350
331 rtc::CritScope crit(&comparison_lock_); 351 rtc::CritScope crit(&comparison_lock_);
332 comparisons_.push_back(FrameComparison(reference_copy, render_copy, dropped, 352 comparisons_.push_back(FrameComparison(reference_copy, render_copy, dropped,
333 send_time_ms, recv_time_ms, 353 send_time_ms, recv_time_ms,
334 render_time_ms, encoded_size)); 354 render_time_ms, encoded_size));
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
502 } 522 }
503 523
504 void PrintSamplesToFile(void) { 524 void PrintSamplesToFile(void) {
505 FILE* out = graph_data_output_file_; 525 FILE* out = graph_data_output_file_;
506 rtc::CritScope crit(&comparison_lock_); 526 rtc::CritScope crit(&comparison_lock_);
507 std::sort(samples_.begin(), samples_.end(), 527 std::sort(samples_.begin(), samples_.end(),
508 [](const Sample& A, const Sample& B) -> bool { 528 [](const Sample& A, const Sample& B) -> bool {
509 return A.input_time_ms < B.input_time_ms; 529 return A.input_time_ms < B.input_time_ms;
510 }); 530 });
511 531
512 fprintf(out, "%s\n", test_label_.c_str()); 532 fprintf(out, "%s\n", graph_title_.c_str());
513 fprintf(out, "%" PRIuS "\n", samples_.size()); 533 fprintf(out, "%" PRIuS "\n", samples_.size());
514 fprintf(out, 534 fprintf(out,
515 "dropped " 535 "dropped "
516 "input_time_ms " 536 "input_time_ms "
517 "send_time_ms " 537 "send_time_ms "
518 "recv_time_ms " 538 "recv_time_ms "
519 "render_time_ms " 539 "render_time_ms "
520 "encoded_frame_size " 540 "encoded_frame_size "
521 "psnr " 541 "psnr "
522 "ssim " 542 "ssim "
(...skipping 17 matching lines...) Expand all
540 } 560 }
541 if (missing_encode_time_samples) { 561 if (missing_encode_time_samples) {
542 fprintf(stderr, 562 fprintf(stderr,
543 "Warning: Missing encode_time_ms samples for %d frame(s).\n", 563 "Warning: Missing encode_time_ms samples for %d frame(s).\n",
544 missing_encode_time_samples); 564 missing_encode_time_samples);
545 } 565 }
546 } 566 }
547 567
548 const std::string test_label_; 568 const std::string test_label_;
549 FILE* const graph_data_output_file_; 569 FILE* const graph_data_output_file_;
570 const std::string graph_title_;
571 const uint32_t ssrc_to_analyze_;
550 std::vector<Sample> samples_ GUARDED_BY(comparison_lock_); 572 std::vector<Sample> samples_ GUARDED_BY(comparison_lock_);
551 std::map<int64_t, int> samples_encode_time_ms_ GUARDED_BY(comparison_lock_); 573 std::map<int64_t, int> samples_encode_time_ms_ GUARDED_BY(comparison_lock_);
552 test::Statistics sender_time_ GUARDED_BY(comparison_lock_); 574 test::Statistics sender_time_ GUARDED_BY(comparison_lock_);
553 test::Statistics receiver_time_ GUARDED_BY(comparison_lock_); 575 test::Statistics receiver_time_ GUARDED_BY(comparison_lock_);
554 test::Statistics psnr_ GUARDED_BY(comparison_lock_); 576 test::Statistics psnr_ GUARDED_BY(comparison_lock_);
555 test::Statistics ssim_ GUARDED_BY(comparison_lock_); 577 test::Statistics ssim_ GUARDED_BY(comparison_lock_);
556 test::Statistics end_to_end_ GUARDED_BY(comparison_lock_); 578 test::Statistics end_to_end_ GUARDED_BY(comparison_lock_);
557 test::Statistics rendered_delta_ GUARDED_BY(comparison_lock_); 579 test::Statistics rendered_delta_ GUARDED_BY(comparison_lock_);
558 test::Statistics encoded_frame_size_ GUARDED_BY(comparison_lock_); 580 test::Statistics encoded_frame_size_ GUARDED_BY(comparison_lock_);
559 test::Statistics encode_frame_rate_ GUARDED_BY(comparison_lock_); 581 test::Statistics encode_frame_rate_ GUARDED_BY(comparison_lock_);
(...skipping 21 matching lines...) Expand all
581 rtc::CriticalSection comparison_lock_; 603 rtc::CriticalSection comparison_lock_;
582 std::vector<ThreadWrapper*> comparison_thread_pool_; 604 std::vector<ThreadWrapper*> comparison_thread_pool_;
583 rtc::scoped_ptr<ThreadWrapper> stats_polling_thread_; 605 rtc::scoped_ptr<ThreadWrapper> stats_polling_thread_;
584 const rtc::scoped_ptr<EventWrapper> comparison_available_event_; 606 const rtc::scoped_ptr<EventWrapper> comparison_available_event_;
585 std::deque<FrameComparison> comparisons_ GUARDED_BY(comparison_lock_); 607 std::deque<FrameComparison> comparisons_ GUARDED_BY(comparison_lock_);
586 const rtc::scoped_ptr<EventWrapper> done_; 608 const rtc::scoped_ptr<EventWrapper> done_;
587 }; 609 };
588 610
589 VideoQualityTest::VideoQualityTest() : clock_(Clock::GetRealTimeClock()) {} 611 VideoQualityTest::VideoQualityTest() : clock_(Clock::GetRealTimeClock()) {}
590 612
591 void VideoQualityTest::ValidateParams(const Params& params) { 613 void VideoQualityTest::TestBody() {}
592 RTC_CHECK_GE(params.common.max_bitrate_bps, params.common.target_bitrate_bps); 614
593 RTC_CHECK_GE(params.common.target_bitrate_bps, params.common.min_bitrate_bps); 615 std::string VideoQualityTest::GenerateGraphTitle() const {
594 RTC_CHECK_LT(params.common.tl_discard_threshold, 616 std::stringstream ss;
595 params.common.num_temporal_layers); 617 ss << params_.common.codec;
618 ss << " (" << params_.common.target_bitrate_bps / 1000 << "kbps";
619 ss << ", " << params_.common.fps << " FPS";
620 if (params_.screenshare.scroll_duration)
621 ss << ", " << params_.screenshare.scroll_duration << "s scroll";
622 if (params_.ss.streams.size() > 1)
623 ss << ", Stream #" << params_.ss.selected_stream;
624 if (params_.ss.num_spatial_layers > 1)
625 ss << ", Layer #" << params_.ss.selected_sl;
626 ss << ")";
627 return ss.str();
596 } 628 }
597 629
598 void VideoQualityTest::TestBody() {} 630 void VideoQualityTest::CheckParams() {
631 // Add a default stream in none specified.
632 if (params_.ss.streams.empty())
633 params_.ss.streams.push_back(VideoQualityTest::DefaultVideoStream(params_));
634 if (params_.ss.num_spatial_layers == 0)
635 params_.ss.num_spatial_layers = 1;
599 636
600 void VideoQualityTest::SetupFullStack(const Params& params, 637 if (params_.pipe.loss_percent != 0 ||
601 Transport* send_transport, 638 params_.pipe.queue_length_packets != 0) {
602 Transport* recv_transport) { 639 // Since LayerFilteringTransport changes the sequence numbers, we can't
603 if (params.logs) 640 // use that feature with pack loss, since the NACK request would end up
641 // retransmitting the wrong packets.
642 RTC_CHECK(params_.ss.selected_sl == -1 ||
643 params_.ss.num_spatial_layers == 1);
644 RTC_CHECK(params_.common.selected_tl == -1 ||
645 params_.common.num_temporal_layers == 1);
646 }
647
648 // TODO(ivica): Should max_bitrate_bps == -1 represent inf max bitrate, as it
649 // does in some parts of the code?
650 RTC_CHECK_GE(params_.common.max_bitrate_bps,
651 params_.common.target_bitrate_bps);
652 RTC_CHECK_GE(params_.common.target_bitrate_bps,
653 params_.common.min_bitrate_bps);
654 RTC_CHECK_LT(params_.common.selected_tl, params_.common.num_temporal_layers);
655 RTC_CHECK_LT(params_.ss.selected_stream, params_.ss.streams.size());
656 for (const VideoStream& stream : params_.ss.streams) {
657 RTC_CHECK_GE(stream.min_bitrate_bps, 0);
658 RTC_CHECK_GE(stream.target_bitrate_bps, stream.min_bitrate_bps);
659 RTC_CHECK_GE(stream.max_bitrate_bps, stream.target_bitrate_bps);
660 RTC_CHECK_EQ(static_cast<int>(stream.temporal_layer_thresholds_bps.size()),
661 params_.common.num_temporal_layers - 1);
662 }
663 // TODO(ivica): Should we check if the sum of all streams/layers is equal to
664 // the total bitrate? We anyway have to update them in the case bitrate
665 // estimator changes the total bitrates.
666 RTC_CHECK_GE(params_.ss.num_spatial_layers, 1);
667 RTC_CHECK_LE(params_.ss.selected_sl, params_.ss.num_spatial_layers);
668 RTC_CHECK(params_.ss.spatial_layers.empty() ||
669 params_.ss.spatial_layers.size() ==
670 static_cast<size_t>(params_.ss.num_spatial_layers));
671 if (params_.common.codec == "VP8") {
672 RTC_CHECK_EQ(params_.ss.num_spatial_layers, 1);
673 } else if (params_.common.codec == "VP9") {
674 RTC_CHECK_EQ(params_.ss.streams.size(), 1u);
675 }
676 }
677
678 // Static.
679 std::vector<int> VideoQualityTest::ParseCSV(const std::string& str) {
680 // Parse comma separated nonnegative integers, where some elements may be
681 // empty. The empty values are replaced with -1.
682 // E.g. "10,-20,,30,40" --> {10, 20, -1, 30,40}
683 // E.g. ",,10,,20," --> {-1, -1, 10, -1, 20, -1}
684 std::vector<int> result;
685 if (str.empty())
686 return result;
687
688 const char* p = str.c_str();
689 int value = -1;
690 int pos;
691 while (*p) {
692 if (*p == ',') {
693 result.push_back(value);
694 value = -1;
695 ++p;
696 continue;
697 }
698 RTC_CHECK_EQ(sscanf(p, "%d%n", &value, &pos), 1)
699 << "Unexpected non-number value.";
700 p += pos;
701 }
702 result.push_back(value);
703 return result;
704 }
705
706 // Static.
707 VideoStream VideoQualityTest::DefaultVideoStream(const Params& params) {
708 VideoStream stream;
709 stream.width = params.common.width;
710 stream.height = params.common.height;
711 stream.max_framerate = params.common.fps;
712 stream.min_bitrate_bps = params.common.min_bitrate_bps;
713 stream.target_bitrate_bps = params.common.target_bitrate_bps;
714 stream.max_bitrate_bps = params.common.max_bitrate_bps;
715 stream.max_qp = 52;
716 if (params.common.num_temporal_layers == 2)
717 stream.temporal_layer_thresholds_bps.push_back(stream.target_bitrate_bps);
718 return stream;
719 }
720
721 // Static.
722 void VideoQualityTest::FillScalabilitySettings(
723 Params* params,
724 const std::vector<std::string>& stream_descriptors,
725 size_t selected_stream,
726 int num_spatial_layers,
727 int selected_sl,
728 const std::vector<std::string>& sl_descriptors) {
729 // Read VideoStream and SpatialLayer elements from a list of comma separated
730 // lists. To use a default value for an element, use -1 or leave empty.
731 // Validity checks performed in CheckParams.
732
733 RTC_CHECK(params->ss.streams.empty());
734 for (auto descriptor : stream_descriptors) {
735 if (descriptor.empty())
736 continue;
737 VideoStream stream = VideoQualityTest::DefaultVideoStream(*params);
738 std::vector<int> v = VideoQualityTest::ParseCSV(descriptor);
739 if (v[0] != -1)
740 stream.width = static_cast<size_t>(v[0]);
741 if (v[1] != -1)
742 stream.height = static_cast<size_t>(v[1]);
743 if (v[2] != -1)
744 stream.max_framerate = v[2];
745 if (v[3] != -1)
746 stream.min_bitrate_bps = v[3];
747 if (v[4] != -1)
748 stream.target_bitrate_bps = v[4];
749 if (v[5] != -1)
750 stream.max_bitrate_bps = v[5];
751 if (v.size() > 6 && v[6] != -1)
752 stream.max_qp = v[6];
753 if (v.size() > 7) {
754 stream.temporal_layer_thresholds_bps.clear();
755 stream.temporal_layer_thresholds_bps.insert(
756 stream.temporal_layer_thresholds_bps.end(), v.begin() + 7, v.end());
757 } else {
758 // Automatic TL thresholds for more than two layers not supported.
759 RTC_CHECK_LE(params->common.num_temporal_layers, 2);
760 }
761 params->ss.streams.push_back(stream);
762 }
763 params->ss.selected_stream = selected_stream;
764
765 params->ss.num_spatial_layers = num_spatial_layers ? num_spatial_layers : 1;
766 params->ss.selected_sl = selected_sl;
767 RTC_CHECK(params->ss.spatial_layers.empty());
768 for (auto descriptor : sl_descriptors) {
769 if (descriptor.empty())
770 continue;
771 std::vector<int> v = VideoQualityTest::ParseCSV(descriptor);
772 RTC_CHECK_GT(v[2], 0);
773
774 SpatialLayer layer;
775 layer.scaling_factor_num = v[0] == -1 ? 1 : v[0];
776 layer.scaling_factor_den = v[1] == -1 ? 1 : v[1];
777 layer.target_bitrate_bps = v[2];
778 params->ss.spatial_layers.push_back(layer);
779 }
780 }
781
782 void VideoQualityTest::SetupCommon(Transport* send_transport,
783 Transport* recv_transport) {
784 if (params_.logs)
604 trace_to_stderr_.reset(new test::TraceToStderr); 785 trace_to_stderr_.reset(new test::TraceToStderr);
605 786
606 CreateSendConfig(1, send_transport); 787 size_t num_streams = params_.ss.streams.size();
788 CreateSendConfig(num_streams, send_transport);
607 789
608 int payload_type; 790 int payload_type;
609 if (params.common.codec == "VP8") { 791 if (params_.common.codec == "VP8") {
610 encoder_.reset(VideoEncoder::Create(VideoEncoder::kVp8)); 792 encoder_.reset(VideoEncoder::Create(VideoEncoder::kVp8));
611 payload_type = kPayloadTypeVP8; 793 payload_type = kPayloadTypeVP8;
612 } else if (params.common.codec == "VP9") { 794 } else if (params_.common.codec == "VP9") {
613 encoder_.reset(VideoEncoder::Create(VideoEncoder::kVp9)); 795 encoder_.reset(VideoEncoder::Create(VideoEncoder::kVp9));
614 payload_type = kPayloadTypeVP9; 796 payload_type = kPayloadTypeVP9;
615 } else { 797 } else {
616 RTC_NOTREACHED() << "Codec not supported!"; 798 RTC_NOTREACHED() << "Codec not supported!";
617 return; 799 return;
618 } 800 }
619 send_config_.encoder_settings.encoder = encoder_.get(); 801 send_config_.encoder_settings.encoder = encoder_.get();
620 send_config_.encoder_settings.payload_name = params.common.codec; 802 send_config_.encoder_settings.payload_name = params_.common.codec;
621 send_config_.encoder_settings.payload_type = payload_type; 803 send_config_.encoder_settings.payload_type = payload_type;
622
623 send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs; 804 send_config_.rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
624 send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
625 send_config_.rtp.rtx.payload_type = kSendRtxPayloadType; 805 send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
806 for (size_t i = 0; i < num_streams; ++i)
807 send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
626 808
627 send_config_.rtp.extensions.clear(); 809 send_config_.rtp.extensions.clear();
628 if (params.common.send_side_bwe) { 810 if (params_.common.send_side_bwe) {
629 send_config_.rtp.extensions.push_back( 811 send_config_.rtp.extensions.push_back(
630 RtpExtension(RtpExtension::kTransportSequenceNumber, 812 RtpExtension(RtpExtension::kTransportSequenceNumber,
631 test::kTransportSequenceNumberExtensionId)); 813 test::kTransportSequenceNumberExtensionId));
632 } else { 814 } else {
633 send_config_.rtp.extensions.push_back(RtpExtension( 815 send_config_.rtp.extensions.push_back(RtpExtension(
634 RtpExtension::kAbsSendTime, test::kAbsSendTimeExtensionId)); 816 RtpExtension::kAbsSendTime, test::kAbsSendTimeExtensionId));
635 } 817 }
636 818
637 // Automatically fill out streams[0] with params. 819 encoder_config_.min_transmit_bitrate_bps = params_.common.min_transmit_bps;
638 VideoStream* stream = &encoder_config_.streams[0]; 820 encoder_config_.streams = params_.ss.streams;
639 stream->width = params.common.width; 821 encoder_config_.spatial_layers = params_.ss.spatial_layers;
640 stream->height = params.common.height;
641 stream->min_bitrate_bps = params.common.min_bitrate_bps;
642 stream->target_bitrate_bps = params.common.target_bitrate_bps;
643 stream->max_bitrate_bps = params.common.max_bitrate_bps;
644 stream->max_framerate = static_cast<int>(params.common.fps);
645
646 stream->temporal_layer_thresholds_bps.clear();
647 if (params.common.num_temporal_layers > 1) {
648 stream->temporal_layer_thresholds_bps.push_back(stream->target_bitrate_bps);
649 }
650 822
651 CreateMatchingReceiveConfigs(recv_transport); 823 CreateMatchingReceiveConfigs(recv_transport);
652 824
653 receive_configs_[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs; 825 for (size_t i = 0; i < num_streams; ++i) {
654 receive_configs_[0].rtp.rtx[kSendRtxPayloadType].ssrc = kSendRtxSsrcs[0]; 826 receive_configs_[i].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
655 receive_configs_[0].rtp.rtx[kSendRtxPayloadType].payload_type = 827 receive_configs_[i].rtp.rtx[kSendRtxPayloadType].ssrc = kSendRtxSsrcs[i];
656 kSendRtxPayloadType; 828 receive_configs_[i].rtp.rtx[kSendRtxPayloadType].payload_type =
657 829 kSendRtxPayloadType;
658 encoder_config_.min_transmit_bitrate_bps = params.common.min_transmit_bps; 830 }
659 } 831 }
660 832
661 void VideoQualityTest::SetupScreenshare(const Params& params) { 833 void VideoQualityTest::SetupScreenshare() {
662 RTC_CHECK(params.screenshare.enabled); 834 RTC_CHECK(params_.screenshare.enabled);
663 835
664 // Fill out codec settings. 836 // Fill out codec settings.
665 encoder_config_.content_type = VideoEncoderConfig::ContentType::kScreen; 837 encoder_config_.content_type = VideoEncoderConfig::ContentType::kScreen;
666 if (params.common.codec == "VP8") { 838 if (params_.common.codec == "VP8") {
667 codec_settings_.VP8 = VideoEncoder::GetDefaultVp8Settings(); 839 codec_settings_.VP8 = VideoEncoder::GetDefaultVp8Settings();
668 codec_settings_.VP8.denoisingOn = false; 840 codec_settings_.VP8.denoisingOn = false;
669 codec_settings_.VP8.frameDroppingOn = false; 841 codec_settings_.VP8.frameDroppingOn = false;
670 codec_settings_.VP8.numberOfTemporalLayers = 842 codec_settings_.VP8.numberOfTemporalLayers =
671 static_cast<unsigned char>(params.common.num_temporal_layers); 843 static_cast<unsigned char>(params_.common.num_temporal_layers);
672 encoder_config_.encoder_specific_settings = &codec_settings_.VP8; 844 encoder_config_.encoder_specific_settings = &codec_settings_.VP8;
673 } else if (params.common.codec == "VP9") { 845 } else if (params_.common.codec == "VP9") {
674 codec_settings_.VP9 = VideoEncoder::GetDefaultVp9Settings(); 846 codec_settings_.VP9 = VideoEncoder::GetDefaultVp9Settings();
675 codec_settings_.VP9.denoisingOn = false; 847 codec_settings_.VP9.denoisingOn = false;
676 codec_settings_.VP9.frameDroppingOn = false; 848 codec_settings_.VP9.frameDroppingOn = false;
677 codec_settings_.VP9.numberOfTemporalLayers = 849 codec_settings_.VP9.numberOfTemporalLayers =
678 static_cast<unsigned char>(params.common.num_temporal_layers); 850 static_cast<unsigned char>(params_.common.num_temporal_layers);
679 encoder_config_.encoder_specific_settings = &codec_settings_.VP9; 851 encoder_config_.encoder_specific_settings = &codec_settings_.VP9;
852 codec_settings_.VP9.numberOfSpatialLayers =
853 static_cast<unsigned char>(params_.ss.num_spatial_layers);
680 } 854 }
681 855
682 // Setup frame generator. 856 // Setup frame generator.
683 const size_t kWidth = 1850; 857 const size_t kWidth = 1850;
684 const size_t kHeight = 1110; 858 const size_t kHeight = 1110;
685 std::vector<std::string> slides; 859 std::vector<std::string> slides;
686 slides.push_back(test::ResourcePath("web_screenshot_1850_1110", "yuv")); 860 slides.push_back(test::ResourcePath("web_screenshot_1850_1110", "yuv"));
687 slides.push_back(test::ResourcePath("presentation_1850_1110", "yuv")); 861 slides.push_back(test::ResourcePath("presentation_1850_1110", "yuv"));
688 slides.push_back(test::ResourcePath("photo_1850_1110", "yuv")); 862 slides.push_back(test::ResourcePath("photo_1850_1110", "yuv"));
689 slides.push_back(test::ResourcePath("difficult_photo_1850_1110", "yuv")); 863 slides.push_back(test::ResourcePath("difficult_photo_1850_1110", "yuv"));
690 864
691 if (params.screenshare.scroll_duration == 0) { 865 if (params_.screenshare.scroll_duration == 0) {
692 // Cycle image every slide_change_interval seconds. 866 // Cycle image every slide_change_interval seconds.
693 frame_generator_.reset(test::FrameGenerator::CreateFromYuvFile( 867 frame_generator_.reset(test::FrameGenerator::CreateFromYuvFile(
694 slides, kWidth, kHeight, 868 slides, kWidth, kHeight,
695 params.screenshare.slide_change_interval * params.common.fps)); 869 params_.screenshare.slide_change_interval * params_.common.fps));
696 } else { 870 } else {
697 RTC_CHECK_LE(params.common.width, kWidth); 871 RTC_CHECK_LE(params_.common.width, kWidth);
698 RTC_CHECK_LE(params.common.height, kHeight); 872 RTC_CHECK_LE(params_.common.height, kHeight);
699 RTC_CHECK_GT(params.screenshare.slide_change_interval, 0); 873 RTC_CHECK_GT(params_.screenshare.slide_change_interval, 0);
700 const int kPauseDurationMs = (params.screenshare.slide_change_interval - 874 const int kPauseDurationMs = (params_.screenshare.slide_change_interval -
701 params.screenshare.scroll_duration) * 1000; 875 params_.screenshare.scroll_duration) *
702 RTC_CHECK_LE(params.screenshare.scroll_duration, 876 1000;
703 params.screenshare.slide_change_interval); 877 RTC_CHECK_LE(params_.screenshare.scroll_duration,
878 params_.screenshare.slide_change_interval);
704 879
705 if (params.screenshare.scroll_duration) { 880 frame_generator_.reset(
706 frame_generator_.reset( 881 test::FrameGenerator::CreateScrollingInputFromYuvFiles(
707 test::FrameGenerator::CreateScrollingInputFromYuvFiles( 882 clock_, slides, kWidth, kHeight, params_.common.width,
708 clock_, slides, kWidth, kHeight, params.common.width, 883 params_.common.height, params_.screenshare.scroll_duration * 1000,
709 params.common.height, params.screenshare.scroll_duration * 1000, 884 kPauseDurationMs));
710 kPauseDurationMs));
711 } else {
712 frame_generator_.reset(test::FrameGenerator::CreateFromYuvFile(
713 slides, kWidth, kHeight,
714 params.screenshare.slide_change_interval * params.common.fps));
715 }
716 } 885 }
717 } 886 }
718 887
719 void VideoQualityTest::CreateCapturer(const Params& params, 888 void VideoQualityTest::CreateCapturer(VideoCaptureInput* input) {
720 VideoCaptureInput* input) { 889 if (params_.screenshare.enabled) {
721 if (params.screenshare.enabled) { 890 test::FrameGeneratorCapturer* frame_generator_capturer =
722 test::FrameGeneratorCapturer *frame_generator_capturer =
723 new test::FrameGeneratorCapturer( 891 new test::FrameGeneratorCapturer(
724 clock_, input, frame_generator_.release(), params.common.fps); 892 clock_, input, frame_generator_.release(), params_.common.fps);
725 EXPECT_TRUE(frame_generator_capturer->Init()); 893 EXPECT_TRUE(frame_generator_capturer->Init());
726 capturer_.reset(frame_generator_capturer); 894 capturer_.reset(frame_generator_capturer);
727 } else { 895 } else {
728 if (params.video.clip_name.empty()) { 896 if (params_.video.clip_name.empty()) {
729 capturer_.reset(test::VideoCapturer::Create( 897 capturer_.reset(test::VideoCapturer::Create(input, params_.common.width,
730 input, params.common.width, params.common.height, params.common.fps, 898 params_.common.height,
731 clock_)); 899 params_.common.fps, clock_));
732 } else { 900 } else {
733 capturer_.reset(test::FrameGeneratorCapturer::CreateFromYuvFile( 901 capturer_.reset(test::FrameGeneratorCapturer::CreateFromYuvFile(
734 input, test::ResourcePath(params.video.clip_name, "yuv"), 902 input, test::ResourcePath(params_.video.clip_name, "yuv"),
735 params.common.width, params.common.height, params.common.fps, 903 params_.common.width, params_.common.height, params_.common.fps,
736 clock_)); 904 clock_));
737 ASSERT_TRUE(capturer_.get() != nullptr) 905 ASSERT_TRUE(capturer_.get() != nullptr)
738 << "Could not create capturer for " << params.video.clip_name 906 << "Could not create capturer for " << params_.video.clip_name
739 << ".yuv. Is this resource file present?"; 907 << ".yuv. Is this resource file present?";
740 } 908 }
741 } 909 }
742 } 910 }
743 911
744 void VideoQualityTest::RunWithAnalyzer(const Params& params) { 912 void VideoQualityTest::RunWithAnalyzer(const Params& params) {
913 params_ = params;
914
745 // TODO(ivica): Merge with RunWithRenderer and use a flag / argument to 915 // TODO(ivica): Merge with RunWithRenderer and use a flag / argument to
746 // differentiate between the analyzer and the renderer case. 916 // differentiate between the analyzer and the renderer case.
747 ValidateParams(params); 917 CheckParams();
748 918
749 FILE* graph_data_output_file = nullptr; 919 FILE* graph_data_output_file = nullptr;
750 if (!params.analyzer.graph_data_output_filename.empty()) { 920 if (!params_.analyzer.graph_data_output_filename.empty()) {
751 graph_data_output_file = 921 graph_data_output_file =
752 fopen(params.analyzer.graph_data_output_filename.c_str(), "w"); 922 fopen(params_.analyzer.graph_data_output_filename.c_str(), "w");
753 RTC_CHECK(graph_data_output_file != nullptr) 923 RTC_CHECK(graph_data_output_file != nullptr)
754 << "Can't open the file " 924 << "Can't open the file " << params_.analyzer.graph_data_output_filename
755 << params.analyzer.graph_data_output_filename << "!"; 925 << "!";
756 } 926 }
757 927
758 Call::Config call_config; 928 Call::Config call_config;
759 call_config.bitrate_config = params.common.call_bitrate_config; 929 call_config.bitrate_config = params.common.call_bitrate_config;
760 CreateCalls(call_config, call_config); 930 CreateCalls(call_config, call_config);
761 931
762 test::LayerFilteringTransport send_transport( 932 test::LayerFilteringTransport send_transport(
763 params.pipe, sender_call_.get(), kPayloadTypeVP8, kPayloadTypeVP9, 933 params.pipe, sender_call_.get(), kPayloadTypeVP8, kPayloadTypeVP9,
764 static_cast<uint8_t>(params.common.tl_discard_threshold), 0); 934 params.common.selected_tl, params_.ss.selected_sl);
765 test::DirectTransport recv_transport(params.pipe, receiver_call_.get()); 935 test::DirectTransport recv_transport(params.pipe, receiver_call_.get());
766 936
937 std::string graph_title = params_.analyzer.graph_title;
938 if (graph_title.empty())
939 graph_title = VideoQualityTest::GenerateGraphTitle();
940
941 // In the case of different resolutions, the functions calculating PSNR and
942 // SSIM return -1.0, instead of a positive value as usual. VideoAnalyzer
943 // aborts if the average psnr/ssim are below the given threshold, which is
944 // 0.0 by default. Setting the thresholds to -1.1 prevents the unnecessary
945 // abort.
946 VideoStream& selected_stream = params_.ss.streams[params_.ss.selected_stream];
947 int selected_sl = params_.ss.selected_sl != -1
948 ? params_.ss.selected_sl
949 : params_.ss.num_spatial_layers - 1;
950 bool disable_quality_check =
951 selected_stream.width != params_.common.width ||
952 selected_stream.height != params_.common.height ||
953 (!params_.ss.spatial_layers.empty() &&
954 params_.ss.spatial_layers[selected_sl].scaling_factor_num !=
955 params_.ss.spatial_layers[selected_sl].scaling_factor_den);
956 if (disable_quality_check) {
957 fprintf(stderr,
958 "Warning: Calculating PSNR and SSIM for downsized resolution "
959 "not implemented yet! Skipping PSNR and SSIM calculations!");
960 }
961
767 VideoAnalyzer analyzer( 962 VideoAnalyzer analyzer(
768 &send_transport, params.analyzer.test_label, 963 &send_transport, params_.analyzer.test_label,
769 params.analyzer.avg_psnr_threshold, params.analyzer.avg_ssim_threshold, 964 disable_quality_check ? -1.1 : params_.analyzer.avg_psnr_threshold,
770 params.analyzer.test_durations_secs * params.common.fps, 965 disable_quality_check ? -1.1 : params_.analyzer.avg_ssim_threshold,
771 graph_data_output_file); 966 params_.analyzer.test_durations_secs * params_.common.fps,
967 graph_data_output_file, graph_title,
968 kSendSsrcs[params_.ss.selected_stream]);
772 969
773 analyzer.SetReceiver(receiver_call_->Receiver()); 970 analyzer.SetReceiver(receiver_call_->Receiver());
774 send_transport.SetReceiver(&analyzer); 971 send_transport.SetReceiver(&analyzer);
775 recv_transport.SetReceiver(sender_call_->Receiver()); 972 recv_transport.SetReceiver(sender_call_->Receiver());
776 973
777 SetupFullStack(params, &analyzer, &recv_transport); 974 SetupCommon(&analyzer, &recv_transport);
778 send_config_.encoding_time_observer = &analyzer; 975 send_config_.encoding_time_observer = &analyzer;
779 receive_configs_[0].renderer = &analyzer; 976 receive_configs_[params_.ss.selected_stream].renderer = &analyzer;
780 for (auto& config : receive_configs_) 977 for (auto& config : receive_configs_)
781 config.pre_decode_callback = &analyzer; 978 config.pre_decode_callback = &analyzer;
782 979
783 if (params.screenshare.enabled) 980 if (params_.screenshare.enabled)
784 SetupScreenshare(params); 981 SetupScreenshare();
785 982
786 CreateStreams(); 983 CreateStreams();
787 analyzer.input_ = send_stream_->Input(); 984 analyzer.input_ = send_stream_->Input();
788 analyzer.send_stream_ = send_stream_; 985 analyzer.send_stream_ = send_stream_;
789 986
790 CreateCapturer(params, &analyzer); 987 CreateCapturer(&analyzer);
791 988
792 send_stream_->Start(); 989 send_stream_->Start();
793 for (size_t i = 0; i < receive_streams_.size(); ++i) 990 for (size_t i = 0; i < receive_streams_.size(); ++i)
794 receive_streams_[i]->Start(); 991 receive_streams_[i]->Start();
795 capturer_->Start(); 992 capturer_->Start();
796 993
797 analyzer.Wait(); 994 analyzer.Wait();
798 995
799 send_transport.StopSending(); 996 send_transport.StopSending();
800 recv_transport.StopSending(); 997 recv_transport.StopSending();
801 998
802 capturer_->Stop(); 999 capturer_->Stop();
803 for (size_t i = 0; i < receive_streams_.size(); ++i) 1000 for (size_t i = 0; i < receive_streams_.size(); ++i)
804 receive_streams_[i]->Stop(); 1001 receive_streams_[i]->Stop();
805 send_stream_->Stop(); 1002 send_stream_->Stop();
806 1003
807 DestroyStreams(); 1004 DestroyStreams();
808 1005
809 if (graph_data_output_file) 1006 if (graph_data_output_file)
810 fclose(graph_data_output_file); 1007 fclose(graph_data_output_file);
811 } 1008 }
812 1009
813 void VideoQualityTest::RunWithVideoRenderer(const Params& params) { 1010 void VideoQualityTest::RunWithVideoRenderer(const Params& params) {
814 ValidateParams(params); 1011 params_ = params;
1012 CheckParams();
815 1013
816 rtc::scoped_ptr<test::VideoRenderer> local_preview( 1014 rtc::scoped_ptr<test::VideoRenderer> local_preview(
817 test::VideoRenderer::Create("Local Preview", params.common.width, 1015 test::VideoRenderer::Create("Local Preview", params_.common.width,
818 params.common.height)); 1016 params_.common.height));
1017 size_t stream_id = params_.ss.selected_stream;
1018 char title[32];
1019 if (params_.ss.streams.size() == 1) {
1020 sprintf(title, "Loopback Video");
1021 } else {
1022 sprintf(title, "Loopback Video - Stream #%" PRIuS, stream_id);
1023 }
819 rtc::scoped_ptr<test::VideoRenderer> loopback_video( 1024 rtc::scoped_ptr<test::VideoRenderer> loopback_video(
820 test::VideoRenderer::Create("Loopback Video", params.common.width, 1025 test::VideoRenderer::Create(title, params_.ss.streams[stream_id].width,
821 params.common.height)); 1026 params_.ss.streams[stream_id].height));
822 1027
823 // TODO(ivica): Remove bitrate_config and use the default Call::Config(), to 1028 // TODO(ivica): Remove bitrate_config and use the default Call::Config(), to
824 // match the full stack tests. 1029 // match the full stack tests.
825 Call::Config call_config; 1030 Call::Config call_config;
826 call_config.bitrate_config = params.common.call_bitrate_config; 1031 call_config.bitrate_config = params_.common.call_bitrate_config;
827 rtc::scoped_ptr<Call> call(Call::Create(call_config)); 1032 rtc::scoped_ptr<Call> call(Call::Create(call_config));
828 1033
829 test::LayerFilteringTransport transport( 1034 test::LayerFilteringTransport transport(
830 params.pipe, call.get(), kPayloadTypeVP8, kPayloadTypeVP9, 1035 params.pipe, call.get(), kPayloadTypeVP8, kPayloadTypeVP9,
831 static_cast<uint8_t>(params.common.tl_discard_threshold), 0); 1036 params.common.selected_tl, params_.ss.selected_sl);
832 // TODO(ivica): Use two calls to be able to merge with RunWithAnalyzer or at 1037 // TODO(ivica): Use two calls to be able to merge with RunWithAnalyzer or at
833 // least share as much code as possible. That way this test would also match 1038 // least share as much code as possible. That way this test would also match
834 // the full stack tests better. 1039 // the full stack tests better.
835 transport.SetReceiver(call->Receiver()); 1040 transport.SetReceiver(call->Receiver());
836 1041
837 SetupFullStack(params, &transport, &transport); 1042 SetupCommon(&transport, &transport);
1043
838 send_config_.local_renderer = local_preview.get(); 1044 send_config_.local_renderer = local_preview.get();
839 receive_configs_[0].renderer = loopback_video.get(); 1045 receive_configs_[stream_id].renderer = loopback_video.get();
840 1046
841 if (params.screenshare.enabled) 1047 if (params_.screenshare.enabled)
842 SetupScreenshare(params); 1048 SetupScreenshare();
843 1049
844 send_stream_ = call->CreateVideoSendStream(send_config_, encoder_config_); 1050 send_stream_ = call->CreateVideoSendStream(send_config_, encoder_config_);
845 VideoReceiveStream* receive_stream = 1051 VideoReceiveStream* receive_stream =
846 call->CreateVideoReceiveStream(receive_configs_[0]); 1052 call->CreateVideoReceiveStream(receive_configs_[stream_id]);
847 CreateCapturer(params, send_stream_->Input()); 1053 CreateCapturer(send_stream_->Input());
848 1054
849 receive_stream->Start(); 1055 receive_stream->Start();
850 send_stream_->Start(); 1056 send_stream_->Start();
851 capturer_->Start(); 1057 capturer_->Start();
852 1058
853 test::PressEnterToContinue(); 1059 test::PressEnterToContinue();
854 1060
855 capturer_->Stop(); 1061 capturer_->Stop();
856 send_stream_->Stop(); 1062 send_stream_->Stop();
857 receive_stream->Stop(); 1063 receive_stream->Stop();
858 1064
859 call->DestroyVideoReceiveStream(receive_stream); 1065 call->DestroyVideoReceiveStream(receive_stream);
860 call->DestroyVideoSendStream(send_stream_); 1066 call->DestroyVideoSendStream(send_stream_);
861 1067
862 transport.StopSending(); 1068 transport.StopSending();
863 } 1069 }
864 1070
865 } // namespace webrtc 1071 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/video/video_quality_test.h ('k') | webrtc/video/video_send_stream.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698