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; |
41 | 43 |
42 // The max allowed size of serialized log. | 44 // The max allowed size of serialized log. |
43 const int kMaxSerializedLogBytes = 10 * 1000 * 1000; | 45 const int kMaxSerializedLogBytes = 10 * 1000 * 1000; |
44 | 46 |
45 // Flags for this program: | 47 // Flags for this program: |
46 // | 48 // |
47 // --address=xx.xx.xx.xx | 49 // --address=xx.xx.xx.xx |
48 // IP address of receiver. | 50 // IP address of receiver. |
49 // | 51 // |
50 // --port=xxxx | 52 // --port=xxxx |
51 // Port number of receiver. | 53 // Port number of receiver. |
52 // | 54 // |
53 // --source-file=xxx.webm | 55 // --source-file=xxx.webm |
54 // WebM file as source of video frames. | 56 // WebM file as source of video frames. |
55 // | 57 // |
56 // --fps=xx | 58 // --fps=xx |
57 // Override framerate of the video stream. | 59 // 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. | |
62 const char kSwitchAddress[] = "address"; | 60 const char kSwitchAddress[] = "address"; |
63 const char kSwitchPort[] = "port"; | 61 const char kSwitchPort[] = "port"; |
64 const char kSwitchSourceFile[] = "source-file"; | 62 const char kSwitchSourceFile[] = "source-file"; |
65 const char kSwitchFps[] = "fps"; | 63 const char kSwitchFps[] = "fps"; |
66 const char kSwitchVaryFrameSizes[] = "vary-frame-sizes"; | 64 |
| 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 } |
67 | 115 |
68 void UpdateCastTransportStatus( | 116 void UpdateCastTransportStatus( |
69 media::cast::CastTransportStatus status) { | 117 media::cast::CastTransportStatus status) { |
70 VLOG(1) << "Transport status: " << status; | 118 VLOG(1) << "Transport status: " << status; |
71 } | 119 } |
72 | 120 |
73 void LogRawEvents( | 121 void LogRawEvents( |
74 const scoped_refptr<media::cast::CastEnvironment>& cast_environment, | 122 const scoped_refptr<media::cast::CastEnvironment>& cast_environment, |
75 const std::vector<media::cast::PacketEvent>& packet_events, | 123 const std::vector<media::cast::PacketEvent>& packet_events, |
76 const std::vector<media::cast::FrameEvent>& frame_events) { | 124 const std::vector<media::cast::FrameEvent>& frame_events) { |
(...skipping 17 matching lines...) Expand all Loading... |
94 it != frame_events.end(); | 142 it != frame_events.end(); |
95 ++it) { | 143 ++it) { |
96 cast_environment->Logging()->InsertFrameEvent(it->timestamp, | 144 cast_environment->Logging()->InsertFrameEvent(it->timestamp, |
97 it->type, | 145 it->type, |
98 it->media_type, | 146 it->media_type, |
99 it->rtp_timestamp, | 147 it->rtp_timestamp, |
100 it->frame_id); | 148 it->frame_id); |
101 } | 149 } |
102 } | 150 } |
103 | 151 |
104 void QuitLoopOnInitializationResult( | 152 void InitializationResult(media::cast::CastInitializationStatus result) { |
105 media::cast::CastInitializationStatus result) { | 153 bool end_result = result == media::cast::STATUS_AUDIO_INITIALIZED || |
106 CHECK(result == media::cast::STATUS_AUDIO_INITIALIZED || | 154 result == media::cast::STATUS_VIDEO_INITIALIZED; |
107 result == media::cast::STATUS_VIDEO_INITIALIZED) | 155 CHECK(end_result) << "Cast sender uninitialized"; |
108 << "Cast sender uninitialized"; | |
109 base::MessageLoop::current()->Quit(); | |
110 } | 156 } |
111 | 157 |
112 net::IPEndPoint CreateUDPAddress(std::string ip_str, uint16 port) { | 158 net::IPEndPoint CreateUDPAddress(std::string ip_str, uint16 port) { |
113 net::IPAddressNumber ip_number; | 159 net::IPAddressNumber ip_number; |
114 CHECK(net::ParseIPLiteralToNumber(ip_str, &ip_number)); | 160 CHECK(net::ParseIPLiteralToNumber(ip_str, &ip_number)); |
115 return net::IPEndPoint(ip_number, port); | 161 return net::IPEndPoint(ip_number, port); |
116 } | 162 } |
117 | 163 |
118 void DumpLoggingData(const media::cast::proto::LogMetadata& log_metadata, | 164 void DumpLoggingData(const media::cast::proto::LogMetadata& log_metadata, |
119 const media::cast::FrameEventList& frame_events, | 165 const media::cast::FrameEventList& frame_events, |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
229 if (remote_ip_address.empty()) | 275 if (remote_ip_address.empty()) |
230 remote_ip_address = "127.0.0.1"; | 276 remote_ip_address = "127.0.0.1"; |
231 int remote_port = 0; | 277 int remote_port = 0; |
232 if (!base::StringToInt(cmd->GetSwitchValueASCII(kSwitchPort), &remote_port) || | 278 if (!base::StringToInt(cmd->GetSwitchValueASCII(kSwitchPort), &remote_port) || |
233 remote_port < 0 || remote_port > 65535) { | 279 remote_port < 0 || remote_port > 65535) { |
234 remote_port = 2344; | 280 remote_port = 2344; |
235 } | 281 } |
236 LOG(INFO) << "Sending to " << remote_ip_address << ":" << remote_port | 282 LOG(INFO) << "Sending to " << remote_ip_address << ":" << remote_port |
237 << "."; | 283 << "."; |
238 | 284 |
239 media::cast::AudioSenderConfig audio_config = | 285 media::cast::AudioSenderConfig audio_config = GetAudioSenderConfig(); |
240 media::cast::GetDefaultAudioSenderConfig(); | 286 media::cast::VideoSenderConfig video_config = GetVideoSenderConfig(); |
241 media::cast::VideoSenderConfig video_config = | |
242 media::cast::GetDefaultVideoSenderConfig(); | |
243 | 287 |
244 // Running transport on the main thread. | 288 // Running transport on the main thread. |
245 // Setting up transport config. | 289 // Setting up transport config. |
246 net::IPEndPoint remote_endpoint = | 290 net::IPEndPoint remote_endpoint = |
247 CreateUDPAddress(remote_ip_address, static_cast<uint16>(remote_port)); | 291 CreateUDPAddress(remote_ip_address, static_cast<uint16>(remote_port)); |
248 | 292 |
249 // Enable raw event and stats logging. | 293 // Enable raw event and stats logging. |
250 // Running transport on the main thread. | 294 // Running transport on the main thread. |
251 scoped_refptr<media::cast::CastEnvironment> cast_environment( | 295 scoped_refptr<media::cast::CastEnvironment> cast_environment( |
252 new media::cast::CastEnvironment( | 296 new media::cast::CastEnvironment( |
(...skipping 11 matching lines...) Expand all Loading... |
264 int override_fps = 0; | 308 int override_fps = 0; |
265 if (!base::StringToInt(cmd->GetSwitchValueASCII(kSwitchFps), | 309 if (!base::StringToInt(cmd->GetSwitchValueASCII(kSwitchFps), |
266 &override_fps)){ | 310 &override_fps)){ |
267 override_fps = 0; | 311 override_fps = 0; |
268 } | 312 } |
269 base::FilePath source_path = cmd->GetSwitchValuePath(kSwitchSourceFile); | 313 base::FilePath source_path = cmd->GetSwitchValuePath(kSwitchSourceFile); |
270 if (!source_path.empty()) { | 314 if (!source_path.empty()) { |
271 LOG(INFO) << "Source: " << source_path.value(); | 315 LOG(INFO) << "Source: " << source_path.value(); |
272 fake_media_source->SetSourceFile(source_path, override_fps); | 316 fake_media_source->SetSourceFile(source_path, override_fps); |
273 } | 317 } |
274 if (cmd->HasSwitch(kSwitchVaryFrameSizes)) | |
275 fake_media_source->SetVariableFrameSizeMode(true); | |
276 | 318 |
277 // CastTransportSender initialization. | 319 // CastTransportSender initialization. |
278 scoped_ptr<media::cast::CastTransportSender> transport_sender = | 320 scoped_ptr<media::cast::CastTransportSender> transport_sender = |
279 media::cast::CastTransportSender::Create( | 321 media::cast::CastTransportSender::Create( |
280 NULL, // net log. | 322 NULL, // net log. |
281 cast_environment->Clock(), | 323 cast_environment->Clock(), |
282 net::IPEndPoint(), | 324 net::IPEndPoint(), |
283 remote_endpoint, | 325 remote_endpoint, |
284 make_scoped_ptr(new base::DictionaryValue), // options | 326 make_scoped_ptr(new base::DictionaryValue), // options |
285 base::Bind(&UpdateCastTransportStatus), | 327 base::Bind(&UpdateCastTransportStatus), |
286 base::Bind(&LogRawEvents, cast_environment), | 328 base::Bind(&LogRawEvents, cast_environment), |
287 base::TimeDelta::FromSeconds(1), | 329 base::TimeDelta::FromSeconds(1), |
288 media::cast::PacketReceiverCallback(), | 330 media::cast::PacketReceiverCallback(), |
289 io_message_loop.message_loop_proxy()); | 331 io_message_loop.message_loop_proxy()); |
290 | 332 |
| 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 |
291 // Set up event subscribers. | 343 // Set up event subscribers. |
292 scoped_ptr<media::cast::EncodingEventSubscriber> video_event_subscriber; | 344 scoped_ptr<media::cast::EncodingEventSubscriber> video_event_subscriber; |
293 scoped_ptr<media::cast::EncodingEventSubscriber> audio_event_subscriber; | 345 scoped_ptr<media::cast::EncodingEventSubscriber> audio_event_subscriber; |
294 std::string video_log_file_name("/tmp/video_events.log.gz"); | 346 std::string video_log_file_name("/tmp/video_events.log.gz"); |
295 std::string audio_log_file_name("/tmp/audio_events.log.gz"); | 347 std::string audio_log_file_name("/tmp/audio_events.log.gz"); |
296 LOG(INFO) << "Logging audio events to: " << audio_log_file_name; | 348 LOG(INFO) << "Logging audio events to: " << audio_log_file_name; |
297 LOG(INFO) << "Logging video events to: " << video_log_file_name; | 349 LOG(INFO) << "Logging video events to: " << video_log_file_name; |
298 video_event_subscriber.reset(new media::cast::EncodingEventSubscriber( | 350 video_event_subscriber.reset(new media::cast::EncodingEventSubscriber( |
299 media::cast::VIDEO_EVENT, 10000)); | 351 media::cast::VIDEO_EVENT, 10000)); |
300 audio_event_subscriber.reset(new media::cast::EncodingEventSubscriber( | 352 audio_event_subscriber.reset(new media::cast::EncodingEventSubscriber( |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
346 | 398 |
347 io_message_loop.message_loop_proxy()->PostDelayedTask( | 399 io_message_loop.message_loop_proxy()->PostDelayedTask( |
348 FROM_HERE, | 400 FROM_HERE, |
349 base::Bind(&WriteStatsAndDestroySubscribers, | 401 base::Bind(&WriteStatsAndDestroySubscribers, |
350 cast_environment, | 402 cast_environment, |
351 base::Passed(&video_stats_subscriber), | 403 base::Passed(&video_stats_subscriber), |
352 base::Passed(&audio_stats_subscriber), | 404 base::Passed(&audio_stats_subscriber), |
353 base::Passed(&offset_estimator)), | 405 base::Passed(&offset_estimator)), |
354 base::TimeDelta::FromSeconds(logging_duration_seconds)); | 406 base::TimeDelta::FromSeconds(logging_duration_seconds)); |
355 | 407 |
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 | |
376 fake_media_source->Start(cast_sender->audio_frame_input(), | 408 fake_media_source->Start(cast_sender->audio_frame_input(), |
377 cast_sender->video_frame_input()); | 409 cast_sender->video_frame_input()); |
| 410 |
378 io_message_loop.Run(); | 411 io_message_loop.Run(); |
379 return 0; | 412 return 0; |
380 } | 413 } |
OLD | NEW |