Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 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 <deque> | 12 #include <deque> |
| 13 #include <map> | 13 #include <map> |
| 14 | 14 |
| 15 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
| 16 | 16 |
| 17 #include "webrtc/base/scoped_ptr.h" | 17 #include "webrtc/base/scoped_ptr.h" |
| 18 #include "webrtc/base/thread_annotations.h" | 18 #include "webrtc/base/thread_annotations.h" |
| 19 #include "webrtc/call.h" | 19 #include "webrtc/call.h" |
| 20 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" | 20 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" |
| 21 #include "webrtc/frame_callback.h" | 21 #include "webrtc/frame_callback.h" |
| 22 #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" | 22 #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" |
| 23 #include "webrtc/system_wrappers/interface/clock.h" | 23 #include "webrtc/system_wrappers/interface/clock.h" |
| 24 #include "webrtc/system_wrappers/interface/cpu_info.h" | 24 #include "webrtc/system_wrappers/interface/cpu_info.h" |
| 25 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" | 25 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" |
| 26 #include "webrtc/system_wrappers/interface/event_wrapper.h" | 26 #include "webrtc/system_wrappers/interface/event_wrapper.h" |
| 27 #include "webrtc/system_wrappers/interface/sleep.h" | 27 #include "webrtc/system_wrappers/interface/sleep.h" |
| 28 #include "webrtc/test/call_test.h" | |
| 29 #include "webrtc/test/direct_transport.h" | |
| 30 #include "webrtc/test/encoder_settings.h" | 28 #include "webrtc/test/encoder_settings.h" |
| 31 #include "webrtc/test/fake_encoder.h" | 29 #include "webrtc/test/fake_encoder.h" |
| 32 #include "webrtc/test/frame_generator.h" | 30 #include "webrtc/test/frame_generator.h" |
| 33 #include "webrtc/test/frame_generator_capturer.h" | 31 #include "webrtc/test/frame_generator_capturer.h" |
| 34 #include "webrtc/test/statistics.h" | 32 #include "webrtc/test/statistics.h" |
| 35 #include "webrtc/test/testsupport/fileutils.h" | 33 #include "webrtc/test/testsupport/fileutils.h" |
| 36 #include "webrtc/typedefs.h" | 34 #include "webrtc/typedefs.h" |
| 35 #include "webrtc/video/full_stack.h" | |
| 37 | 36 |
| 38 namespace webrtc { | 37 namespace webrtc { |
| 39 | 38 |
| 40 static const int kFullStackTestDurationSecs = 60; | 39 static const int kFullStackTestDurationSecs = 60; |
| 41 static const int kSendStatsPollingIntervalMs = 1000; | 40 static const int kSendStatsPollingIntervalMs = 1000; |
| 42 | 41 |
| 43 struct FullStackTestParams { | |
| 44 const char* test_label; | |
| 45 struct { | |
| 46 const char* name; | |
| 47 size_t width, height; | |
| 48 int fps; | |
| 49 } clip; | |
| 50 bool screenshare; | |
| 51 int min_bitrate_bps; | |
| 52 int target_bitrate_bps; | |
| 53 int max_bitrate_bps; | |
| 54 double avg_psnr_threshold; | |
| 55 double avg_ssim_threshold; | |
| 56 int test_durations_secs; | |
| 57 std::string codec; | |
| 58 FakeNetworkPipe::Config link; | |
| 59 }; | |
| 60 | |
| 61 class FullStackTest : public test::CallTest { | |
| 62 protected: | |
| 63 void RunTest(const FullStackTestParams& params); | |
| 64 }; | |
| 65 | |
| 66 class VideoAnalyzer : public PacketReceiver, | 42 class VideoAnalyzer : public PacketReceiver, |
| 67 public newapi::Transport, | 43 public newapi::Transport, |
| 68 public VideoRenderer, | 44 public VideoRenderer, |
| 69 public VideoCaptureInput, | 45 public VideoCaptureInput, |
| 70 public EncodedFrameObserver { | 46 public EncodedFrameObserver { |
| 71 public: | 47 public: |
| 72 VideoAnalyzer(VideoCaptureInput* input, | 48 VideoAnalyzer(VideoCaptureInput* input, |
| 73 Transport* transport, | 49 Transport* transport, |
| 74 const char* test_label, | 50 const char* test_label, |
| 75 double avg_psnr_threshold, | 51 double avg_psnr_threshold, |
| 76 double avg_ssim_threshold, | 52 double avg_ssim_threshold, |
| 77 int duration_frames) | 53 int duration_frames, |
| 54 const std::string& graph_data_filename) | |
| 78 : input_(input), | 55 : input_(input), |
| 79 transport_(transport), | 56 transport_(transport), |
| 80 receiver_(nullptr), | 57 receiver_(nullptr), |
| 81 send_stream_(nullptr), | 58 send_stream_(nullptr), |
| 82 test_label_(test_label), | 59 test_label_(test_label), |
| 60 save_samples_(!graph_data_filename.empty()), | |
| 61 graph_data_filename_(graph_data_filename), | |
| 83 frames_to_process_(duration_frames), | 62 frames_to_process_(duration_frames), |
| 84 frames_recorded_(0), | 63 frames_recorded_(0), |
| 85 frames_processed_(0), | 64 frames_processed_(0), |
| 86 dropped_frames_(0), | 65 dropped_frames_(0), |
| 87 last_render_time_(0), | 66 last_render_time_(0), |
| 88 rtp_timestamp_delta_(0), | 67 rtp_timestamp_delta_(0), |
| 89 avg_psnr_threshold_(avg_psnr_threshold), | 68 avg_psnr_threshold_(avg_psnr_threshold), |
| 90 avg_ssim_threshold_(avg_ssim_threshold), | 69 avg_ssim_threshold_(avg_ssim_threshold), |
| 91 comparison_available_event_(EventWrapper::Create()), | 70 comparison_available_event_(EventWrapper::Create()), |
| 92 done_(EventWrapper::Create()) { | 71 done_(EventWrapper::Create()) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 141 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds(); | 120 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds(); |
| 142 } | 121 } |
| 143 | 122 |
| 144 return receiver_->DeliverPacket(media_type, packet, length); | 123 return receiver_->DeliverPacket(media_type, packet, length); |
| 145 } | 124 } |
| 146 | 125 |
| 147 void IncomingCapturedFrame(const VideoFrame& video_frame) override { | 126 void IncomingCapturedFrame(const VideoFrame& video_frame) override { |
| 148 VideoFrame copy = video_frame; | 127 VideoFrame copy = video_frame; |
| 149 copy.set_timestamp(copy.ntp_time_ms() * 90); | 128 copy.set_timestamp(copy.ntp_time_ms() * 90); |
| 150 | 129 |
| 130 VideoSendStream::Stats stats = send_stream_->GetStats(); | |
| 151 { | 131 { |
| 152 rtc::CritScope lock(&crit_); | 132 rtc::CritScope lock(&crit_); |
| 153 if (first_send_frame_.IsZeroSize() && rtp_timestamp_delta_ == 0) | 133 if (first_send_frame_.IsZeroSize() && rtp_timestamp_delta_ == 0) |
| 154 first_send_frame_ = copy; | 134 first_send_frame_ = copy; |
| 155 | 135 |
| 156 frames_.push_back(copy); | 136 frames_.push_back(copy); |
| 137 send_stats_.push_back(stats); | |
| 157 } | 138 } |
| 158 | 139 |
| 159 input_->IncomingCapturedFrame(video_frame); | 140 input_->IncomingCapturedFrame(video_frame); |
| 160 } | 141 } |
| 161 | 142 |
| 162 bool SendRtp(const uint8_t* packet, size_t length) override { | 143 bool SendRtp(const uint8_t* packet, size_t length) override { |
| 163 rtc::scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create()); | 144 rtc::scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create()); |
| 164 RTPHeader header; | 145 RTPHeader header; |
| 165 parser->Parse(packet, length, &header); | 146 parser->Parse(packet, length, &header); |
| 166 | 147 |
| 167 { | 148 { |
| 168 rtc::CritScope lock(&crit_); | 149 rtc::CritScope lock(&crit_); |
| 169 if (rtp_timestamp_delta_ == 0) { | 150 if (rtp_timestamp_delta_ == 0) { |
| 170 rtp_timestamp_delta_ = | 151 rtp_timestamp_delta_ = |
| 171 header.timestamp - first_send_frame_.timestamp(); | 152 header.timestamp - first_send_frame_.timestamp(); |
| 172 first_send_frame_.Reset(); | 153 first_send_frame_.Reset(); |
| 173 } | 154 } |
| 174 send_times_[header.timestamp - rtp_timestamp_delta_] = | 155 uint32_t timestamp = header.timestamp - rtp_timestamp_delta_; |
| 156 send_times_[timestamp] = | |
| 175 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds(); | 157 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds(); |
| 158 encoded_frame_sizes_[timestamp] += | |
| 159 length - (header.headerLength + header.paddingLength); | |
|
sprang_webrtc
2015/08/19 13:33:37
Rebase error? This is handles by EncodedFrameCallb
ivica
2015/08/20 13:25:59
For graphs I need encoded frame size for each fram
| |
| 176 } | 160 } |
| 177 | 161 |
| 178 return transport_->SendRtp(packet, length); | 162 return transport_->SendRtp(packet, length); |
| 179 } | 163 } |
| 180 | 164 |
| 181 bool SendRtcp(const uint8_t* packet, size_t length) override { | 165 bool SendRtcp(const uint8_t* packet, size_t length) override { |
| 182 return transport_->SendRtcp(packet, length); | 166 return transport_->SendRtcp(packet, length); |
| 183 } | 167 } |
| 184 | 168 |
| 185 void EncodedFrameCallback(const EncodedFrame& frame) override { | 169 void EncodedFrameCallback(const EncodedFrame& frame) override { |
| 186 rtc::CritScope lock(&comparison_lock_); | 170 rtc::CritScope lock(&comparison_lock_); |
| 187 if (frames_recorded_ < frames_to_process_) | 171 if (frames_recorded_ < frames_to_process_) |
| 188 encoded_frame_size_.AddSample(frame.length_); | 172 encoded_frame_size_.AddSample(frame.length_); |
| 189 } | 173 } |
| 190 | 174 |
| 191 void RenderFrame(const VideoFrame& video_frame, | 175 void RenderFrame(const VideoFrame& video_frame, |
| 192 int time_to_render_ms) override { | 176 int time_to_render_ms) override { |
| 193 int64_t render_time_ms = | 177 int64_t render_time_ms = |
| 194 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds(); | 178 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds(); |
| 195 uint32_t send_timestamp = video_frame.timestamp() - rtp_timestamp_delta_; | 179 uint32_t send_timestamp = video_frame.timestamp() - rtp_timestamp_delta_; |
| 196 | 180 |
| 197 rtc::CritScope lock(&crit_); | 181 rtc::CritScope lock(&crit_); |
| 198 | 182 |
| 199 while (frames_.front().timestamp() < send_timestamp) { | 183 while (frames_.front().timestamp() < send_timestamp) { |
| 200 AddFrameComparison(frames_.front(), last_rendered_frame_, true, | 184 AddFrameComparison(frames_.front(), last_rendered_frame_, true, |
| 201 render_time_ms); | 185 render_time_ms, send_stats_.front()); |
| 202 frames_.pop_front(); | 186 frames_.pop_front(); |
| 187 send_stats_.pop_front(); | |
| 203 } | 188 } |
| 204 | 189 |
| 205 VideoFrame reference_frame = frames_.front(); | 190 VideoFrame reference_frame = frames_.front(); |
| 206 frames_.pop_front(); | 191 frames_.pop_front(); |
| 207 assert(!reference_frame.IsZeroSize()); | 192 assert(!reference_frame.IsZeroSize()); |
| 208 EXPECT_EQ(reference_frame.timestamp(), send_timestamp); | 193 EXPECT_EQ(reference_frame.timestamp(), send_timestamp); |
| 209 assert(reference_frame.timestamp() == send_timestamp); | 194 assert(reference_frame.timestamp() == send_timestamp); |
| 210 | 195 |
| 211 AddFrameComparison(reference_frame, video_frame, false, render_time_ms); | 196 AddFrameComparison(reference_frame, video_frame, false, render_time_ms, |
| 197 send_stats_.front()); | |
| 198 send_stats_.pop_front(); | |
| 212 | 199 |
| 213 last_rendered_frame_ = video_frame; | 200 last_rendered_frame_ = video_frame; |
| 214 } | 201 } |
| 215 | 202 |
| 216 bool IsTextureSupported() const override { return false; } | 203 bool IsTextureSupported() const override { return false; } |
| 217 | 204 |
| 218 void Wait() { | 205 void Wait() { |
| 219 // Frame comparisons can be very expensive. Wait for test to be done, but | 206 // 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 | 207 // 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. | 208 // time, otherwise fail. Hopefully this will reduce test flakiness. |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 246 } | 233 } |
| 247 | 234 |
| 248 VideoCaptureInput* input_; | 235 VideoCaptureInput* input_; |
| 249 Transport* transport_; | 236 Transport* transport_; |
| 250 PacketReceiver* receiver_; | 237 PacketReceiver* receiver_; |
| 251 VideoSendStream* send_stream_; | 238 VideoSendStream* send_stream_; |
| 252 | 239 |
| 253 private: | 240 private: |
| 254 struct FrameComparison { | 241 struct FrameComparison { |
| 255 FrameComparison() | 242 FrameComparison() |
| 256 : dropped(false), send_time_ms(0), recv_time_ms(0), render_time_ms(0) {} | 243 : dropped(false), |
| 244 send_time_ms(0), | |
| 245 recv_time_ms(0), | |
| 246 render_time_ms(0), | |
| 247 encoded_frame_size(0) {} | |
| 257 | 248 |
| 258 FrameComparison(const VideoFrame& reference, | 249 FrameComparison(const VideoFrame& reference, |
| 259 const VideoFrame& render, | 250 const VideoFrame& render, |
| 260 bool dropped, | 251 bool dropped, |
| 261 int64_t send_time_ms, | 252 int64_t send_time_ms, |
| 262 int64_t recv_time_ms, | 253 int64_t recv_time_ms, |
| 263 int64_t render_time_ms) | 254 int64_t render_time_ms, |
| 255 size_t encoded_frame_size, | |
| 256 const VideoSendStream::Stats& send_stats) | |
| 264 : reference(reference), | 257 : reference(reference), |
| 265 render(render), | 258 render(render), |
| 266 dropped(dropped), | 259 dropped(dropped), |
| 267 send_time_ms(send_time_ms), | 260 send_time_ms(send_time_ms), |
| 268 recv_time_ms(recv_time_ms), | 261 recv_time_ms(recv_time_ms), |
| 269 render_time_ms(render_time_ms) {} | 262 render_time_ms(render_time_ms), |
| 263 encoded_frame_size(encoded_frame_size), | |
| 264 send_stats(send_stats) {} | |
| 270 | 265 |
| 271 VideoFrame reference; | 266 VideoFrame reference; |
| 272 VideoFrame render; | 267 VideoFrame render; |
| 273 bool dropped; | 268 bool dropped; |
| 274 int64_t send_time_ms; | 269 int64_t send_time_ms; |
| 275 int64_t recv_time_ms; | 270 int64_t recv_time_ms; |
| 276 int64_t render_time_ms; | 271 int64_t render_time_ms; |
| 272 size_t encoded_frame_size; | |
| 273 VideoSendStream::Stats send_stats; | |
| 274 }; | |
| 275 | |
| 276 struct Sample { | |
| 277 Sample(double dropped, | |
| 278 double input_time_ms, | |
| 279 double send_time_ms, | |
| 280 double recv_time_ms, | |
| 281 double avg_encode_time_ms, | |
| 282 double encoded_frame_size, | |
| 283 double encode_frame_rate, | |
| 284 double encode_usage_percent, | |
| 285 double media_bitrate_bps, | |
| 286 double psnr, | |
| 287 double ssim, | |
| 288 double decoded_time_ms) | |
| 289 : dropped(dropped), | |
| 290 input_time_ms(input_time_ms), | |
| 291 send_time_ms(send_time_ms), | |
| 292 recv_time_ms(recv_time_ms), | |
| 293 avg_encode_time_ms(avg_encode_time_ms), | |
| 294 encoded_frame_size(encoded_frame_size), | |
| 295 encode_frame_rate(encode_frame_rate), | |
| 296 encode_usage_percent(encode_usage_percent), | |
| 297 media_bitrate_bps(media_bitrate_bps), | |
| 298 psnr(psnr), | |
| 299 ssim(ssim), | |
| 300 decoded_time_ms(decoded_time_ms) {} | |
| 301 | |
| 302 double dropped; | |
| 303 double input_time_ms; | |
| 304 double send_time_ms; | |
| 305 double recv_time_ms; | |
| 306 double avg_encode_time_ms; | |
| 307 double encoded_frame_size; | |
| 308 double encode_frame_rate; | |
| 309 double encode_usage_percent; | |
| 310 double media_bitrate_bps; | |
| 311 double psnr; | |
| 312 double ssim; | |
| 313 double decoded_time_ms; | |
| 277 }; | 314 }; |
| 278 | 315 |
| 279 void AddFrameComparison(const VideoFrame& reference, | 316 void AddFrameComparison(const VideoFrame& reference, |
| 280 const VideoFrame& render, | 317 const VideoFrame& render, |
| 281 bool dropped, | 318 bool dropped, |
| 282 int64_t render_time_ms) | 319 int64_t render_time_ms, |
| 320 const VideoSendStream::Stats& send_stats) | |
| 283 EXCLUSIVE_LOCKS_REQUIRED(crit_) { | 321 EXCLUSIVE_LOCKS_REQUIRED(crit_) { |
| 284 int64_t send_time_ms = send_times_[reference.timestamp()]; | 322 int64_t send_time_ms = send_times_[reference.timestamp()]; |
| 285 send_times_.erase(reference.timestamp()); | 323 send_times_.erase(reference.timestamp()); |
| 286 int64_t recv_time_ms = recv_times_[reference.timestamp()]; | 324 int64_t recv_time_ms = recv_times_[reference.timestamp()]; |
| 287 recv_times_.erase(reference.timestamp()); | 325 recv_times_.erase(reference.timestamp()); |
| 288 | 326 |
| 327 size_t encoded_size = encoded_frame_sizes_[reference.timestamp()]; | |
| 328 encoded_frame_sizes_.erase(reference.timestamp()); | |
| 329 | |
| 330 VideoFrame reference_copy; | |
| 331 VideoFrame render_copy; | |
| 332 reference_copy.CopyFrame(reference); | |
| 333 render_copy.CopyFrame(render); | |
| 334 | |
| 289 rtc::CritScope crit(&comparison_lock_); | 335 rtc::CritScope crit(&comparison_lock_); |
| 290 comparisons_.push_back(FrameComparison(reference, render, dropped, | 336 comparisons_.push_back(FrameComparison( |
| 291 send_time_ms, recv_time_ms, | 337 reference_copy, render_copy, dropped, send_time_ms, recv_time_ms, |
| 292 render_time_ms)); | 338 render_time_ms, encoded_size, send_stats)); |
| 293 comparison_available_event_->Set(); | 339 comparison_available_event_->Set(); |
| 294 } | 340 } |
| 295 | 341 |
| 296 static bool PollStatsThread(void* obj) { | 342 static bool PollStatsThread(void* obj) { |
| 297 return static_cast<VideoAnalyzer*>(obj)->PollStats(); | 343 return static_cast<VideoAnalyzer*>(obj)->PollStats(); |
| 298 } | 344 } |
| 299 | 345 |
| 300 bool PollStats() { | 346 bool PollStats() { |
| 301 switch (done_->Wait(kSendStatsPollingIntervalMs)) { | 347 switch (done_->Wait(kSendStatsPollingIntervalMs)) { |
| 302 case kEventSignaled: | 348 case kEventSignaled: |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 340 comparison_available_event_->Set(); | 386 comparison_available_event_->Set(); |
| 341 return false; | 387 return false; |
| 342 } | 388 } |
| 343 return true; // Try again. | 389 return true; // Try again. |
| 344 } | 390 } |
| 345 | 391 |
| 346 PerformFrameComparison(comparison); | 392 PerformFrameComparison(comparison); |
| 347 | 393 |
| 348 if (FrameProcessed()) { | 394 if (FrameProcessed()) { |
| 349 PrintResults(); | 395 PrintResults(); |
| 396 if (save_samples_) { | |
| 397 PrintSamplesToFile(); | |
| 398 } | |
|
sprang_webrtc
2015/08/19 13:33:37
Remove braces
ivica
2015/08/20 13:25:59
Done.
| |
| 350 done_->Set(); | 399 done_->Set(); |
| 351 comparison_available_event_->Set(); | 400 comparison_available_event_->Set(); |
| 352 return false; | 401 return false; |
| 353 } | 402 } |
| 354 | 403 |
| 355 return true; | 404 return true; |
| 356 } | 405 } |
| 357 | 406 |
| 358 bool PopComparison(FrameComparison* comparison) { | 407 bool PopComparison(FrameComparison* comparison) { |
| 359 rtc::CritScope crit(&comparison_lock_); | 408 rtc::CritScope crit(&comparison_lock_); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 412 | 461 |
| 413 EXPECT_GT(psnr_.Mean(), avg_psnr_threshold_); | 462 EXPECT_GT(psnr_.Mean(), avg_psnr_threshold_); |
| 414 EXPECT_GT(ssim_.Mean(), avg_ssim_threshold_); | 463 EXPECT_GT(ssim_.Mean(), avg_ssim_threshold_); |
| 415 } | 464 } |
| 416 | 465 |
| 417 void PerformFrameComparison(const FrameComparison& comparison) { | 466 void PerformFrameComparison(const FrameComparison& comparison) { |
| 418 // Perform expensive psnr and ssim calculations while not holding lock. | 467 // Perform expensive psnr and ssim calculations while not holding lock. |
| 419 double psnr = I420PSNR(&comparison.reference, &comparison.render); | 468 double psnr = I420PSNR(&comparison.reference, &comparison.render); |
| 420 double ssim = I420SSIM(&comparison.reference, &comparison.render); | 469 double ssim = I420SSIM(&comparison.reference, &comparison.render); |
| 421 | 470 |
| 471 int64_t input_time_ms = comparison.reference.ntp_time_ms(); | |
| 472 Sample sample( | |
| 473 comparison.dropped, input_time_ms, comparison.send_time_ms, | |
| 474 comparison.recv_time_ms, comparison.send_stats.avg_encode_time_ms, | |
| 475 comparison.encoded_frame_size, comparison.send_stats.encode_frame_rate, | |
| 476 comparison.send_stats.encode_usage_percent, | |
| 477 comparison.send_stats.media_bitrate_bps, psnr, ssim, | |
| 478 comparison.render_time_ms); // decoded_time_ms | |
|
sprang_webrtc
2015/08/19 13:33:37
I don't think comparison.send_stats is available h
ivica
2015/08/20 13:25:59
Removed. Can be added later if necessary.
| |
| 479 | |
| 422 rtc::CritScope crit(&comparison_lock_); | 480 rtc::CritScope crit(&comparison_lock_); |
| 481 if (save_samples_) { | |
| 482 samples_.push_back(sample); | |
| 483 } | |
| 423 psnr_.AddSample(psnr); | 484 psnr_.AddSample(psnr); |
| 424 ssim_.AddSample(ssim); | 485 ssim_.AddSample(ssim); |
| 486 | |
| 425 if (comparison.dropped) { | 487 if (comparison.dropped) { |
| 426 ++dropped_frames_; | 488 ++dropped_frames_; |
| 427 return; | 489 return; |
| 428 } | 490 } |
| 429 if (last_render_time_ != 0) | 491 if (last_render_time_ != 0) |
| 430 rendered_delta_.AddSample(comparison.render_time_ms - last_render_time_); | 492 rendered_delta_.AddSample(comparison.render_time_ms - last_render_time_); |
| 431 last_render_time_ = comparison.render_time_ms; | 493 last_render_time_ = comparison.render_time_ms; |
| 432 | 494 |
| 433 int64_t input_time_ms = comparison.reference.ntp_time_ms(); | |
| 434 sender_time_.AddSample(comparison.send_time_ms - input_time_ms); | 495 sender_time_.AddSample(comparison.send_time_ms - input_time_ms); |
| 435 receiver_time_.AddSample(comparison.render_time_ms - | 496 receiver_time_.AddSample(comparison.render_time_ms - |
| 436 comparison.recv_time_ms); | 497 comparison.recv_time_ms); |
| 437 end_to_end_.AddSample(comparison.render_time_ms - input_time_ms); | 498 end_to_end_.AddSample(comparison.render_time_ms - input_time_ms); |
| 499 encoded_frame_size_.AddSample(comparison.encoded_frame_size); | |
| 438 } | 500 } |
| 439 | 501 |
| 440 void PrintResult(const char* result_type, | 502 void PrintResult(const char* result_type, |
| 441 test::Statistics stats, | 503 test::Statistics stats, |
| 442 const char* unit) { | 504 const char* unit) { |
| 443 printf("RESULT %s: %s = {%f, %f}%s\n", | 505 printf("RESULT %s: %s = {%f, %f}%s\n", |
| 444 result_type, | 506 result_type, |
| 445 test_label_, | 507 test_label_, |
| 446 stats.Mean(), | 508 stats.Mean(), |
| 447 stats.StandardDeviation(), | 509 stats.StandardDeviation(), |
| 448 unit); | 510 unit); |
| 449 } | 511 } |
| 450 | 512 |
| 513 void PrintSamplesToFile(void) { | |
| 514 FILE* f = fopen(graph_data_filename_.c_str(), "w"); | |
| 515 if (f == NULL) { | |
| 516 fprintf(stderr, "Couldn't open file %s\n", graph_data_filename_.c_str()); | |
| 517 abort(); | |
| 518 } | |
| 519 | |
| 520 rtc::CritScope crit(&comparison_lock_); | |
| 521 std::sort(samples_.begin(), samples_.end(), | |
| 522 [](const Sample& A, const Sample& B) | |
| 523 -> bool { return A.input_time_ms < B.input_time_ms; }); | |
| 524 | |
| 525 fprintf(f, "%s\n", test_label_); | |
| 526 fprintf(f, "%d\n", (int)samples_.size()); | |
|
sprang_webrtc
2015/08/19 13:33:37
Use static_cast rather than c-style cast.
Or just
ivica
2015/08/20 13:25:59
Using %" PRIuS " as described in style guide...
| |
| 527 #define PRINT_SAMPLES(field) \ | |
| 528 { \ | |
| 529 fprintf(f, "%s ", #field); \ | |
| 530 for (Sample & value : samples_) { \ | |
| 531 fprintf(f, "%lf ", value.field); \ | |
| 532 } \ | |
| 533 fprintf(f, "\n"); \ | |
| 534 } | |
|
sprang_webrtc
2015/08/19 13:33:37
Macros are unfortunately only allowed in some very
ivica
2015/08/20 13:25:59
Changed from one-field-one-row to one-field-one-co
| |
| 535 PRINT_SAMPLES(dropped); | |
| 536 PRINT_SAMPLES(input_time_ms); | |
| 537 PRINT_SAMPLES(send_time_ms); | |
| 538 PRINT_SAMPLES(recv_time_ms); | |
| 539 PRINT_SAMPLES(avg_encode_time_ms); | |
| 540 PRINT_SAMPLES(encoded_frame_size); | |
| 541 PRINT_SAMPLES(encode_frame_rate); | |
| 542 PRINT_SAMPLES(encode_usage_percent); | |
| 543 PRINT_SAMPLES(media_bitrate_bps); | |
| 544 PRINT_SAMPLES(psnr); | |
| 545 PRINT_SAMPLES(ssim); | |
| 546 PRINT_SAMPLES(decoded_time_ms); | |
| 547 #undef PRINT_SAMPLES | |
| 548 | |
| 549 // Add an end specifier, to be able to add comments to the end of file if | |
| 550 // necessary. | |
| 551 fprintf(f, "--END--\n"); | |
| 552 fclose(f); | |
| 553 } | |
| 554 | |
| 451 const char* const test_label_; | 555 const char* const test_label_; |
| 556 bool save_samples_; | |
|
sprang_webrtc
2015/08/19 13:33:37
Not sure this is necessary. Calling graph_data_fil
ivica
2015/08/20 13:25:59
Removed.
| |
| 557 std::string graph_data_filename_; | |
| 558 std::vector<Sample> samples_ GUARDED_BY(comparison_lock_); | |
| 452 test::Statistics sender_time_ GUARDED_BY(comparison_lock_); | 559 test::Statistics sender_time_ GUARDED_BY(comparison_lock_); |
| 453 test::Statistics receiver_time_ GUARDED_BY(comparison_lock_); | 560 test::Statistics receiver_time_ GUARDED_BY(comparison_lock_); |
| 454 test::Statistics psnr_ GUARDED_BY(comparison_lock_); | 561 test::Statistics psnr_ GUARDED_BY(comparison_lock_); |
| 455 test::Statistics ssim_ GUARDED_BY(comparison_lock_); | 562 test::Statistics ssim_ GUARDED_BY(comparison_lock_); |
| 456 test::Statistics end_to_end_ GUARDED_BY(comparison_lock_); | 563 test::Statistics end_to_end_ GUARDED_BY(comparison_lock_); |
| 457 test::Statistics rendered_delta_ GUARDED_BY(comparison_lock_); | 564 test::Statistics rendered_delta_ GUARDED_BY(comparison_lock_); |
| 458 test::Statistics encoded_frame_size_ GUARDED_BY(comparison_lock_); | 565 test::Statistics encoded_frame_size_ GUARDED_BY(comparison_lock_); |
| 459 test::Statistics encode_frame_rate_ GUARDED_BY(comparison_lock_); | 566 test::Statistics encode_frame_rate_ GUARDED_BY(comparison_lock_); |
| 460 test::Statistics encode_time_ms GUARDED_BY(comparison_lock_); | 567 test::Statistics encode_time_ms GUARDED_BY(comparison_lock_); |
| 461 test::Statistics encode_usage_percent GUARDED_BY(comparison_lock_); | 568 test::Statistics encode_usage_percent GUARDED_BY(comparison_lock_); |
| 462 test::Statistics media_bitrate_bps GUARDED_BY(comparison_lock_); | 569 test::Statistics media_bitrate_bps GUARDED_BY(comparison_lock_); |
| 463 | 570 |
| 464 const int frames_to_process_; | 571 const int frames_to_process_; |
| 465 int frames_recorded_; | 572 int frames_recorded_; |
| 466 int frames_processed_; | 573 int frames_processed_; |
| 467 int dropped_frames_; | 574 int dropped_frames_; |
| 468 int64_t last_render_time_; | 575 int64_t last_render_time_; |
| 469 uint32_t rtp_timestamp_delta_; | 576 uint32_t rtp_timestamp_delta_; |
| 470 | 577 |
| 471 rtc::CriticalSection crit_; | 578 rtc::CriticalSection crit_; |
| 472 std::deque<VideoFrame> frames_ GUARDED_BY(crit_); | 579 std::deque<VideoFrame> frames_ GUARDED_BY(crit_); |
| 580 std::deque<VideoSendStream::Stats> send_stats_ GUARDED_BY(crit_); | |
| 473 VideoFrame last_rendered_frame_ GUARDED_BY(crit_); | 581 VideoFrame last_rendered_frame_ GUARDED_BY(crit_); |
| 474 std::map<uint32_t, int64_t> send_times_ GUARDED_BY(crit_); | 582 std::map<uint32_t, int64_t> send_times_ GUARDED_BY(crit_); |
| 475 std::map<uint32_t, int64_t> recv_times_ GUARDED_BY(crit_); | 583 std::map<uint32_t, int64_t> recv_times_ GUARDED_BY(crit_); |
| 584 std::map<uint32_t, size_t> encoded_frame_sizes_ GUARDED_BY(crit_); | |
| 476 VideoFrame first_send_frame_ GUARDED_BY(crit_); | 585 VideoFrame first_send_frame_ GUARDED_BY(crit_); |
| 477 const double avg_psnr_threshold_; | 586 const double avg_psnr_threshold_; |
| 478 const double avg_ssim_threshold_; | 587 const double avg_ssim_threshold_; |
| 479 | 588 |
| 480 rtc::CriticalSection comparison_lock_; | 589 rtc::CriticalSection comparison_lock_; |
| 481 std::vector<ThreadWrapper*> comparison_thread_pool_; | 590 std::vector<ThreadWrapper*> comparison_thread_pool_; |
| 482 rtc::scoped_ptr<ThreadWrapper> stats_polling_thread_; | 591 rtc::scoped_ptr<ThreadWrapper> stats_polling_thread_; |
| 483 const rtc::scoped_ptr<EventWrapper> comparison_available_event_; | 592 const rtc::scoped_ptr<EventWrapper> comparison_available_event_; |
| 484 std::deque<FrameComparison> comparisons_ GUARDED_BY(comparison_lock_); | 593 std::deque<FrameComparison> comparisons_ GUARDED_BY(comparison_lock_); |
| 485 const rtc::scoped_ptr<EventWrapper> done_; | 594 const rtc::scoped_ptr<EventWrapper> done_; |
| 486 }; | 595 }; |
| 487 | 596 |
| 488 void FullStackTest::RunTest(const FullStackTestParams& params) { | 597 void FullStackTest::RunTest(const FullStackTestParams& params) { |
| 598 // TODO(ivica): Add num_temporal_layers as a param. | |
| 599 unsigned char num_temporal_layers = | |
| 600 params.graph_data_filename.empty() ? 2 : 1; | |
| 601 | |
| 489 test::DirectTransport send_transport(params.link); | 602 test::DirectTransport send_transport(params.link); |
| 490 test::DirectTransport recv_transport(params.link); | 603 test::DirectTransport recv_transport(params.link); |
| 491 VideoAnalyzer analyzer(nullptr, &send_transport, params.test_label, | 604 VideoAnalyzer analyzer(nullptr, &send_transport, params.test_label, |
| 492 params.avg_psnr_threshold, params.avg_ssim_threshold, | 605 params.avg_psnr_threshold, params.avg_ssim_threshold, |
| 493 params.test_durations_secs * params.clip.fps); | 606 params.test_durations_secs * params.clip.fps, |
| 607 params.graph_data_filename); | |
| 494 | 608 |
| 495 CreateCalls(Call::Config(&analyzer), Call::Config(&recv_transport)); | 609 CreateCalls(Call::Config(&analyzer), Call::Config(&recv_transport)); |
| 496 | 610 |
| 497 analyzer.SetReceiver(receiver_call_->Receiver()); | 611 analyzer.SetReceiver(receiver_call_->Receiver()); |
| 498 send_transport.SetReceiver(&analyzer); | 612 send_transport.SetReceiver(&analyzer); |
| 499 recv_transport.SetReceiver(sender_call_->Receiver()); | 613 recv_transport.SetReceiver(sender_call_->Receiver()); |
| 500 | 614 |
| 501 CreateSendConfig(1); | 615 CreateSendConfig(1); |
| 502 | 616 |
| 503 rtc::scoped_ptr<VideoEncoder> encoder; | 617 rtc::scoped_ptr<VideoEncoder> encoder; |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 531 | 645 |
| 532 VideoCodecVP8 vp8_settings; | 646 VideoCodecVP8 vp8_settings; |
| 533 VideoCodecVP9 vp9_settings; | 647 VideoCodecVP9 vp9_settings; |
| 534 if (params.screenshare) { | 648 if (params.screenshare) { |
| 535 encoder_config_.content_type = VideoEncoderConfig::ContentType::kScreen; | 649 encoder_config_.content_type = VideoEncoderConfig::ContentType::kScreen; |
| 536 encoder_config_.min_transmit_bitrate_bps = 400 * 1000; | 650 encoder_config_.min_transmit_bitrate_bps = 400 * 1000; |
| 537 if (params.codec == "VP8") { | 651 if (params.codec == "VP8") { |
| 538 vp8_settings = VideoEncoder::GetDefaultVp8Settings(); | 652 vp8_settings = VideoEncoder::GetDefaultVp8Settings(); |
| 539 vp8_settings.denoisingOn = false; | 653 vp8_settings.denoisingOn = false; |
| 540 vp8_settings.frameDroppingOn = false; | 654 vp8_settings.frameDroppingOn = false; |
| 541 vp8_settings.numberOfTemporalLayers = 2; | 655 vp8_settings.numberOfTemporalLayers = num_temporal_layers; |
| 542 encoder_config_.encoder_specific_settings = &vp8_settings; | 656 encoder_config_.encoder_specific_settings = &vp8_settings; |
| 543 } else if (params.codec == "VP9") { | 657 } else if (params.codec == "VP9") { |
| 544 vp9_settings = VideoEncoder::GetDefaultVp9Settings(); | 658 vp9_settings = VideoEncoder::GetDefaultVp9Settings(); |
| 545 vp9_settings.denoisingOn = false; | 659 vp9_settings.denoisingOn = false; |
| 546 vp9_settings.frameDroppingOn = false; | 660 vp9_settings.frameDroppingOn = false; |
| 547 vp9_settings.numberOfTemporalLayers = 2; | 661 vp9_settings.numberOfTemporalLayers = num_temporal_layers; |
| 548 encoder_config_.encoder_specific_settings = &vp9_settings; | 662 encoder_config_.encoder_specific_settings = &vp9_settings; |
| 549 } | 663 } |
| 550 | 664 |
| 551 stream->temporal_layer_thresholds_bps.clear(); | 665 stream->temporal_layer_thresholds_bps.clear(); |
| 552 stream->temporal_layer_thresholds_bps.push_back(stream->target_bitrate_bps); | 666 if (num_temporal_layers > 1) { |
| 667 stream->temporal_layer_thresholds_bps.push_back( | |
| 668 stream->target_bitrate_bps); | |
| 669 } | |
| 553 } | 670 } |
| 554 | 671 |
| 555 CreateMatchingReceiveConfigs(); | 672 CreateMatchingReceiveConfigs(); |
| 556 receive_configs_[0].renderer = &analyzer; | 673 receive_configs_[0].renderer = &analyzer; |
| 557 receive_configs_[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs; | 674 receive_configs_[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs; |
| 558 receive_configs_[0].rtp.rtx[kSendRtxPayloadType].ssrc = kSendRtxSsrcs[0]; | 675 receive_configs_[0].rtp.rtx[kSendRtxPayloadType].ssrc = kSendRtxSsrcs[0]; |
| 559 receive_configs_[0].rtp.rtx[kSendRtxPayloadType].payload_type = | 676 receive_configs_[0].rtp.rtx[kSendRtxPayloadType].payload_type = |
| 560 kSendRtxPayloadType; | 677 kSendRtxPayloadType; |
| 561 | 678 |
| 562 for (auto& config : receive_configs_) | 679 for (auto& config : receive_configs_) |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 762 50000, | 879 50000, |
| 763 200000, | 880 200000, |
| 764 2000000, | 881 2000000, |
| 765 0.0, | 882 0.0, |
| 766 0.0, | 883 0.0, |
| 767 kFullStackTestDurationSecs, | 884 kFullStackTestDurationSecs, |
| 768 "VP9"}; | 885 "VP9"}; |
| 769 RunTest(screenshare_params); | 886 RunTest(screenshare_params); |
| 770 } | 887 } |
| 771 } // namespace webrtc | 888 } // namespace webrtc |
| OLD | NEW |