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> |
(...skipping 25 matching lines...) Expand all Loading... | |
36 | 36 |
37 namespace webrtc { | 37 namespace webrtc { |
38 | 38 |
39 static const int kSendStatsPollingIntervalMs = 1000; | 39 static const int kSendStatsPollingIntervalMs = 1000; |
40 static const int kPayloadTypeH264 = 122; | 40 static const int kPayloadTypeH264 = 122; |
41 static const int kPayloadTypeVP8 = 123; | 41 static const int kPayloadTypeVP8 = 123; |
42 static const int kPayloadTypeVP9 = 124; | 42 static const int kPayloadTypeVP9 = 124; |
43 | 43 |
44 class VideoAnalyzer : public PacketReceiver, | 44 class VideoAnalyzer : public PacketReceiver, |
45 public Transport, | 45 public Transport, |
46 public I420FrameCallback, | |
46 public VideoRenderer, | 47 public VideoRenderer, |
47 public VideoCaptureInput, | 48 public VideoCaptureInput, |
48 public EncodedFrameObserver { | 49 public EncodedFrameObserver { |
49 public: | 50 public: |
50 VideoAnalyzer(test::LayerFilteringTransport* transport, | 51 VideoAnalyzer(test::LayerFilteringTransport* transport, |
51 const std::string& test_label, | 52 const std::string& test_label, |
52 double avg_psnr_threshold, | 53 double avg_psnr_threshold, |
53 double avg_ssim_threshold, | 54 double avg_ssim_threshold, |
54 int duration_frames, | 55 int duration_frames, |
55 FILE* graph_data_output_file, | 56 FILE* graph_data_output_file, |
56 const std::string& graph_title, | 57 const std::string& graph_title, |
57 uint32_t ssrc_to_analyze) | 58 uint32_t ssrc_to_analyze) |
58 : input_(nullptr), | 59 : input_(nullptr), |
59 transport_(transport), | 60 transport_(transport), |
60 receiver_(nullptr), | 61 receiver_(nullptr), |
61 send_stream_(nullptr), | 62 send_stream_(nullptr), |
62 test_label_(test_label), | 63 test_label_(test_label), |
63 graph_data_output_file_(graph_data_output_file), | 64 graph_data_output_file_(graph_data_output_file), |
64 graph_title_(graph_title), | 65 graph_title_(graph_title), |
65 ssrc_to_analyze_(ssrc_to_analyze), | 66 ssrc_to_analyze_(ssrc_to_analyze), |
66 encode_timing_proxy_(this), | 67 encode_timing_proxy_(this), |
67 frames_to_process_(duration_frames), | 68 frames_to_process_(duration_frames), |
68 frames_recorded_(0), | 69 frames_recorded_(0), |
69 frames_processed_(0), | 70 frames_processed_(0), |
70 dropped_frames_(0), | 71 dropped_frames_(0), |
72 dropped_frames_before_first_encode_(0), | |
73 dropped_frames_before_rendering_(0), | |
71 last_render_time_(0), | 74 last_render_time_(0), |
72 rtp_timestamp_delta_(0), | 75 rtp_timestamp_delta_(0), |
73 avg_psnr_threshold_(avg_psnr_threshold), | 76 avg_psnr_threshold_(avg_psnr_threshold), |
74 avg_ssim_threshold_(avg_ssim_threshold), | 77 avg_ssim_threshold_(avg_ssim_threshold), |
75 stats_polling_thread_(&PollStatsThread, this, "StatsPoller"), | 78 stats_polling_thread_(&PollStatsThread, this, "StatsPoller"), |
76 comparison_available_event_(false, false), | 79 comparison_available_event_(false, false), |
77 done_(true, false) { | 80 done_(true, false) { |
78 // Create thread pool for CPU-expensive PSNR/SSIM calculations. | 81 // Create thread pool for CPU-expensive PSNR/SSIM calculations. |
79 | 82 |
80 // Try to use about as many threads as cores, but leave kMinCoresLeft alone, | 83 // Try to use about as many threads as cores, but leave kMinCoresLeft alone, |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
129 } | 132 } |
130 | 133 |
131 void MeasuredEncodeTiming(int64_t ntp_time_ms, int encode_time_ms) { | 134 void MeasuredEncodeTiming(int64_t ntp_time_ms, int encode_time_ms) { |
132 rtc::CritScope crit(&comparison_lock_); | 135 rtc::CritScope crit(&comparison_lock_); |
133 samples_encode_time_ms_[ntp_time_ms] = encode_time_ms; | 136 samples_encode_time_ms_[ntp_time_ms] = encode_time_ms; |
134 } | 137 } |
135 | 138 |
136 void IncomingCapturedFrame(const VideoFrame& video_frame) override { | 139 void IncomingCapturedFrame(const VideoFrame& video_frame) override { |
137 VideoFrame copy = video_frame; | 140 VideoFrame copy = video_frame; |
138 copy.set_timestamp(copy.ntp_time_ms() * 90); | 141 copy.set_timestamp(copy.ntp_time_ms() * 90); |
139 | |
140 { | 142 { |
141 rtc::CritScope lock(&crit_); | 143 rtc::CritScope lock(&crit_); |
142 if (first_send_frame_.IsZeroSize() && rtp_timestamp_delta_ == 0) | |
143 first_send_frame_ = copy; | |
144 | |
145 frames_.push_back(copy); | 144 frames_.push_back(copy); |
146 } | 145 } |
147 | 146 |
148 input_->IncomingCapturedFrame(video_frame); | 147 input_->IncomingCapturedFrame(video_frame); |
149 } | 148 } |
150 | 149 |
150 void FrameCallback(VideoFrame* video_frame) { | |
151 rtc::CritScope lock(&crit_); | |
152 if (first_send_frame_.IsZeroSize() && rtp_timestamp_delta_ == 0) { | |
153 while (frames_.front().timestamp() != video_frame->timestamp()) { | |
154 ++dropped_frames_before_first_encode_; | |
155 frames_.pop_front(); | |
156 RTC_CHECK(!frames_.empty()); | |
157 } | |
158 first_send_frame_ = *video_frame; | |
159 } | |
160 } | |
161 | |
151 bool SendRtp(const uint8_t* packet, | 162 bool SendRtp(const uint8_t* packet, |
152 size_t length, | 163 size_t length, |
153 const PacketOptions& options) override { | 164 const PacketOptions& options) override { |
154 RtpUtility::RtpHeaderParser parser(packet, length); | 165 RtpUtility::RtpHeaderParser parser(packet, length); |
155 RTPHeader header; | 166 RTPHeader header; |
156 parser.Parse(&header); | 167 parser.Parse(&header); |
157 | 168 |
158 int64_t current_time = | 169 int64_t current_time = |
159 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds(); | 170 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds(); |
160 bool result = transport_->SendRtp(packet, length, options); | 171 bool result = transport_->SendRtp(packet, length, options); |
161 { | 172 { |
162 rtc::CritScope lock(&crit_); | 173 rtc::CritScope lock(&crit_); |
163 int64_t timestamp = wrap_handler_.Unwrap(header.timestamp); | 174 int64_t timestamp = wrap_handler_.Unwrap(header.timestamp); |
164 | 175 |
165 if (rtp_timestamp_delta_ == 0) { | 176 if (!first_send_frame_.IsZeroSize()) { |
166 rtp_timestamp_delta_ = timestamp - first_send_frame_.timestamp(); | 177 rtp_timestamp_delta_ = timestamp - first_send_frame_.timestamp(); |
167 first_send_frame_.Reset(); | 178 first_send_frame_.Reset(); |
168 } | 179 } |
169 timestamp -= rtp_timestamp_delta_; | 180 timestamp -= rtp_timestamp_delta_; |
170 send_times_[timestamp] = current_time; | 181 send_times_[timestamp] = current_time; |
171 if (!transport_->DiscardedLastPacket() && | 182 if (!transport_->DiscardedLastPacket() && |
172 header.ssrc == ssrc_to_analyze_) { | 183 header.ssrc == ssrc_to_analyze_) { |
173 encoded_frame_sizes_[timestamp] += | 184 encoded_frame_sizes_[timestamp] += |
174 length - (header.headerLength + header.paddingLength); | 185 length - (header.headerLength + header.paddingLength); |
175 } | 186 } |
(...skipping 12 matching lines...) Expand all Loading... | |
188 } | 199 } |
189 | 200 |
190 void RenderFrame(const VideoFrame& video_frame, | 201 void RenderFrame(const VideoFrame& video_frame, |
191 int time_to_render_ms) override { | 202 int time_to_render_ms) override { |
192 int64_t render_time_ms = | 203 int64_t render_time_ms = |
193 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds(); | 204 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds(); |
194 uint32_t send_timestamp = video_frame.timestamp() - rtp_timestamp_delta_; | 205 uint32_t send_timestamp = video_frame.timestamp() - rtp_timestamp_delta_; |
195 | 206 |
196 rtc::CritScope lock(&crit_); | 207 rtc::CritScope lock(&crit_); |
197 | 208 |
198 while (frames_.front().timestamp() < send_timestamp) { | 209 while (frames_.front().timestamp() != send_timestamp) { |
210 if (last_rendered_frame_.IsZeroSize()) { | |
211 // No previous frame rendered, this one was dropped after sending but | |
212 // before rendering. | |
213 ++dropped_frames_before_rendering_; | |
214 frames_.pop_front(); | |
215 RTC_CHECK(!frames_.empty()); | |
216 continue; | |
217 } | |
199 AddFrameComparison(frames_.front(), last_rendered_frame_, true, | 218 AddFrameComparison(frames_.front(), last_rendered_frame_, true, |
200 render_time_ms); | 219 render_time_ms); |
201 frames_.pop_front(); | 220 frames_.pop_front(); |
221 RTC_DCHECK(!frames_.empty()); | |
202 } | 222 } |
203 | 223 |
204 VideoFrame reference_frame = frames_.front(); | 224 VideoFrame reference_frame = frames_.front(); |
205 frames_.pop_front(); | 225 frames_.pop_front(); |
206 assert(!reference_frame.IsZeroSize()); | 226 assert(!reference_frame.IsZeroSize()); |
207 if (send_timestamp == reference_frame.timestamp() - 1) { | 227 if (send_timestamp == reference_frame.timestamp() - 1) { |
208 // TODO(ivica): Make this work for > 2 streams. | 228 // TODO(ivica): Make this work for > 2 streams. |
209 // Look at RTPSender::BuildRTPHeader. | 229 // Look at RTPSender::BuildRTPHeader. |
210 ++send_timestamp; | 230 ++send_timestamp; |
211 } | 231 } |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
342 | 362 |
343 private: | 363 private: |
344 VideoAnalyzer* const parent_; | 364 VideoAnalyzer* const parent_; |
345 }; | 365 }; |
346 | 366 |
347 void AddFrameComparison(const VideoFrame& reference, | 367 void AddFrameComparison(const VideoFrame& reference, |
348 const VideoFrame& render, | 368 const VideoFrame& render, |
349 bool dropped, | 369 bool dropped, |
350 int64_t render_time_ms) | 370 int64_t render_time_ms) |
351 EXCLUSIVE_LOCKS_REQUIRED(crit_) { | 371 EXCLUSIVE_LOCKS_REQUIRED(crit_) { |
372 RTC_DCHECK(!render.IsZeroSize()); | |
352 int64_t reference_timestamp = wrap_handler_.Unwrap(reference.timestamp()); | 373 int64_t reference_timestamp = wrap_handler_.Unwrap(reference.timestamp()); |
353 int64_t send_time_ms = send_times_[reference_timestamp]; | 374 int64_t send_time_ms = send_times_[reference_timestamp]; |
354 send_times_.erase(reference_timestamp); | 375 send_times_.erase(reference_timestamp); |
355 int64_t recv_time_ms = recv_times_[reference_timestamp]; | 376 int64_t recv_time_ms = recv_times_[reference_timestamp]; |
356 recv_times_.erase(reference_timestamp); | 377 recv_times_.erase(reference_timestamp); |
357 | 378 |
358 // TODO(ivica): Make this work for > 2 streams. | 379 // TODO(ivica): Make this work for > 2 streams. |
359 auto it = encoded_frame_sizes_.find(reference_timestamp); | 380 auto it = encoded_frame_sizes_.find(reference_timestamp); |
360 if (it == encoded_frame_sizes_.end()) | 381 if (it == encoded_frame_sizes_.end()) |
361 it = encoded_frame_sizes_.find(reference_timestamp - 1); | 382 it = encoded_frame_sizes_.find(reference_timestamp - 1); |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
476 return frames_processed_ == frames_to_process_; | 497 return frames_processed_ == frames_to_process_; |
477 } | 498 } |
478 | 499 |
479 void PrintResults() { | 500 void PrintResults() { |
480 rtc::CritScope crit(&comparison_lock_); | 501 rtc::CritScope crit(&comparison_lock_); |
481 PrintResult("psnr", psnr_, " dB"); | 502 PrintResult("psnr", psnr_, " dB"); |
482 PrintResult("ssim", ssim_, " score"); | 503 PrintResult("ssim", ssim_, " score"); |
483 PrintResult("sender_time", sender_time_, " ms"); | 504 PrintResult("sender_time", sender_time_, " ms"); |
484 printf("RESULT dropped_frames: %s = %d frames\n", test_label_.c_str(), | 505 printf("RESULT dropped_frames: %s = %d frames\n", test_label_.c_str(), |
485 dropped_frames_); | 506 dropped_frames_); |
507 printf("RESULT dropped_frames_before_first_encode: %s = %d frames\n", | |
508 test_label_.c_str(), dropped_frames_before_first_encode_); | |
509 printf("RESULT dropped_frames_before_rendering: %s = %d frames\n", | |
510 test_label_.c_str(), dropped_frames_before_rendering_); | |
stefan-webrtc
2016/03/14 13:14:03
It's a bit weird that we mix PrintResult with prin
pbos-webrtc
2016/03/14 15:12:58
Done.
| |
486 PrintResult("receiver_time", receiver_time_, " ms"); | 511 PrintResult("receiver_time", receiver_time_, " ms"); |
487 PrintResult("total_delay_incl_network", end_to_end_, " ms"); | 512 PrintResult("total_delay_incl_network", end_to_end_, " ms"); |
488 PrintResult("time_between_rendered_frames", rendered_delta_, " ms"); | 513 PrintResult("time_between_rendered_frames", rendered_delta_, " ms"); |
489 PrintResult("encoded_frame_size", encoded_frame_size_, " bytes"); | 514 PrintResult("encoded_frame_size", encoded_frame_size_, " bytes"); |
490 PrintResult("encode_frame_rate", encode_frame_rate_, " fps"); | 515 PrintResult("encode_frame_rate", encode_frame_rate_, " fps"); |
491 PrintResult("encode_time", encode_time_ms, " ms"); | 516 PrintResult("encode_time", encode_time_ms, " ms"); |
492 PrintResult("encode_usage_percent", encode_usage_percent, " percent"); | 517 PrintResult("encode_usage_percent", encode_usage_percent, " percent"); |
493 PrintResult("media_bitrate", media_bitrate_bps, " bps"); | 518 PrintResult("media_bitrate", media_bitrate_bps, " bps"); |
494 | 519 |
495 EXPECT_GT(psnr_.Mean(), avg_psnr_threshold_); | 520 EXPECT_GT(psnr_.Mean(), avg_psnr_threshold_); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
599 test::Statistics encoded_frame_size_ GUARDED_BY(comparison_lock_); | 624 test::Statistics encoded_frame_size_ GUARDED_BY(comparison_lock_); |
600 test::Statistics encode_frame_rate_ GUARDED_BY(comparison_lock_); | 625 test::Statistics encode_frame_rate_ GUARDED_BY(comparison_lock_); |
601 test::Statistics encode_time_ms GUARDED_BY(comparison_lock_); | 626 test::Statistics encode_time_ms GUARDED_BY(comparison_lock_); |
602 test::Statistics encode_usage_percent GUARDED_BY(comparison_lock_); | 627 test::Statistics encode_usage_percent GUARDED_BY(comparison_lock_); |
603 test::Statistics media_bitrate_bps GUARDED_BY(comparison_lock_); | 628 test::Statistics media_bitrate_bps GUARDED_BY(comparison_lock_); |
604 | 629 |
605 const int frames_to_process_; | 630 const int frames_to_process_; |
606 int frames_recorded_; | 631 int frames_recorded_; |
607 int frames_processed_; | 632 int frames_processed_; |
608 int dropped_frames_; | 633 int dropped_frames_; |
634 int dropped_frames_before_first_encode_; | |
635 int dropped_frames_before_rendering_; | |
609 int64_t last_render_time_; | 636 int64_t last_render_time_; |
610 uint32_t rtp_timestamp_delta_; | 637 uint32_t rtp_timestamp_delta_; |
611 | 638 |
612 rtc::CriticalSection crit_; | 639 rtc::CriticalSection crit_; |
613 std::deque<VideoFrame> frames_ GUARDED_BY(crit_); | 640 std::deque<VideoFrame> frames_ GUARDED_BY(crit_); |
614 VideoFrame last_rendered_frame_ GUARDED_BY(crit_); | 641 VideoFrame last_rendered_frame_ GUARDED_BY(crit_); |
615 rtc::TimestampWrapAroundHandler wrap_handler_ GUARDED_BY(crit_); | 642 rtc::TimestampWrapAroundHandler wrap_handler_ GUARDED_BY(crit_); |
616 std::map<int64_t, int64_t> send_times_ GUARDED_BY(crit_); | 643 std::map<int64_t, int64_t> send_times_ GUARDED_BY(crit_); |
617 std::map<int64_t, int64_t> recv_times_ GUARDED_BY(crit_); | 644 std::map<int64_t, int64_t> recv_times_ GUARDED_BY(crit_); |
618 std::map<int64_t, size_t> encoded_frame_sizes_ GUARDED_BY(crit_); | 645 std::map<int64_t, size_t> encoded_frame_sizes_ GUARDED_BY(crit_); |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
992 params_.analyzer.test_durations_secs * params_.common.fps, | 1019 params_.analyzer.test_durations_secs * params_.common.fps, |
993 graph_data_output_file, graph_title, | 1020 graph_data_output_file, graph_title, |
994 kVideoSendSsrcs[params_.ss.selected_stream]); | 1021 kVideoSendSsrcs[params_.ss.selected_stream]); |
995 | 1022 |
996 analyzer.SetReceiver(receiver_call_->Receiver()); | 1023 analyzer.SetReceiver(receiver_call_->Receiver()); |
997 send_transport.SetReceiver(&analyzer); | 1024 send_transport.SetReceiver(&analyzer); |
998 recv_transport.SetReceiver(sender_call_->Receiver()); | 1025 recv_transport.SetReceiver(sender_call_->Receiver()); |
999 | 1026 |
1000 SetupCommon(&analyzer, &recv_transport); | 1027 SetupCommon(&analyzer, &recv_transport); |
1001 video_receive_configs_[params_.ss.selected_stream].renderer = &analyzer; | 1028 video_receive_configs_[params_.ss.selected_stream].renderer = &analyzer; |
1029 video_send_config_.pre_encode_callback = &analyzer; | |
1002 for (auto& config : video_receive_configs_) | 1030 for (auto& config : video_receive_configs_) |
1003 config.pre_decode_callback = &analyzer; | 1031 config.pre_decode_callback = &analyzer; |
1004 RTC_DCHECK(!video_send_config_.post_encode_callback); | 1032 RTC_DCHECK(!video_send_config_.post_encode_callback); |
1005 video_send_config_.post_encode_callback = analyzer.encode_timing_proxy(); | 1033 video_send_config_.post_encode_callback = analyzer.encode_timing_proxy(); |
1006 | 1034 |
1007 if (params_.screenshare.enabled) | 1035 if (params_.screenshare.enabled) |
1008 SetupScreenshare(); | 1036 SetupScreenshare(); |
1009 | 1037 |
1010 CreateVideoStreams(); | 1038 CreateVideoStreams(); |
1011 analyzer.input_ = video_send_stream_->Input(); | 1039 analyzer.input_ = video_send_stream_->Input(); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1092 video_send_stream_->Stop(); | 1120 video_send_stream_->Stop(); |
1093 receive_stream->Stop(); | 1121 receive_stream->Stop(); |
1094 | 1122 |
1095 call->DestroyVideoReceiveStream(receive_stream); | 1123 call->DestroyVideoReceiveStream(receive_stream); |
1096 call->DestroyVideoSendStream(video_send_stream_); | 1124 call->DestroyVideoSendStream(video_send_stream_); |
1097 | 1125 |
1098 transport.StopSending(); | 1126 transport.StopSending(); |
1099 } | 1127 } |
1100 | 1128 |
1101 } // namespace webrtc | 1129 } // namespace webrtc |
OLD | NEW |