OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 // Test application that simulates a cast sender - Data can be either generated | 5 // Test application that simulates a cast sender - Data can be either generated |
6 // or read from a file. | 6 // or read from a file. |
7 | 7 |
8 #include "base/at_exit.h" | 8 #include "base/at_exit.h" |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
(...skipping 28 matching lines...) Expand all Loading... |
39 #define DEFAULT_AUDIO_PAYLOAD_TYPE "127" | 39 #define DEFAULT_AUDIO_PAYLOAD_TYPE "127" |
40 #define DEFAULT_VIDEO_SENDER_SSRC "11" | 40 #define DEFAULT_VIDEO_SENDER_SSRC "11" |
41 #define DEFAULT_VIDEO_RECEIVER_SSRC "12" | 41 #define DEFAULT_VIDEO_RECEIVER_SSRC "12" |
42 #define DEFAULT_VIDEO_PAYLOAD_TYPE "96" | 42 #define DEFAULT_VIDEO_PAYLOAD_TYPE "96" |
43 #define DEFAULT_VIDEO_CODEC_WIDTH "1280" | 43 #define DEFAULT_VIDEO_CODEC_WIDTH "1280" |
44 #define DEFAULT_VIDEO_CODEC_HEIGHT "720" | 44 #define DEFAULT_VIDEO_CODEC_HEIGHT "720" |
45 #define DEFAULT_VIDEO_CODEC_BITRATE "2000" | 45 #define DEFAULT_VIDEO_CODEC_BITRATE "2000" |
46 #define DEFAULT_VIDEO_CODEC_MAX_BITRATE "4000" | 46 #define DEFAULT_VIDEO_CODEC_MAX_BITRATE "4000" |
47 #define DEFAULT_VIDEO_CODEC_MIN_BITRATE "1000" | 47 #define DEFAULT_VIDEO_CODEC_MIN_BITRATE "1000" |
48 | 48 |
49 #define DEFAULT_LOGGING_DURATION "30" | 49 #define DEFAULT_LOGGING_DURATION "10" |
| 50 #define DEFAULT_COMPRESS_LOGS "1" |
50 | 51 |
51 namespace { | 52 namespace { |
52 static const int kAudioChannels = 2; | 53 static const int kAudioChannels = 2; |
53 static const int kAudioSamplingFrequency = 48000; | 54 static const int kAudioSamplingFrequency = 48000; |
54 static const int kSoundFrequency = 1234; // Frequency of sinusoid wave. | 55 static const int kSoundFrequency = 1234; // Frequency of sinusoid wave. |
55 // The tests are commonly implemented with |kFrameTimerMs| RunTask function; | 56 // The tests are commonly implemented with |kFrameTimerMs| RunTask function; |
56 // a normal video is 30 fps hence the 33 ms between frames. | 57 // a normal video is 30 fps hence the 33 ms between frames. |
57 static const float kSoundVolume = 0.5f; | 58 static const float kSoundVolume = 0.5f; |
58 static const int kFrameTimerMs = 33; | 59 static const int kFrameTimerMs = 33; |
59 | 60 |
| 61 // The max allowed size of serialized log. |
| 62 const int kMaxSerializedLogBytes = 10 * 1000 * 1000; |
| 63 |
60 // Dummy callback function that does nothing except to accept ownership of | 64 // Dummy callback function that does nothing except to accept ownership of |
61 // |audio_bus| for destruction. This guarantees that the audio_bus is valid for | 65 // |audio_bus| for destruction. This guarantees that the audio_bus is valid for |
62 // the entire duration of the encode/send process (not equivalent to DoNothing). | 66 // the entire duration of the encode/send process (not equivalent to DoNothing). |
63 void OwnThatAudioBus(scoped_ptr<AudioBus> audio_bus) {} | 67 void OwnThatAudioBus(scoped_ptr<AudioBus> audio_bus) {} |
64 } // namespace | 68 } // namespace |
65 | 69 |
66 void GetPort(int* port) { | 70 void GetPort(int* port) { |
67 test::InputBuilder input( | 71 test::InputBuilder input( |
68 "Enter receiver port.", DEFAULT_RECEIVER_PORT, 1, INT_MAX); | 72 "Enter receiver port.", DEFAULT_RECEIVER_PORT, 1, INT_MAX); |
69 *port = input.GetIntInput(); | 73 *port = input.GetIntInput(); |
(...skipping 11 matching lines...) Expand all Loading... |
81 | 85 |
82 int GetLoggingDuration() { | 86 int GetLoggingDuration() { |
83 test::InputBuilder input( | 87 test::InputBuilder input( |
84 "Choose logging duration (seconds), 0 for no logging.", | 88 "Choose logging duration (seconds), 0 for no logging.", |
85 DEFAULT_LOGGING_DURATION, | 89 DEFAULT_LOGGING_DURATION, |
86 0, | 90 0, |
87 INT_MAX); | 91 INT_MAX); |
88 return input.GetIntInput(); | 92 return input.GetIntInput(); |
89 } | 93 } |
90 | 94 |
91 std::string GetLogFileDestination() { | 95 std::string GetVideoLogFileDestination(bool compress) { |
92 test::InputBuilder input( | 96 test::InputBuilder input( |
93 "Enter log file destination.", "./raw_events.log", INT_MIN, INT_MAX); | 97 "Enter video events log file destination.", |
| 98 compress ? "./video_events.log.gz" : "./video_events.log", |
| 99 INT_MIN, |
| 100 INT_MAX); |
94 return input.GetStringInput(); | 101 return input.GetStringInput(); |
95 } | 102 } |
96 | 103 |
| 104 std::string GetAudioLogFileDestination(bool compress) { |
| 105 test::InputBuilder input( |
| 106 "Enter audio events log file destination.", |
| 107 compress ? "./audio_events.log.gz" : "./audio_events.log", |
| 108 INT_MIN, |
| 109 INT_MAX); |
| 110 return input.GetStringInput(); |
| 111 } |
| 112 |
| 113 bool CompressLogs() { |
| 114 test::InputBuilder input( |
| 115 "Enter 1 to enable compression on logs.", DEFAULT_COMPRESS_LOGS, 0, 1); |
| 116 return (1 == input.GetIntInput()); |
| 117 } |
| 118 |
97 bool ReadFromFile() { | 119 bool ReadFromFile() { |
98 test::InputBuilder input( | 120 test::InputBuilder input( |
99 "Enter 1 to read from file.", DEFAULT_READ_FROM_FILE, 0, 1); | 121 "Enter 1 to read from file.", DEFAULT_READ_FROM_FILE, 0, 1); |
100 return (1 == input.GetIntInput()); | 122 return (1 == input.GetIntInput()); |
101 } | 123 } |
102 | 124 |
103 std::string GetVideoFile() { | 125 std::string GetVideoFile() { |
104 test::InputBuilder input( | 126 test::InputBuilder input( |
105 "Enter file and path to raw video file.", "", INT_MIN, INT_MAX); | 127 "Enter file and path to raw video file.", "", INT_MIN, INT_MAX); |
106 return input.GetStringInput(); | 128 return input.GetStringInput(); |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 result == media::cast::STATUS_VIDEO_INITIALIZED; | 366 result == media::cast::STATUS_VIDEO_INITIALIZED; |
345 CHECK(end_result) << "Cast sender uninitialized"; | 367 CHECK(end_result) << "Cast sender uninitialized"; |
346 } | 368 } |
347 | 369 |
348 net::IPEndPoint CreateUDPAddress(std::string ip_str, int port) { | 370 net::IPEndPoint CreateUDPAddress(std::string ip_str, int port) { |
349 net::IPAddressNumber ip_number; | 371 net::IPAddressNumber ip_number; |
350 CHECK(net::ParseIPLiteralToNumber(ip_str, &ip_number)); | 372 CHECK(net::ParseIPLiteralToNumber(ip_str, &ip_number)); |
351 return net::IPEndPoint(ip_number, port); | 373 return net::IPEndPoint(ip_number, port); |
352 } | 374 } |
353 | 375 |
| 376 void DumpLoggingData( |
| 377 scoped_ptr<media::cast::EncodingEventSubscriber> event_subscriber, |
| 378 file_util::ScopedFILE log_file, |
| 379 bool compress) { |
| 380 media::cast::FrameEventMap frame_events; |
| 381 media::cast::PacketEventMap packet_events; |
| 382 media::cast::proto::LogMetadata log_metadata; |
| 383 |
| 384 event_subscriber->GetEventsAndReset( |
| 385 &log_metadata, &frame_events, &packet_events); |
| 386 |
| 387 VLOG(0) << "Frame map size: " << frame_events.size(); |
| 388 VLOG(0) << "Packet map size: " << packet_events.size(); |
| 389 |
| 390 scoped_ptr<char[]> event_log(new char[media::cast::kMaxSerializedLogBytes]); |
| 391 int event_log_bytes; |
| 392 if (!media::cast::SerializeEvents(log_metadata, |
| 393 frame_events, |
| 394 packet_events, |
| 395 compress, |
| 396 media::cast::kMaxSerializedLogBytes, |
| 397 event_log.get(), |
| 398 &event_log_bytes)) { |
| 399 VLOG(0) << "Failed to serialize events."; |
| 400 return; |
| 401 } |
| 402 |
| 403 VLOG(0) << "Events serialized length: " << event_log_bytes; |
| 404 |
| 405 int ret = fwrite(event_log.get(), 1, event_log_bytes, log_file.get()); |
| 406 if (ret != event_log_bytes) |
| 407 VLOG(0) << "Failed to write logs to file."; |
| 408 } |
| 409 |
354 void WriteLogsToFileAndStopSubscribing( | 410 void WriteLogsToFileAndStopSubscribing( |
355 const scoped_refptr<media::cast::CastEnvironment>& cast_environment, | 411 const scoped_refptr<media::cast::CastEnvironment>& cast_environment, |
356 scoped_ptr<media::cast::EncodingEventSubscriber> video_event_subscriber, | 412 scoped_ptr<media::cast::EncodingEventSubscriber> video_event_subscriber, |
357 scoped_ptr<media::cast::EncodingEventSubscriber> audio_event_subscriber, | 413 scoped_ptr<media::cast::EncodingEventSubscriber> audio_event_subscriber, |
358 file_util::ScopedFILE log_file) { | 414 file_util::ScopedFILE video_log_file, |
359 media::cast::LogSerializer serializer(media::cast::kMaxSerializedLogBytes); | 415 file_util::ScopedFILE audio_log_file, |
360 | 416 bool compress) { |
361 // Serialize video events. | 417 // Serialize video events. |
362 cast_environment->Logging()->RemoveRawEventSubscriber( | 418 cast_environment->Logging()->RemoveRawEventSubscriber( |
363 video_event_subscriber.get()); | 419 video_event_subscriber.get()); |
364 media::cast::FrameEventMap frame_events; | |
365 media::cast::PacketEventMap packet_events; | |
366 media::cast::proto::LogMetadata video_log_metadata; | |
367 video_event_subscriber->GetEventsAndReset( | |
368 &video_log_metadata, &frame_events, &packet_events); | |
369 | |
370 VLOG(0) << "Video frame map size: " << frame_events.size(); | |
371 VLOG(0) << "Video packet map size: " << packet_events.size(); | |
372 | |
373 if (!serializer.SerializeEventsForStream( | |
374 video_log_metadata, frame_events, packet_events)) { | |
375 VLOG(1) << "Failed to serialize video events."; | |
376 return; | |
377 } | |
378 | |
379 int length_so_far = serializer.GetSerializedLength(); | |
380 VLOG(0) << "Video events serialized length: " << length_so_far; | |
381 | |
382 // Serialize audio events. | |
383 media::cast::proto::LogMetadata audio_log_metadata; | |
384 cast_environment->Logging()->RemoveRawEventSubscriber( | 420 cast_environment->Logging()->RemoveRawEventSubscriber( |
385 audio_event_subscriber.get()); | 421 audio_event_subscriber.get()); |
386 audio_event_subscriber->GetEventsAndReset( | |
387 &audio_log_metadata, &frame_events, &packet_events); | |
388 | 422 |
389 VLOG(0) << "Audio frame map size: " << frame_events.size(); | 423 VLOG(0) << "Dumping logging data for video stream."; |
390 VLOG(0) << "Audio packet map size: " << packet_events.size(); | 424 DumpLoggingData( |
| 425 video_event_subscriber.Pass(), video_log_file.Pass(), compress); |
391 | 426 |
392 if (!serializer.SerializeEventsForStream( | 427 VLOG(0) << "Dumping logging data for audio stream."; |
393 audio_log_metadata, frame_events, packet_events)) { | 428 DumpLoggingData( |
394 VLOG(1) << "Failed to serialize audio events."; | 429 audio_event_subscriber.Pass(), audio_log_file.Pass(), compress); |
395 return; | |
396 } | |
397 | |
398 VLOG(0) << "Audio events serialized length: " | |
399 << serializer.GetSerializedLength() - length_so_far; | |
400 | |
401 scoped_ptr<std::string> serialized_string = | |
402 serializer.GetSerializedLogAndReset(); | |
403 VLOG(0) << "Serialized string size: " << serialized_string->size(); | |
404 | |
405 size_t ret = fwrite( | |
406 &(*serialized_string)[0], 1, serialized_string->size(), log_file.get()); | |
407 if (ret != serialized_string->size()) | |
408 VLOG(1) << "Failed to write logs to file."; | |
409 } | 430 } |
410 | 431 |
411 } // namespace | 432 } // namespace |
412 | 433 |
413 int main(int argc, char** argv) { | 434 int main(int argc, char** argv) { |
414 base::AtExitManager at_exit; | 435 base::AtExitManager at_exit; |
415 CommandLine::Init(argc, argv); | 436 CommandLine::Init(argc, argv); |
416 InitLogging(logging::LoggingSettings()); | 437 InitLogging(logging::LoggingSettings()); |
417 base::Thread test_thread("Cast sender test app thread"); | 438 base::Thread test_thread("Cast sender test app thread"); |
418 base::Thread audio_thread("Cast audio encoder thread"); | 439 base::Thread audio_thread("Cast audio encoder thread"); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
496 cast_environment->Clock(), | 517 cast_environment->Clock(), |
497 video_config, | 518 video_config, |
498 audio_frame_input, | 519 audio_frame_input, |
499 video_frame_input)); | 520 video_frame_input)); |
500 | 521 |
501 // Set up event subscribers. | 522 // Set up event subscribers. |
502 int logging_duration = media::cast::GetLoggingDuration(); | 523 int logging_duration = media::cast::GetLoggingDuration(); |
503 scoped_ptr<media::cast::EncodingEventSubscriber> video_event_subscriber; | 524 scoped_ptr<media::cast::EncodingEventSubscriber> video_event_subscriber; |
504 scoped_ptr<media::cast::EncodingEventSubscriber> audio_event_subscriber; | 525 scoped_ptr<media::cast::EncodingEventSubscriber> audio_event_subscriber; |
505 if (logging_duration > 0) { | 526 if (logging_duration > 0) { |
506 std::string log_file_name(media::cast::GetLogFileDestination()); | 527 bool compress = media::cast::CompressLogs(); |
| 528 std::string video_log_file_name( |
| 529 media::cast::GetVideoLogFileDestination(compress)); |
| 530 std::string audio_log_file_name( |
| 531 media::cast::GetAudioLogFileDestination(compress)); |
507 video_event_subscriber.reset(new media::cast::EncodingEventSubscriber( | 532 video_event_subscriber.reset(new media::cast::EncodingEventSubscriber( |
508 media::cast::VIDEO_EVENT, 10000)); | 533 media::cast::VIDEO_EVENT, 10000)); |
509 audio_event_subscriber.reset(new media::cast::EncodingEventSubscriber( | 534 audio_event_subscriber.reset(new media::cast::EncodingEventSubscriber( |
510 media::cast::AUDIO_EVENT, 10000)); | 535 media::cast::AUDIO_EVENT, 10000)); |
511 cast_environment->Logging()->AddRawEventSubscriber( | 536 cast_environment->Logging()->AddRawEventSubscriber( |
512 video_event_subscriber.get()); | 537 video_event_subscriber.get()); |
513 cast_environment->Logging()->AddRawEventSubscriber( | 538 cast_environment->Logging()->AddRawEventSubscriber( |
514 audio_event_subscriber.get()); | 539 audio_event_subscriber.get()); |
515 file_util::ScopedFILE log_file(fopen(log_file_name.c_str(), "w")); | 540 |
516 if (!log_file) { | 541 file_util::ScopedFILE video_log_file( |
517 VLOG(1) << "Failed to open log file for writing."; | 542 fopen(video_log_file_name.c_str(), "w")); |
| 543 if (!video_log_file) { |
| 544 VLOG(1) << "Failed to open video log file for writing."; |
518 exit(-1); | 545 exit(-1); |
519 } | 546 } |
520 | 547 |
| 548 file_util::ScopedFILE audio_log_file( |
| 549 fopen(audio_log_file_name.c_str(), "w")); |
| 550 if (!audio_log_file) { |
| 551 VLOG(1) << "Failed to open audio log file for writing."; |
| 552 exit(-1); |
| 553 } |
| 554 |
521 io_message_loop.message_loop_proxy()->PostDelayedTask( | 555 io_message_loop.message_loop_proxy()->PostDelayedTask( |
522 FROM_HERE, | 556 FROM_HERE, |
523 base::Bind(&WriteLogsToFileAndStopSubscribing, | 557 base::Bind(&WriteLogsToFileAndStopSubscribing, |
524 cast_environment, | 558 cast_environment, |
525 base::Passed(&video_event_subscriber), | 559 base::Passed(&video_event_subscriber), |
526 base::Passed(&audio_event_subscriber), | 560 base::Passed(&audio_event_subscriber), |
527 base::Passed(&log_file)), | 561 base::Passed(&video_log_file), |
| 562 base::Passed(&audio_log_file), |
| 563 compress), |
528 base::TimeDelta::FromSeconds(logging_duration)); | 564 base::TimeDelta::FromSeconds(logging_duration)); |
529 } | 565 } |
530 | 566 |
531 test_thread.message_loop_proxy()->PostTask( | 567 test_thread.message_loop_proxy()->PostTask( |
532 FROM_HERE, | 568 FROM_HERE, |
533 base::Bind(&media::cast::SendProcess::SendFrame, | 569 base::Bind(&media::cast::SendProcess::SendFrame, |
534 base::Unretained(send_process.get()))); | 570 base::Unretained(send_process.get()))); |
535 | 571 |
536 io_message_loop.Run(); | 572 io_message_loop.Run(); |
537 | 573 |
538 return 0; | 574 return 0; |
539 } | 575 } |
OLD | NEW |