OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Simulate end to end streaming. | 5 // Simulate end to end streaming. |
6 // | 6 // |
7 // Input: | 7 // Input: |
8 // --source= | 8 // --source= |
9 // WebM used as the source of video and audio frames. | 9 // WebM used as the source of video and audio frames. |
10 // --output= | 10 // --output= |
11 // File path to writing out the raw event log of the simulation session. | 11 // File path to writing out the raw event log of the simulation session. |
12 // --sim-id= | 12 // --sim-id= |
13 // Unique simulation ID. | 13 // Unique simulation ID. |
| 14 // --target-delay-ms= |
| 15 // Target playout delay to configure (integer number of milliseconds). |
| 16 // Optional; default is 400. |
14 // | 17 // |
15 // Output: | 18 // Output: |
16 // - Raw event log of the simulation session tagged with the unique test ID, | 19 // - Raw event log of the simulation session tagged with the unique test ID, |
17 // written out to the specified file path. | 20 // written out to the specified file path. |
18 | 21 |
19 #include "base/at_exit.h" | 22 #include "base/at_exit.h" |
20 #include "base/base_paths.h" | 23 #include "base/base_paths.h" |
21 #include "base/command_line.h" | 24 #include "base/command_line.h" |
22 #include "base/files/file_path.h" | 25 #include "base/files/file_path.h" |
23 #include "base/files/file_util.h" | 26 #include "base/files/file_util.h" |
24 #include "base/files/memory_mapped_file.h" | 27 #include "base/files/memory_mapped_file.h" |
25 #include "base/files/scoped_file.h" | 28 #include "base/files/scoped_file.h" |
26 #include "base/json/json_writer.h" | 29 #include "base/json/json_writer.h" |
27 #include "base/logging.h" | 30 #include "base/logging.h" |
28 #include "base/path_service.h" | 31 #include "base/path_service.h" |
| 32 #include "base/strings/string_number_conversions.h" |
29 #include "base/test/simple_test_tick_clock.h" | 33 #include "base/test/simple_test_tick_clock.h" |
30 #include "base/thread_task_runner_handle.h" | 34 #include "base/thread_task_runner_handle.h" |
31 #include "base/time/tick_clock.h" | 35 #include "base/time/tick_clock.h" |
32 #include "base/values.h" | 36 #include "base/values.h" |
33 #include "media/base/audio_bus.h" | 37 #include "media/base/audio_bus.h" |
34 #include "media/base/media.h" | 38 #include "media/base/media.h" |
35 #include "media/base/video_frame.h" | 39 #include "media/base/video_frame.h" |
36 #include "media/cast/cast_config.h" | 40 #include "media/cast/cast_config.h" |
37 #include "media/cast/cast_environment.h" | 41 #include "media/cast/cast_environment.h" |
38 #include "media/cast/cast_receiver.h" | 42 #include "media/cast/cast_receiver.h" |
(...skipping 19 matching lines...) Expand all Loading... |
58 #include "media/cast/test/utility/udp_proxy.h" | 62 #include "media/cast/test/utility/udp_proxy.h" |
59 #include "media/cast/test/utility/video_utility.h" | 63 #include "media/cast/test/utility/video_utility.h" |
60 | 64 |
61 using media::cast::proto::IPPModel; | 65 using media::cast::proto::IPPModel; |
62 using media::cast::proto::NetworkSimulationModel; | 66 using media::cast::proto::NetworkSimulationModel; |
63 using media::cast::proto::NetworkSimulationModelType; | 67 using media::cast::proto::NetworkSimulationModelType; |
64 | 68 |
65 namespace media { | 69 namespace media { |
66 namespace cast { | 70 namespace cast { |
67 namespace { | 71 namespace { |
68 const int kTargetDelay = 400; | |
69 const char kSourcePath[] = "source"; | 72 const char kSourcePath[] = "source"; |
70 const char kModelPath[] = "model"; | 73 const char kModelPath[] = "model"; |
71 const char kOutputPath[] = "output"; | 74 const char kOutputPath[] = "output"; |
72 const char kSimulationId[] = "sim-id"; | 75 const char kSimulationId[] = "sim-id"; |
73 const char kLibDir[] = "lib-dir"; | 76 const char kLibDir[] = "lib-dir"; |
| 77 const char kTargetDelay[] = "target-delay-ms"; |
| 78 |
| 79 base::TimeDelta GetTargetPlayoutDelay() { |
| 80 const std::string delay_str = |
| 81 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(kTargetDelay); |
| 82 if (delay_str.empty()) |
| 83 return base::TimeDelta::FromMilliseconds(400); |
| 84 int delay_ms; |
| 85 CHECK(base::StringToInt(delay_str, &delay_ms)); |
| 86 CHECK_GT(delay_ms, 0); |
| 87 return base::TimeDelta::FromMilliseconds(delay_ms); |
| 88 } |
74 | 89 |
75 void UpdateCastTransportStatus(CastTransportStatus status) { | 90 void UpdateCastTransportStatus(CastTransportStatus status) { |
76 LOG(INFO) << "Cast transport status: " << status; | 91 LOG(INFO) << "Cast transport status: " << status; |
77 } | 92 } |
78 | 93 |
79 void AudioInitializationStatus(CastInitializationStatus status) { | 94 void AudioInitializationStatus(CastInitializationStatus status) { |
80 LOG(INFO) << "Audio status: " << status; | 95 LOG(INFO) << "Audio status: " << status; |
81 } | 96 } |
82 | 97 |
83 void VideoInitializationStatus(CastInitializationStatus status) { | 98 void VideoInitializationStatus(CastInitializationStatus status) { |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 // Event subscriber. Store at most 1 hour of events. | 227 // Event subscriber. Store at most 1 hour of events. |
213 EncodingEventSubscriber audio_event_subscriber(AUDIO_EVENT, | 228 EncodingEventSubscriber audio_event_subscriber(AUDIO_EVENT, |
214 100 * 60 * 60); | 229 100 * 60 * 60); |
215 EncodingEventSubscriber video_event_subscriber(VIDEO_EVENT, | 230 EncodingEventSubscriber video_event_subscriber(VIDEO_EVENT, |
216 30 * 60 * 60); | 231 30 * 60 * 60); |
217 sender_env->Logging()->AddRawEventSubscriber(&audio_event_subscriber); | 232 sender_env->Logging()->AddRawEventSubscriber(&audio_event_subscriber); |
218 sender_env->Logging()->AddRawEventSubscriber(&video_event_subscriber); | 233 sender_env->Logging()->AddRawEventSubscriber(&video_event_subscriber); |
219 | 234 |
220 // Audio sender config. | 235 // Audio sender config. |
221 AudioSenderConfig audio_sender_config = GetDefaultAudioSenderConfig(); | 236 AudioSenderConfig audio_sender_config = GetDefaultAudioSenderConfig(); |
222 audio_sender_config.max_playout_delay = | 237 audio_sender_config.max_playout_delay = GetTargetPlayoutDelay(); |
223 base::TimeDelta::FromMilliseconds(kTargetDelay); | |
224 | 238 |
225 // Audio receiver config. | 239 // Audio receiver config. |
226 FrameReceiverConfig audio_receiver_config = | 240 FrameReceiverConfig audio_receiver_config = |
227 GetDefaultAudioReceiverConfig(); | 241 GetDefaultAudioReceiverConfig(); |
228 audio_receiver_config.rtp_max_delay_ms = | 242 audio_receiver_config.rtp_max_delay_ms = |
229 audio_sender_config.max_playout_delay.InMilliseconds(); | 243 audio_sender_config.max_playout_delay.InMilliseconds(); |
230 | 244 |
231 // Video sender config. | 245 // Video sender config. |
232 VideoSenderConfig video_sender_config = GetDefaultVideoSenderConfig(); | 246 VideoSenderConfig video_sender_config = GetDefaultVideoSenderConfig(); |
233 video_sender_config.max_bitrate = 2500000; | 247 video_sender_config.max_bitrate = 2500000; |
234 video_sender_config.min_bitrate = 2000000; | 248 video_sender_config.min_bitrate = 2000000; |
235 video_sender_config.start_bitrate = 2000000; | 249 video_sender_config.start_bitrate = 2000000; |
236 video_sender_config.max_playout_delay = | 250 video_sender_config.max_playout_delay = GetTargetPlayoutDelay(); |
237 base::TimeDelta::FromMilliseconds(kTargetDelay); | |
238 | 251 |
239 // Video receiver config. | 252 // Video receiver config. |
240 FrameReceiverConfig video_receiver_config = | 253 FrameReceiverConfig video_receiver_config = |
241 GetDefaultVideoReceiverConfig(); | 254 GetDefaultVideoReceiverConfig(); |
242 video_receiver_config.rtp_max_delay_ms = | 255 video_receiver_config.rtp_max_delay_ms = |
243 video_sender_config.max_playout_delay.InMilliseconds(); | 256 video_sender_config.max_playout_delay.InMilliseconds(); |
244 | 257 |
245 // Loopback transport. | 258 // Loopback transport. |
246 LoopBackTransport receiver_to_sender(receiver_env); | 259 LoopBackTransport receiver_to_sender(receiver_env); |
247 LoopBackTransport sender_to_receiver(sender_env); | 260 LoopBackTransport sender_to_receiver(sender_env); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 // * Total video frames captured. | 361 // * Total video frames captured. |
349 // * Total video frames encoded. | 362 // * Total video frames encoded. |
350 // * Total video frames dropped. | 363 // * Total video frames dropped. |
351 // * Total video frames received late. | 364 // * Total video frames received late. |
352 // * Average target bitrate. | 365 // * Average target bitrate. |
353 // * Average encoded bitrate. | 366 // * Average encoded bitrate. |
354 int total_video_frames = 0; | 367 int total_video_frames = 0; |
355 int encoded_video_frames = 0; | 368 int encoded_video_frames = 0; |
356 int dropped_video_frames = 0; | 369 int dropped_video_frames = 0; |
357 int late_video_frames = 0; | 370 int late_video_frames = 0; |
| 371 int64 total_delay_of_late_frames_ms = 0; |
358 int64 encoded_size = 0; | 372 int64 encoded_size = 0; |
359 int64 target_bitrate = 0; | 373 int64 target_bitrate = 0; |
360 for (size_t i = 0; i < video_frame_events.size(); ++i) { | 374 for (size_t i = 0; i < video_frame_events.size(); ++i) { |
361 const media::cast::proto::AggregatedFrameEvent& event = | 375 const media::cast::proto::AggregatedFrameEvent& event = |
362 *video_frame_events[i]; | 376 *video_frame_events[i]; |
363 ++total_video_frames; | 377 ++total_video_frames; |
364 if (event.has_encoded_frame_size()) { | 378 if (event.has_encoded_frame_size()) { |
365 ++encoded_video_frames; | 379 ++encoded_video_frames; |
366 encoded_size += event.encoded_frame_size(); | 380 encoded_size += event.encoded_frame_size(); |
367 target_bitrate += event.target_bitrate(); | 381 target_bitrate += event.target_bitrate(); |
368 } else { | 382 } else { |
369 ++dropped_video_frames; | 383 ++dropped_video_frames; |
370 } | 384 } |
371 if (event.has_delay_millis() && event.delay_millis() < 0) | 385 if (event.has_delay_millis() && event.delay_millis() < 0) { |
372 ++late_video_frames; | 386 ++late_video_frames; |
| 387 total_delay_of_late_frames_ms += -event.delay_millis(); |
| 388 } |
373 } | 389 } |
374 | 390 |
375 double avg_encoded_bitrate = | 391 double avg_encoded_bitrate = |
376 !encoded_video_frames ? 0 : | 392 !encoded_video_frames ? 0 : |
377 8.0 * encoded_size * video_sender_config.max_frame_rate / | 393 8.0 * encoded_size * video_sender_config.max_frame_rate / |
378 encoded_video_frames / 1000; | 394 encoded_video_frames / 1000; |
379 double avg_target_bitrate = | 395 double avg_target_bitrate = |
380 !encoded_video_frames ? 0 : target_bitrate / encoded_video_frames / 1000; | 396 !encoded_video_frames ? 0 : target_bitrate / encoded_video_frames / 1000; |
381 | 397 |
| 398 LOG(INFO) << "Configured target playout delay (ms): " |
| 399 << video_receiver_config.rtp_max_delay_ms; |
382 LOG(INFO) << "Audio frame count: " << audio_frame_count; | 400 LOG(INFO) << "Audio frame count: " << audio_frame_count; |
383 LOG(INFO) << "Total video frames: " << total_video_frames; | 401 LOG(INFO) << "Total video frames: " << total_video_frames; |
384 LOG(INFO) << "Dropped video frames " << dropped_video_frames; | 402 LOG(INFO) << "Dropped video frames " << dropped_video_frames; |
385 LOG(INFO) << "Late video frames: " << late_video_frames; | 403 LOG(INFO) << "Late video frames: " << late_video_frames |
| 404 << " (average lateness: " |
| 405 << (late_video_frames > 0 ? |
| 406 static_cast<double>(total_delay_of_late_frames_ms) / |
| 407 late_video_frames : |
| 408 0) |
| 409 << " ms)"; |
386 LOG(INFO) << "Average encoded bitrate (kbps): " << avg_encoded_bitrate; | 410 LOG(INFO) << "Average encoded bitrate (kbps): " << avg_encoded_bitrate; |
387 LOG(INFO) << "Average target bitrate (kbps): " << avg_target_bitrate; | 411 LOG(INFO) << "Average target bitrate (kbps): " << avg_target_bitrate; |
388 LOG(INFO) << "Writing log: " << output_path.value(); | 412 LOG(INFO) << "Writing log: " << output_path.value(); |
389 | 413 |
390 // Truncate file and then write serialized log. | 414 // Truncate file and then write serialized log. |
391 { | 415 { |
392 base::ScopedFILE file(base::OpenFile(output_path, "wb")); | 416 base::ScopedFILE file(base::OpenFile(output_path, "wb")); |
393 if (!file.get()) { | 417 if (!file.get()) { |
394 LOG(INFO) << "Cannot write to log."; | 418 LOG(INFO) << "Cannot write to log."; |
395 return; | 419 return; |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
513 values.SetBoolean("sim", true); | 537 values.SetBoolean("sim", true); |
514 values.SetString("sim-id", sim_id); | 538 values.SetString("sim-id", sim_id); |
515 | 539 |
516 std::string extra_data; | 540 std::string extra_data; |
517 base::JSONWriter::Write(&values, &extra_data); | 541 base::JSONWriter::Write(&values, &extra_data); |
518 | 542 |
519 // Run. | 543 // Run. |
520 media::cast::RunSimulation(source_path, output_path, extra_data, model); | 544 media::cast::RunSimulation(source_path, output_path, extra_data, model); |
521 return 0; | 545 return 0; |
522 } | 546 } |
OLD | NEW |