OLD | NEW |
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 <sstream> |
16 #include <string> | 16 #include <string> |
17 #include <vector> | 17 #include <vector> |
18 | 18 |
19 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
20 | 20 |
21 #include "webrtc/base/checks.h" | 21 #include "webrtc/base/checks.h" |
| 22 #include "webrtc/base/event.h" |
22 #include "webrtc/base/format_macros.h" | 23 #include "webrtc/base/format_macros.h" |
23 #include "webrtc/base/scoped_ptr.h" | 24 #include "webrtc/base/scoped_ptr.h" |
24 #include "webrtc/call.h" | 25 #include "webrtc/call.h" |
25 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" | 26 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" |
26 #include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" | 27 #include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" |
27 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" | 28 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" |
28 #include "webrtc/system_wrappers/include/cpu_info.h" | 29 #include "webrtc/system_wrappers/include/cpu_info.h" |
29 #include "webrtc/test/layer_filtering_transport.h" | 30 #include "webrtc/test/layer_filtering_transport.h" |
30 #include "webrtc/test/run_loop.h" | 31 #include "webrtc/test/run_loop.h" |
31 #include "webrtc/test/statistics.h" | 32 #include "webrtc/test/statistics.h" |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
64 ssrc_to_analyze_(ssrc_to_analyze), | 65 ssrc_to_analyze_(ssrc_to_analyze), |
65 frames_to_process_(duration_frames), | 66 frames_to_process_(duration_frames), |
66 frames_recorded_(0), | 67 frames_recorded_(0), |
67 frames_processed_(0), | 68 frames_processed_(0), |
68 dropped_frames_(0), | 69 dropped_frames_(0), |
69 last_render_time_(0), | 70 last_render_time_(0), |
70 rtp_timestamp_delta_(0), | 71 rtp_timestamp_delta_(0), |
71 avg_psnr_threshold_(avg_psnr_threshold), | 72 avg_psnr_threshold_(avg_psnr_threshold), |
72 avg_ssim_threshold_(avg_ssim_threshold), | 73 avg_ssim_threshold_(avg_ssim_threshold), |
73 stats_polling_thread_(&PollStatsThread, this, "StatsPoller"), | 74 stats_polling_thread_(&PollStatsThread, this, "StatsPoller"), |
74 comparison_available_event_(EventWrapper::Create()), | 75 comparison_available_event_(false, false), |
75 done_(EventWrapper::Create()) { | 76 done_(false, false) { |
76 // Create thread pool for CPU-expensive PSNR/SSIM calculations. | 77 // Create thread pool for CPU-expensive PSNR/SSIM calculations. |
77 | 78 |
78 // Try to use about as many threads as cores, but leave kMinCoresLeft alone, | 79 // Try to use about as many threads as cores, but leave kMinCoresLeft alone, |
79 // so that we don't accidentally starve "real" worker threads (codec etc). | 80 // so that we don't accidentally starve "real" worker threads (codec etc). |
80 // Also, don't allocate more than kMaxComparisonThreads, even if there are | 81 // Also, don't allocate more than kMaxComparisonThreads, even if there are |
81 // spare cores. | 82 // spare cores. |
82 | 83 |
83 uint32_t num_cores = CpuInfo::DetectNumberOfCores(); | 84 uint32_t num_cores = CpuInfo::DetectNumberOfCores(); |
84 RTC_DCHECK_GE(num_cores, 1u); | 85 RTC_DCHECK_GE(num_cores, 1u); |
85 static const uint32_t kMinCoresLeft = 4; | 86 static const uint32_t kMinCoresLeft = 4; |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 bool IsTextureSupported() const override { return false; } | 217 bool IsTextureSupported() const override { return false; } |
217 | 218 |
218 void Wait() { | 219 void Wait() { |
219 // Frame comparisons can be very expensive. Wait for test to be done, but | 220 // Frame comparisons can be very expensive. Wait for test to be done, but |
220 // at time-out check if frames_processed is going up. If so, give it more | 221 // at time-out check if frames_processed is going up. If so, give it more |
221 // time, otherwise fail. Hopefully this will reduce test flakiness. | 222 // time, otherwise fail. Hopefully this will reduce test flakiness. |
222 | 223 |
223 stats_polling_thread_.Start(); | 224 stats_polling_thread_.Start(); |
224 | 225 |
225 int last_frames_processed = -1; | 226 int last_frames_processed = -1; |
226 EventTypeWrapper eventType; | |
227 int iteration = 0; | 227 int iteration = 0; |
228 while ((eventType = done_->Wait(VideoQualityTest::kDefaultTimeoutMs)) != | 228 while (!done_.Wait(VideoQualityTest::kDefaultTimeoutMs)) { |
229 kEventSignaled) { | |
230 int frames_processed; | 229 int frames_processed; |
231 { | 230 { |
232 rtc::CritScope crit(&comparison_lock_); | 231 rtc::CritScope crit(&comparison_lock_); |
233 frames_processed = frames_processed_; | 232 frames_processed = frames_processed_; |
234 } | 233 } |
235 | 234 |
236 // Print some output so test infrastructure won't think we've crashed. | 235 // Print some output so test infrastructure won't think we've crashed. |
237 const char* kKeepAliveMessages[3] = { | 236 const char* kKeepAliveMessages[3] = { |
238 "Uh, I'm-I'm not quite dead, sir.", | 237 "Uh, I'm-I'm not quite dead, sir.", |
239 "Uh, I-I think uh, I could pull through, sir.", | 238 "Uh, I-I think uh, I could pull through, sir.", |
240 "Actually, I think I'm all right to come with you--"}; | 239 "Actually, I think I'm all right to come with you--"}; |
241 printf("- %s\n", kKeepAliveMessages[iteration++ % 3]); | 240 printf("- %s\n", kKeepAliveMessages[iteration++ % 3]); |
242 | 241 |
243 if (last_frames_processed == -1) { | 242 if (last_frames_processed == -1) { |
244 last_frames_processed = frames_processed; | 243 last_frames_processed = frames_processed; |
245 continue; | 244 continue; |
246 } | 245 } |
247 ASSERT_GT(frames_processed, last_frames_processed) | 246 ASSERT_GT(frames_processed, last_frames_processed) |
248 << "Analyzer stalled while waiting for test to finish."; | 247 << "Analyzer stalled while waiting for test to finish."; |
249 last_frames_processed = frames_processed; | 248 last_frames_processed = frames_processed; |
250 } | 249 } |
251 | 250 |
252 if (iteration > 0) | 251 if (iteration > 0) |
253 printf("- Farewell, sweet Concorde!\n"); | 252 printf("- Farewell, sweet Concorde!\n"); |
254 | 253 |
255 // Signal stats polling thread if that is still waiting and stop it now, | 254 // Signal stats polling thread if that is still waiting and stop it now, |
256 // since it uses the send_stream_ reference that might be reclaimed after | 255 // since it uses the send_stream_ reference that might be reclaimed after |
257 // returning from this method. | 256 // returning from this method. |
258 done_->Set(); | 257 done_.Set(); |
259 stats_polling_thread_.Stop(); | 258 stats_polling_thread_.Stop(); |
260 } | 259 } |
261 | 260 |
262 VideoCaptureInput* input_; | 261 VideoCaptureInput* input_; |
263 test::LayerFilteringTransport* const transport_; | 262 test::LayerFilteringTransport* const transport_; |
264 PacketReceiver* receiver_; | 263 PacketReceiver* receiver_; |
265 VideoSendStream* send_stream_; | 264 VideoSendStream* send_stream_; |
266 | 265 |
267 private: | 266 private: |
268 struct FrameComparison { | 267 struct FrameComparison { |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
345 | 344 |
346 VideoFrame reference_copy; | 345 VideoFrame reference_copy; |
347 VideoFrame render_copy; | 346 VideoFrame render_copy; |
348 reference_copy.CopyFrame(reference); | 347 reference_copy.CopyFrame(reference); |
349 render_copy.CopyFrame(render); | 348 render_copy.CopyFrame(render); |
350 | 349 |
351 rtc::CritScope crit(&comparison_lock_); | 350 rtc::CritScope crit(&comparison_lock_); |
352 comparisons_.push_back(FrameComparison(reference_copy, render_copy, dropped, | 351 comparisons_.push_back(FrameComparison(reference_copy, render_copy, dropped, |
353 send_time_ms, recv_time_ms, | 352 send_time_ms, recv_time_ms, |
354 render_time_ms, encoded_size)); | 353 render_time_ms, encoded_size)); |
355 comparison_available_event_->Set(); | 354 comparison_available_event_.Set(); |
356 } | 355 } |
357 | 356 |
358 static bool PollStatsThread(void* obj) { | 357 static bool PollStatsThread(void* obj) { |
359 return static_cast<VideoAnalyzer*>(obj)->PollStats(); | 358 return static_cast<VideoAnalyzer*>(obj)->PollStats(); |
360 } | 359 } |
361 | 360 |
362 bool PollStats() { | 361 bool PollStats() { |
363 switch (done_->Wait(kSendStatsPollingIntervalMs)) { | 362 if (done_.Wait(kSendStatsPollingIntervalMs)) { |
364 case kEventSignaled: | 363 // Set event again to make sure main thread is also signaled, then we're |
365 case kEventError: | 364 // done. |
366 done_->Set(); // Make sure main thread is also signaled. | 365 done_.Set(); |
367 return false; | 366 return false; |
368 case kEventTimeout: | |
369 break; | |
370 default: | |
371 RTC_NOTREACHED(); | |
372 } | 367 } |
373 | 368 |
374 VideoSendStream::Stats stats = send_stream_->GetStats(); | 369 VideoSendStream::Stats stats = send_stream_->GetStats(); |
375 | 370 |
376 rtc::CritScope crit(&comparison_lock_); | 371 rtc::CritScope crit(&comparison_lock_); |
377 encode_frame_rate_.AddSample(stats.encode_frame_rate); | 372 encode_frame_rate_.AddSample(stats.encode_frame_rate); |
378 encode_time_ms.AddSample(stats.avg_encode_time_ms); | 373 encode_time_ms.AddSample(stats.avg_encode_time_ms); |
379 encode_usage_percent.AddSample(stats.encode_usage_percent); | 374 encode_usage_percent.AddSample(stats.encode_usage_percent); |
380 media_bitrate_bps.AddSample(stats.media_bitrate_bps); | 375 media_bitrate_bps.AddSample(stats.media_bitrate_bps); |
381 | 376 |
382 return true; | 377 return true; |
383 } | 378 } |
384 | 379 |
385 static bool FrameComparisonThread(void* obj) { | 380 static bool FrameComparisonThread(void* obj) { |
386 return static_cast<VideoAnalyzer*>(obj)->CompareFrames(); | 381 return static_cast<VideoAnalyzer*>(obj)->CompareFrames(); |
387 } | 382 } |
388 | 383 |
389 bool CompareFrames() { | 384 bool CompareFrames() { |
390 if (AllFramesRecorded()) | 385 if (AllFramesRecorded()) |
391 return false; | 386 return false; |
392 | 387 |
393 VideoFrame reference; | 388 VideoFrame reference; |
394 VideoFrame render; | 389 VideoFrame render; |
395 FrameComparison comparison; | 390 FrameComparison comparison; |
396 | 391 |
397 if (!PopComparison(&comparison)) { | 392 if (!PopComparison(&comparison)) { |
398 // Wait until new comparison task is available, or test is done. | 393 // Wait until new comparison task is available, or test is done. |
399 // If done, wake up remaining threads waiting. | 394 // If done, wake up remaining threads waiting. |
400 comparison_available_event_->Wait(1000); | 395 comparison_available_event_.Wait(1000); |
401 if (AllFramesRecorded()) { | 396 if (AllFramesRecorded()) { |
402 comparison_available_event_->Set(); | 397 comparison_available_event_.Set(); |
403 return false; | 398 return false; |
404 } | 399 } |
405 return true; // Try again. | 400 return true; // Try again. |
406 } | 401 } |
407 | 402 |
408 PerformFrameComparison(comparison); | 403 PerformFrameComparison(comparison); |
409 | 404 |
410 if (FrameProcessed()) { | 405 if (FrameProcessed()) { |
411 PrintResults(); | 406 PrintResults(); |
412 if (graph_data_output_file_) | 407 if (graph_data_output_file_) |
413 PrintSamplesToFile(); | 408 PrintSamplesToFile(); |
414 done_->Set(); | 409 done_.Set(); |
415 comparison_available_event_->Set(); | 410 comparison_available_event_.Set(); |
416 return false; | 411 return false; |
417 } | 412 } |
418 | 413 |
419 return true; | 414 return true; |
420 } | 415 } |
421 | 416 |
422 bool PopComparison(FrameComparison* comparison) { | 417 bool PopComparison(FrameComparison* comparison) { |
423 rtc::CritScope crit(&comparison_lock_); | 418 rtc::CritScope crit(&comparison_lock_); |
424 // If AllFramesRecorded() is true, it means we have already popped | 419 // If AllFramesRecorded() is true, it means we have already popped |
425 // frames_to_process_ frames from comparisons_, so there is no more work | 420 // frames_to_process_ frames from comparisons_, so there is no more work |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
596 std::map<uint32_t, int64_t> send_times_ GUARDED_BY(crit_); | 591 std::map<uint32_t, int64_t> send_times_ GUARDED_BY(crit_); |
597 std::map<uint32_t, int64_t> recv_times_ GUARDED_BY(crit_); | 592 std::map<uint32_t, int64_t> recv_times_ GUARDED_BY(crit_); |
598 std::map<uint32_t, size_t> encoded_frame_sizes_ GUARDED_BY(crit_); | 593 std::map<uint32_t, size_t> encoded_frame_sizes_ GUARDED_BY(crit_); |
599 VideoFrame first_send_frame_ GUARDED_BY(crit_); | 594 VideoFrame first_send_frame_ GUARDED_BY(crit_); |
600 const double avg_psnr_threshold_; | 595 const double avg_psnr_threshold_; |
601 const double avg_ssim_threshold_; | 596 const double avg_ssim_threshold_; |
602 | 597 |
603 rtc::CriticalSection comparison_lock_; | 598 rtc::CriticalSection comparison_lock_; |
604 std::vector<rtc::PlatformThread*> comparison_thread_pool_; | 599 std::vector<rtc::PlatformThread*> comparison_thread_pool_; |
605 rtc::PlatformThread stats_polling_thread_; | 600 rtc::PlatformThread stats_polling_thread_; |
606 const rtc::scoped_ptr<EventWrapper> comparison_available_event_; | 601 rtc::Event comparison_available_event_; |
607 std::deque<FrameComparison> comparisons_ GUARDED_BY(comparison_lock_); | 602 std::deque<FrameComparison> comparisons_ GUARDED_BY(comparison_lock_); |
608 const rtc::scoped_ptr<EventWrapper> done_; | 603 rtc::Event done_; |
609 }; | 604 }; |
610 | 605 |
611 VideoQualityTest::VideoQualityTest() : clock_(Clock::GetRealTimeClock()) {} | 606 VideoQualityTest::VideoQualityTest() : clock_(Clock::GetRealTimeClock()) {} |
612 | 607 |
613 void VideoQualityTest::TestBody() {} | 608 void VideoQualityTest::TestBody() {} |
614 | 609 |
615 std::string VideoQualityTest::GenerateGraphTitle() const { | 610 std::string VideoQualityTest::GenerateGraphTitle() const { |
616 std::stringstream ss; | 611 std::stringstream ss; |
617 ss << params_.common.codec; | 612 ss << params_.common.codec; |
618 ss << " (" << params_.common.target_bitrate_bps / 1000 << "kbps"; | 613 ss << " (" << params_.common.target_bitrate_bps / 1000 << "kbps"; |
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1066 send_stream_->Stop(); | 1061 send_stream_->Stop(); |
1067 receive_stream->Stop(); | 1062 receive_stream->Stop(); |
1068 | 1063 |
1069 call->DestroyVideoReceiveStream(receive_stream); | 1064 call->DestroyVideoReceiveStream(receive_stream); |
1070 call->DestroyVideoSendStream(send_stream_); | 1065 call->DestroyVideoSendStream(send_stream_); |
1071 | 1066 |
1072 transport.StopSending(); | 1067 transport.StopSending(); |
1073 } | 1068 } |
1074 | 1069 |
1075 } // namespace webrtc | 1070 } // namespace webrtc |
OLD | NEW |