| 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 <queue> | 8 #include <queue> |
| 9 | 9 |
| 10 #include "base/at_exit.h" | 10 #include "base/at_exit.h" |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 #include "media/cast/logging/receiver_time_offset_estimator_impl.h" | 31 #include "media/cast/logging/receiver_time_offset_estimator_impl.h" |
| 32 #include "media/cast/logging/stats_event_subscriber.h" | 32 #include "media/cast/logging/stats_event_subscriber.h" |
| 33 #include "media/cast/net/cast_transport_defines.h" | 33 #include "media/cast/net/cast_transport_defines.h" |
| 34 #include "media/cast/net/cast_transport_sender.h" | 34 #include "media/cast/net/cast_transport_sender.h" |
| 35 #include "media/cast/net/udp_transport.h" | 35 #include "media/cast/net/udp_transport.h" |
| 36 #include "media/cast/test/fake_media_source.h" | 36 #include "media/cast/test/fake_media_source.h" |
| 37 #include "media/cast/test/utility/default_config.h" | 37 #include "media/cast/test/utility/default_config.h" |
| 38 #include "media/cast/test/utility/input_builder.h" | 38 #include "media/cast/test/utility/input_builder.h" |
| 39 | 39 |
| 40 namespace { | 40 namespace { |
| 41 static const int kAudioChannels = 2; | |
| 42 static const int kAudioSamplingFrequency = 48000; | |
| 43 | 41 |
| 44 // The max allowed size of serialized log. | 42 // The max allowed size of serialized log. |
| 45 const int kMaxSerializedLogBytes = 10 * 1000 * 1000; | 43 const int kMaxSerializedLogBytes = 10 * 1000 * 1000; |
| 46 | 44 |
| 47 // Flags for this program: | 45 // Flags for this program: |
| 48 // | 46 // |
| 49 // --address=xx.xx.xx.xx | 47 // --address=xx.xx.xx.xx |
| 50 // IP address of receiver. | 48 // IP address of receiver. |
| 51 // | 49 // |
| 52 // --port=xxxx | 50 // --port=xxxx |
| 53 // Port number of receiver. | 51 // Port number of receiver. |
| 54 // | 52 // |
| 55 // --source-file=xxx.webm | 53 // --source-file=xxx.webm |
| 56 // WebM file as source of video frames. | 54 // WebM file as source of video frames. |
| 57 // | 55 // |
| 58 // --fps=xx | 56 // --fps=xx |
| 59 // Override framerate of the video stream. | 57 // Override framerate of the video stream. |
| 58 // |
| 59 // --vary-frame-sizes |
| 60 // Randomly vary the video frame sizes at random points in time. Has no |
| 61 // effect if --source-file is being used. |
| 60 const char kSwitchAddress[] = "address"; | 62 const char kSwitchAddress[] = "address"; |
| 61 const char kSwitchPort[] = "port"; | 63 const char kSwitchPort[] = "port"; |
| 62 const char kSwitchSourceFile[] = "source-file"; | 64 const char kSwitchSourceFile[] = "source-file"; |
| 63 const char kSwitchFps[] = "fps"; | 65 const char kSwitchFps[] = "fps"; |
| 64 | 66 const char kSwitchVaryFrameSizes[] = "vary-frame-sizes"; |
| 65 media::cast::AudioSenderConfig GetAudioSenderConfig() { | |
| 66 media::cast::AudioSenderConfig audio_config; | |
| 67 | |
| 68 audio_config.use_external_encoder = false; | |
| 69 audio_config.frequency = kAudioSamplingFrequency; | |
| 70 audio_config.channels = kAudioChannels; | |
| 71 audio_config.bitrate = 0; // Use Opus auto-VBR mode. | |
| 72 audio_config.codec = media::cast::CODEC_AUDIO_OPUS; | |
| 73 audio_config.ssrc = 1; | |
| 74 audio_config.receiver_ssrc = 2; | |
| 75 audio_config.rtp_payload_type = 127; | |
| 76 // TODO(miu): The default in cast_defines.h is 100. Should this be 100, and | |
| 77 // should receiver.cc's config also be 100? | |
| 78 audio_config.max_playout_delay = base::TimeDelta::FromMilliseconds(300); | |
| 79 return audio_config; | |
| 80 } | |
| 81 | |
| 82 media::cast::VideoSenderConfig GetVideoSenderConfig() { | |
| 83 media::cast::VideoSenderConfig video_config; | |
| 84 | |
| 85 video_config.use_external_encoder = false; | |
| 86 | |
| 87 // Resolution. | |
| 88 video_config.width = 1280; | |
| 89 video_config.height = 720; | |
| 90 video_config.max_frame_rate = 30; | |
| 91 | |
| 92 // Bitrates. | |
| 93 video_config.max_bitrate = 2500000; | |
| 94 video_config.min_bitrate = 100000; | |
| 95 video_config.start_bitrate = video_config.min_bitrate; | |
| 96 | |
| 97 // Codec. | |
| 98 video_config.codec = media::cast::CODEC_VIDEO_VP8; | |
| 99 video_config.max_number_of_video_buffers_used = 1; | |
| 100 video_config.number_of_encode_threads = 2; | |
| 101 | |
| 102 // Quality options. | |
| 103 video_config.min_qp = 4; | |
| 104 video_config.max_qp = 40; | |
| 105 | |
| 106 // SSRCs and payload type. Don't change them. | |
| 107 video_config.ssrc = 11; | |
| 108 video_config.receiver_ssrc = 12; | |
| 109 video_config.rtp_payload_type = 96; | |
| 110 // TODO(miu): The default in cast_defines.h is 100. Should this be 100, and | |
| 111 // should receiver.cc's config also be 100? | |
| 112 video_config.max_playout_delay = base::TimeDelta::FromMilliseconds(300); | |
| 113 return video_config; | |
| 114 } | |
| 115 | 67 |
| 116 void UpdateCastTransportStatus( | 68 void UpdateCastTransportStatus( |
| 117 media::cast::CastTransportStatus status) { | 69 media::cast::CastTransportStatus status) { |
| 118 VLOG(1) << "Transport status: " << status; | 70 VLOG(1) << "Transport status: " << status; |
| 119 } | 71 } |
| 120 | 72 |
| 121 void LogRawEvents( | 73 void LogRawEvents( |
| 122 const scoped_refptr<media::cast::CastEnvironment>& cast_environment, | 74 const scoped_refptr<media::cast::CastEnvironment>& cast_environment, |
| 123 const std::vector<media::cast::PacketEvent>& packet_events, | 75 const std::vector<media::cast::PacketEvent>& packet_events, |
| 124 const std::vector<media::cast::FrameEvent>& frame_events) { | 76 const std::vector<media::cast::FrameEvent>& frame_events) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 142 it != frame_events.end(); | 94 it != frame_events.end(); |
| 143 ++it) { | 95 ++it) { |
| 144 cast_environment->Logging()->InsertFrameEvent(it->timestamp, | 96 cast_environment->Logging()->InsertFrameEvent(it->timestamp, |
| 145 it->type, | 97 it->type, |
| 146 it->media_type, | 98 it->media_type, |
| 147 it->rtp_timestamp, | 99 it->rtp_timestamp, |
| 148 it->frame_id); | 100 it->frame_id); |
| 149 } | 101 } |
| 150 } | 102 } |
| 151 | 103 |
| 152 void InitializationResult(media::cast::CastInitializationStatus result) { | 104 void QuitLoopOnInitializationResult( |
| 153 bool end_result = result == media::cast::STATUS_AUDIO_INITIALIZED || | 105 media::cast::CastInitializationStatus result) { |
| 154 result == media::cast::STATUS_VIDEO_INITIALIZED; | 106 CHECK(result == media::cast::STATUS_AUDIO_INITIALIZED || |
| 155 CHECK(end_result) << "Cast sender uninitialized"; | 107 result == media::cast::STATUS_VIDEO_INITIALIZED) |
| 108 << "Cast sender uninitialized"; |
| 109 base::MessageLoop::current()->Quit(); |
| 156 } | 110 } |
| 157 | 111 |
| 158 net::IPEndPoint CreateUDPAddress(std::string ip_str, uint16 port) { | 112 net::IPEndPoint CreateUDPAddress(std::string ip_str, uint16 port) { |
| 159 net::IPAddressNumber ip_number; | 113 net::IPAddressNumber ip_number; |
| 160 CHECK(net::ParseIPLiteralToNumber(ip_str, &ip_number)); | 114 CHECK(net::ParseIPLiteralToNumber(ip_str, &ip_number)); |
| 161 return net::IPEndPoint(ip_number, port); | 115 return net::IPEndPoint(ip_number, port); |
| 162 } | 116 } |
| 163 | 117 |
| 164 void DumpLoggingData(const media::cast::proto::LogMetadata& log_metadata, | 118 void DumpLoggingData(const media::cast::proto::LogMetadata& log_metadata, |
| 165 const media::cast::FrameEventList& frame_events, | 119 const media::cast::FrameEventList& frame_events, |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 if (remote_ip_address.empty()) | 229 if (remote_ip_address.empty()) |
| 276 remote_ip_address = "127.0.0.1"; | 230 remote_ip_address = "127.0.0.1"; |
| 277 int remote_port = 0; | 231 int remote_port = 0; |
| 278 if (!base::StringToInt(cmd->GetSwitchValueASCII(kSwitchPort), &remote_port) || | 232 if (!base::StringToInt(cmd->GetSwitchValueASCII(kSwitchPort), &remote_port) || |
| 279 remote_port < 0 || remote_port > 65535) { | 233 remote_port < 0 || remote_port > 65535) { |
| 280 remote_port = 2344; | 234 remote_port = 2344; |
| 281 } | 235 } |
| 282 LOG(INFO) << "Sending to " << remote_ip_address << ":" << remote_port | 236 LOG(INFO) << "Sending to " << remote_ip_address << ":" << remote_port |
| 283 << "."; | 237 << "."; |
| 284 | 238 |
| 285 media::cast::AudioSenderConfig audio_config = GetAudioSenderConfig(); | 239 media::cast::AudioSenderConfig audio_config = |
| 286 media::cast::VideoSenderConfig video_config = GetVideoSenderConfig(); | 240 media::cast::GetDefaultAudioSenderConfig(); |
| 241 media::cast::VideoSenderConfig video_config = |
| 242 media::cast::GetDefaultVideoSenderConfig(); |
| 287 | 243 |
| 288 // Running transport on the main thread. | 244 // Running transport on the main thread. |
| 289 // Setting up transport config. | 245 // Setting up transport config. |
| 290 net::IPEndPoint remote_endpoint = | 246 net::IPEndPoint remote_endpoint = |
| 291 CreateUDPAddress(remote_ip_address, static_cast<uint16>(remote_port)); | 247 CreateUDPAddress(remote_ip_address, static_cast<uint16>(remote_port)); |
| 292 | 248 |
| 293 // Enable raw event and stats logging. | 249 // Enable raw event and stats logging. |
| 294 // Running transport on the main thread. | 250 // Running transport on the main thread. |
| 295 scoped_refptr<media::cast::CastEnvironment> cast_environment( | 251 scoped_refptr<media::cast::CastEnvironment> cast_environment( |
| 296 new media::cast::CastEnvironment( | 252 new media::cast::CastEnvironment( |
| (...skipping 11 matching lines...) Expand all Loading... |
| 308 int override_fps = 0; | 264 int override_fps = 0; |
| 309 if (!base::StringToInt(cmd->GetSwitchValueASCII(kSwitchFps), | 265 if (!base::StringToInt(cmd->GetSwitchValueASCII(kSwitchFps), |
| 310 &override_fps)){ | 266 &override_fps)){ |
| 311 override_fps = 0; | 267 override_fps = 0; |
| 312 } | 268 } |
| 313 base::FilePath source_path = cmd->GetSwitchValuePath(kSwitchSourceFile); | 269 base::FilePath source_path = cmd->GetSwitchValuePath(kSwitchSourceFile); |
| 314 if (!source_path.empty()) { | 270 if (!source_path.empty()) { |
| 315 LOG(INFO) << "Source: " << source_path.value(); | 271 LOG(INFO) << "Source: " << source_path.value(); |
| 316 fake_media_source->SetSourceFile(source_path, override_fps); | 272 fake_media_source->SetSourceFile(source_path, override_fps); |
| 317 } | 273 } |
| 274 if (cmd->HasSwitch(kSwitchVaryFrameSizes)) |
| 275 fake_media_source->SetVariableFrameSizeMode(true); |
| 318 | 276 |
| 319 // CastTransportSender initialization. | 277 // CastTransportSender initialization. |
| 320 scoped_ptr<media::cast::CastTransportSender> transport_sender = | 278 scoped_ptr<media::cast::CastTransportSender> transport_sender = |
| 321 media::cast::CastTransportSender::Create( | 279 media::cast::CastTransportSender::Create( |
| 322 NULL, // net log. | 280 NULL, // net log. |
| 323 cast_environment->Clock(), | 281 cast_environment->Clock(), |
| 324 net::IPEndPoint(), | 282 net::IPEndPoint(), |
| 325 remote_endpoint, | 283 remote_endpoint, |
| 326 make_scoped_ptr(new base::DictionaryValue), // options | 284 make_scoped_ptr(new base::DictionaryValue), // options |
| 327 base::Bind(&UpdateCastTransportStatus), | 285 base::Bind(&UpdateCastTransportStatus), |
| 328 base::Bind(&LogRawEvents, cast_environment), | 286 base::Bind(&LogRawEvents, cast_environment), |
| 329 base::TimeDelta::FromSeconds(1), | 287 base::TimeDelta::FromSeconds(1), |
| 330 media::cast::PacketReceiverCallback(), | 288 media::cast::PacketReceiverCallback(), |
| 331 io_message_loop.message_loop_proxy()); | 289 io_message_loop.message_loop_proxy()); |
| 332 | 290 |
| 333 // CastSender initialization. | |
| 334 scoped_ptr<media::cast::CastSender> cast_sender = | |
| 335 media::cast::CastSender::Create(cast_environment, transport_sender.get()); | |
| 336 cast_sender->InitializeVideo( | |
| 337 fake_media_source->get_video_config(), | |
| 338 base::Bind(&InitializationResult), | |
| 339 media::cast::CreateDefaultVideoEncodeAcceleratorCallback(), | |
| 340 media::cast::CreateDefaultVideoEncodeMemoryCallback()); | |
| 341 cast_sender->InitializeAudio(audio_config, base::Bind(&InitializationResult)); | |
| 342 | |
| 343 // Set up event subscribers. | 291 // Set up event subscribers. |
| 344 scoped_ptr<media::cast::EncodingEventSubscriber> video_event_subscriber; | 292 scoped_ptr<media::cast::EncodingEventSubscriber> video_event_subscriber; |
| 345 scoped_ptr<media::cast::EncodingEventSubscriber> audio_event_subscriber; | 293 scoped_ptr<media::cast::EncodingEventSubscriber> audio_event_subscriber; |
| 346 std::string video_log_file_name("/tmp/video_events.log.gz"); | 294 std::string video_log_file_name("/tmp/video_events.log.gz"); |
| 347 std::string audio_log_file_name("/tmp/audio_events.log.gz"); | 295 std::string audio_log_file_name("/tmp/audio_events.log.gz"); |
| 348 LOG(INFO) << "Logging audio events to: " << audio_log_file_name; | 296 LOG(INFO) << "Logging audio events to: " << audio_log_file_name; |
| 349 LOG(INFO) << "Logging video events to: " << video_log_file_name; | 297 LOG(INFO) << "Logging video events to: " << video_log_file_name; |
| 350 video_event_subscriber.reset(new media::cast::EncodingEventSubscriber( | 298 video_event_subscriber.reset(new media::cast::EncodingEventSubscriber( |
| 351 media::cast::VIDEO_EVENT, 10000)); | 299 media::cast::VIDEO_EVENT, 10000)); |
| 352 audio_event_subscriber.reset(new media::cast::EncodingEventSubscriber( | 300 audio_event_subscriber.reset(new media::cast::EncodingEventSubscriber( |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 | 346 |
| 399 io_message_loop.message_loop_proxy()->PostDelayedTask( | 347 io_message_loop.message_loop_proxy()->PostDelayedTask( |
| 400 FROM_HERE, | 348 FROM_HERE, |
| 401 base::Bind(&WriteStatsAndDestroySubscribers, | 349 base::Bind(&WriteStatsAndDestroySubscribers, |
| 402 cast_environment, | 350 cast_environment, |
| 403 base::Passed(&video_stats_subscriber), | 351 base::Passed(&video_stats_subscriber), |
| 404 base::Passed(&audio_stats_subscriber), | 352 base::Passed(&audio_stats_subscriber), |
| 405 base::Passed(&offset_estimator)), | 353 base::Passed(&offset_estimator)), |
| 406 base::TimeDelta::FromSeconds(logging_duration_seconds)); | 354 base::TimeDelta::FromSeconds(logging_duration_seconds)); |
| 407 | 355 |
| 356 // CastSender initialization. |
| 357 scoped_ptr<media::cast::CastSender> cast_sender = |
| 358 media::cast::CastSender::Create(cast_environment, transport_sender.get()); |
| 359 io_message_loop.PostTask( |
| 360 FROM_HERE, |
| 361 base::Bind(&media::cast::CastSender::InitializeVideo, |
| 362 base::Unretained(cast_sender.get()), |
| 363 fake_media_source->get_video_config(), |
| 364 base::Bind(&QuitLoopOnInitializationResult), |
| 365 media::cast::CreateDefaultVideoEncodeAcceleratorCallback(), |
| 366 media::cast::CreateDefaultVideoEncodeMemoryCallback())); |
| 367 io_message_loop.Run(); // Wait for video initialization. |
| 368 io_message_loop.PostTask( |
| 369 FROM_HERE, |
| 370 base::Bind(&media::cast::CastSender::InitializeAudio, |
| 371 base::Unretained(cast_sender.get()), |
| 372 audio_config, |
| 373 base::Bind(&QuitLoopOnInitializationResult))); |
| 374 io_message_loop.Run(); // Wait for audio initialization. |
| 375 |
| 408 fake_media_source->Start(cast_sender->audio_frame_input(), | 376 fake_media_source->Start(cast_sender->audio_frame_input(), |
| 409 cast_sender->video_frame_input()); | 377 cast_sender->video_frame_input()); |
| 410 | |
| 411 io_message_loop.Run(); | 378 io_message_loop.Run(); |
| 412 return 0; | 379 return 0; |
| 413 } | 380 } |
| OLD | NEW |