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/file_util.h" | 9 #include "base/file_util.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
198 video_config.max_number_of_video_buffers_used = 1; | 198 video_config.max_number_of_video_buffers_used = 1; |
199 video_config.number_of_cores = 1; | 199 video_config.number_of_cores = 1; |
200 return video_config; | 200 return video_config; |
201 } | 201 } |
202 | 202 |
203 class SendProcess { | 203 class SendProcess { |
204 public: | 204 public: |
205 SendProcess(scoped_refptr<base::SingleThreadTaskRunner> thread_proxy, | 205 SendProcess(scoped_refptr<base::SingleThreadTaskRunner> thread_proxy, |
206 base::TickClock* clock, | 206 base::TickClock* clock, |
207 const VideoSenderConfig& video_config, | 207 const VideoSenderConfig& video_config, |
208 FrameInput* frame_input) | 208 scoped_refptr<AudioFrameInput> audio_frame_input, |
209 scoped_refptr<VideoFrameInput> video_frame_input) | |
209 : test_app_thread_proxy_(thread_proxy), | 210 : test_app_thread_proxy_(thread_proxy), |
210 video_config_(video_config), | 211 video_config_(video_config), |
211 audio_diff_(kFrameTimerMs), | 212 audio_diff_(kFrameTimerMs), |
212 frame_input_(frame_input), | 213 audio_frame_input_(audio_frame_input), |
214 video_frame_input_(video_frame_input), | |
213 synthetic_count_(0), | 215 synthetic_count_(0), |
214 clock_(clock), | 216 clock_(clock), |
215 start_time_(), | 217 start_time_(), |
216 send_time_(), | 218 send_time_(), |
217 weak_factory_(this) { | 219 weak_factory_(this) { |
218 audio_bus_factory_.reset(new TestAudioBusFactory(kAudioChannels, | 220 audio_bus_factory_.reset(new TestAudioBusFactory(kAudioChannels, |
219 kAudioSamplingFrequency, | 221 kAudioSamplingFrequency, |
220 kSoundFrequency, | 222 kSoundFrequency, |
221 kSoundVolume)); | 223 kSoundVolume)); |
222 if (ReadFromFile()) { | 224 if (ReadFromFile()) { |
(...skipping 15 matching lines...) Expand all Loading... | |
238 | 240 |
239 void SendFrame() { | 241 void SendFrame() { |
240 // Make sure that we don't drift. | 242 // Make sure that we don't drift. |
241 int num_10ms_blocks = audio_diff_ / 10; | 243 int num_10ms_blocks = audio_diff_ / 10; |
242 // Avoid drift. | 244 // Avoid drift. |
243 audio_diff_ += kFrameTimerMs - num_10ms_blocks * 10; | 245 audio_diff_ += kFrameTimerMs - num_10ms_blocks * 10; |
244 | 246 |
245 scoped_ptr<AudioBus> audio_bus(audio_bus_factory_->NextAudioBus( | 247 scoped_ptr<AudioBus> audio_bus(audio_bus_factory_->NextAudioBus( |
246 base::TimeDelta::FromMilliseconds(10) * num_10ms_blocks)); | 248 base::TimeDelta::FromMilliseconds(10) * num_10ms_blocks)); |
247 AudioBus* const audio_bus_ptr = audio_bus.get(); | 249 AudioBus* const audio_bus_ptr = audio_bus.get(); |
248 frame_input_->InsertAudio( | 250 audio_frame_input_->InsertAudio( |
249 audio_bus_ptr, | 251 audio_bus_ptr, |
250 clock_->NowTicks(), | 252 clock_->NowTicks(), |
251 base::Bind(&OwnThatAudioBus, base::Passed(&audio_bus))); | 253 base::Bind(&OwnThatAudioBus, base::Passed(&audio_bus))); |
252 | 254 |
253 gfx::Size size(video_config_.width, video_config_.height); | 255 gfx::Size size(video_config_.width, video_config_.height); |
254 // TODO(mikhal): Use the provided timestamp. | 256 // TODO(mikhal): Use the provided timestamp. |
255 if (start_time_.is_null()) | 257 if (start_time_.is_null()) |
256 start_time_ = clock_->NowTicks(); | 258 start_time_ = clock_->NowTicks(); |
257 base::TimeDelta time_diff = clock_->NowTicks() - start_time_; | 259 base::TimeDelta time_diff = clock_->NowTicks() - start_time_; |
258 scoped_refptr<media::VideoFrame> video_frame = | 260 scoped_refptr<media::VideoFrame> video_frame = |
(...skipping 11 matching lines...) Expand all Loading... | |
270 // Sleep if that time has yet to elapse. | 272 // Sleep if that time has yet to elapse. |
271 base::TimeTicks now = clock_->NowTicks(); | 273 base::TimeTicks now = clock_->NowTicks(); |
272 base::TimeDelta video_frame_time = | 274 base::TimeDelta video_frame_time = |
273 base::TimeDelta::FromMilliseconds(kFrameTimerMs); | 275 base::TimeDelta::FromMilliseconds(kFrameTimerMs); |
274 base::TimeDelta elapsed_time = now - send_time_; | 276 base::TimeDelta elapsed_time = now - send_time_; |
275 if (elapsed_time < video_frame_time) { | 277 if (elapsed_time < video_frame_time) { |
276 VLOG(1) << "Wait" << (video_frame_time - elapsed_time).InMilliseconds(); | 278 VLOG(1) << "Wait" << (video_frame_time - elapsed_time).InMilliseconds(); |
277 test_app_thread_proxy_->PostDelayedTask( | 279 test_app_thread_proxy_->PostDelayedTask( |
278 FROM_HERE, | 280 FROM_HERE, |
279 base::Bind(&SendProcess::SendVideoFrameOnTime, | 281 base::Bind(&SendProcess::SendVideoFrameOnTime, |
280 base::Unretained(this), | 282 weak_factory_.GetWeakPtr(), |
281 video_frame), | 283 video_frame), |
282 video_frame_time - elapsed_time); | 284 video_frame_time - elapsed_time); |
283 } else { | 285 } else { |
284 test_app_thread_proxy_->PostTask( | 286 test_app_thread_proxy_->PostTask( |
285 FROM_HERE, | 287 FROM_HERE, |
286 base::Bind(&SendProcess::SendVideoFrameOnTime, | 288 base::Bind(&SendProcess::SendVideoFrameOnTime, |
287 base::Unretained(this), | 289 weak_factory_.GetWeakPtr(), |
288 video_frame)); | 290 video_frame)); |
289 } | 291 } |
290 } | 292 } |
291 | 293 |
292 void SendVideoFrameOnTime(scoped_refptr<media::VideoFrame> video_frame) { | 294 void SendVideoFrameOnTime(scoped_refptr<media::VideoFrame> video_frame) { |
293 send_time_ = clock_->NowTicks(); | 295 send_time_ = clock_->NowTicks(); |
294 frame_input_->InsertRawVideoFrame(video_frame, send_time_); | 296 video_frame_input_->InsertRawVideoFrame(video_frame, send_time_); |
295 test_app_thread_proxy_->PostTask( | 297 test_app_thread_proxy_->PostTask( |
296 FROM_HERE, base::Bind(&SendProcess::SendFrame, base::Unretained(this))); | 298 FROM_HERE, base::Bind(&SendProcess::SendFrame, base::Unretained(this))); |
297 } | 299 } |
298 | 300 |
299 private: | 301 private: |
300 scoped_refptr<base::SingleThreadTaskRunner> test_app_thread_proxy_; | 302 scoped_refptr<base::SingleThreadTaskRunner> test_app_thread_proxy_; |
301 const VideoSenderConfig video_config_; | 303 const VideoSenderConfig video_config_; |
302 int audio_diff_; | 304 int audio_diff_; |
303 const scoped_refptr<FrameInput> frame_input_; | 305 const scoped_refptr<AudioFrameInput> audio_frame_input_; |
306 const scoped_refptr<VideoFrameInput> video_frame_input_; | |
304 FILE* video_file_; | 307 FILE* video_file_; |
305 uint8 synthetic_count_; | 308 uint8 synthetic_count_; |
306 base::TickClock* const clock_; // Not owned by this class. | 309 base::TickClock* const clock_; // Not owned by this class. |
307 base::TimeTicks start_time_; | 310 base::TimeTicks start_time_; |
308 base::TimeTicks send_time_; | 311 base::TimeTicks send_time_; |
309 scoped_ptr<TestAudioBusFactory> audio_bus_factory_; | 312 scoped_ptr<TestAudioBusFactory> audio_bus_factory_; |
310 base::WeakPtrFactory<SendProcess> weak_factory_; | 313 base::WeakPtrFactory<SendProcess> weak_factory_; |
311 }; | 314 }; |
312 | 315 |
313 } // namespace cast | 316 } // namespace cast |
314 } // namespace media | 317 } // namespace media |
315 | 318 |
316 namespace { | 319 namespace { |
317 void UpdateCastTransportStatus( | 320 void UpdateCastTransportStatus( |
318 media::cast::transport::CastTransportStatus status) {} | 321 media::cast::transport::CastTransportStatus status) {} |
319 | 322 |
320 void InitializationResult(media::cast::CastInitializationStatus result) { | 323 void InitializationResult(media::cast::CastInitializationStatus result) { |
321 CHECK_EQ(result, media::cast::STATUS_INITIALIZED); | 324 bool end_result = result == media::cast::STATUS_AUDIO_INITIALIZED || |
322 VLOG(1) << "Cast Sender initialized"; | 325 result == media::cast::STATUS_VIDEO_INITIALIZED; |
326 CHECK(end_result); | |
Alpha Left Google
2014/03/06 23:10:04
This should give a log message if !end_result is t
mikhal1
2014/03/06 23:38:53
Done.
| |
323 } | 327 } |
324 | 328 |
325 net::IPEndPoint CreateUDPAddress(std::string ip_str, int port) { | 329 net::IPEndPoint CreateUDPAddress(std::string ip_str, int port) { |
326 net::IPAddressNumber ip_number; | 330 net::IPAddressNumber ip_number; |
327 CHECK(net::ParseIPLiteralToNumber(ip_str, &ip_number)); | 331 CHECK(net::ParseIPLiteralToNumber(ip_str, &ip_number)); |
328 return net::IPEndPoint(ip_number, port); | 332 return net::IPEndPoint(ip_number, port); |
329 } | 333 } |
330 | 334 |
331 void WriteLogsToFileAndStopSubscribing( | 335 void WriteLogsToFileAndStopSubscribing( |
332 const scoped_refptr<media::cast::CastEnvironment>& cast_environment, | 336 const scoped_refptr<media::cast::CastEnvironment>& cast_environment, |
333 scoped_ptr<media::cast::EncodingEventSubscriber> video_event_subscriber, | 337 scoped_ptr<media::cast::EncodingEventSubscriber> video_event_subscriber, |
334 scoped_ptr<media::cast::EncodingEventSubscriber> audio_event_subscriber, | 338 scoped_ptr<media::cast::EncodingEventSubscriber> audio_event_subscriber, |
335 file_util::ScopedFILE log_file) { | 339 file_util::ScopedFILE log_file) { |
336 media::cast::LogSerializer serializer(media::cast::kMaxSerializedLogBytes); | 340 media::cast::LogSerializer serializer(media::cast::kMaxSerializedLogBytes); |
337 | 341 |
338 // Serialize video events. | 342 // Serialize video events. |
339 cast_environment->Logging()->RemoveRawEventSubscriber( | 343 cast_environment->Logging()->RemoveRawEventSubscriber( |
340 video_event_subscriber.get()); | 344 video_event_subscriber.get()); |
341 media::cast::FrameEventMap frame_events; | 345 media::cast::FrameEventMap frame_events; |
342 media::cast::PacketEventMap packet_events; | 346 media::cast::PacketEventMap packet_events; |
343 media::cast::RtpTimestamp first_rtp_timestamp; | 347 media::cast::RtpTimestamp first_rtp_timestamp; |
344 video_event_subscriber->GetEventsAndReset(&frame_events, &packet_events, | 348 video_event_subscriber->GetEventsAndReset( |
345 &first_rtp_timestamp); | 349 &frame_events, &packet_events, &first_rtp_timestamp); |
346 | 350 |
347 VLOG(0) << "Video frame map size: " << frame_events.size(); | 351 VLOG(0) << "Video frame map size: " << frame_events.size(); |
348 VLOG(0) << "Video packet map size: " << packet_events.size(); | 352 VLOG(0) << "Video packet map size: " << packet_events.size(); |
349 | 353 |
350 if (!serializer.SerializeEventsForStream(false, frame_events, packet_events, | 354 if (!serializer.SerializeEventsForStream( |
351 first_rtp_timestamp)) { | 355 false, frame_events, packet_events, first_rtp_timestamp)) { |
352 VLOG(1) << "Failed to serialize video events."; | 356 VLOG(1) << "Failed to serialize video events."; |
353 return; | 357 return; |
354 } | 358 } |
355 | 359 |
356 int length_so_far = serializer.GetSerializedLength(); | 360 int length_so_far = serializer.GetSerializedLength(); |
357 VLOG(0) << "Video events serialized length: " << length_so_far; | 361 VLOG(0) << "Video events serialized length: " << length_so_far; |
358 | 362 |
359 // Serialize audio events. | 363 // Serialize audio events. |
360 cast_environment->Logging()->RemoveRawEventSubscriber( | 364 cast_environment->Logging()->RemoveRawEventSubscriber( |
361 audio_event_subscriber.get()); | 365 audio_event_subscriber.get()); |
362 audio_event_subscriber->GetEventsAndReset(&frame_events, &packet_events, | 366 audio_event_subscriber->GetEventsAndReset( |
363 &first_rtp_timestamp); | 367 &frame_events, &packet_events, &first_rtp_timestamp); |
364 | 368 |
365 VLOG(0) << "Audio frame map size: " << frame_events.size(); | 369 VLOG(0) << "Audio frame map size: " << frame_events.size(); |
366 VLOG(0) << "Audio packet map size: " << packet_events.size(); | 370 VLOG(0) << "Audio packet map size: " << packet_events.size(); |
367 | 371 |
368 if (!serializer.SerializeEventsForStream(true, frame_events, packet_events, | 372 if (!serializer.SerializeEventsForStream( |
369 first_rtp_timestamp)) { | 373 true, frame_events, packet_events, first_rtp_timestamp)) { |
370 VLOG(1) << "Failed to serialize audio events."; | 374 VLOG(1) << "Failed to serialize audio events."; |
371 return; | 375 return; |
372 } | 376 } |
373 | 377 |
374 VLOG(0) << "Audio events serialized length: " | 378 VLOG(0) << "Audio events serialized length: " |
375 << serializer.GetSerializedLength() - length_so_far; | 379 << serializer.GetSerializedLength() - length_so_far; |
376 | 380 |
377 scoped_ptr<std::string> serialized_string = | 381 scoped_ptr<std::string> serialized_string = |
378 serializer.GetSerializedLogAndReset(); | 382 serializer.GetSerializedLogAndReset(); |
379 VLOG(0) << "Serialized string size: " << serialized_string->size(); | 383 VLOG(0) << "Serialized string size: " << serialized_string->size(); |
380 | 384 |
381 size_t ret = fwrite( | 385 size_t ret = fwrite( |
382 &(*serialized_string)[0], 1, serialized_string->size(), log_file.get()); | 386 &(*serialized_string)[0], 1, serialized_string->size(), log_file.get()); |
383 if (ret != serialized_string->size()) | 387 if (ret != serialized_string->size()) |
384 VLOG(1) << "Failed to write logs to file."; | 388 VLOG(1) << "Failed to write logs to file."; |
385 } | 389 } |
386 | 390 |
387 } // namespace | 391 } // namespace |
388 | 392 |
389 int main(int argc, char** argv) { | 393 int main(int argc, char** argv) { |
390 base::AtExitManager at_exit; | 394 base::AtExitManager at_exit; |
391 VLOG(1) << "Cast Sender"; | |
392 base::Thread test_thread("Cast sender test app thread"); | 395 base::Thread test_thread("Cast sender test app thread"); |
393 base::Thread audio_thread("Cast audio encoder thread"); | 396 base::Thread audio_thread("Cast audio encoder thread"); |
394 base::Thread video_thread("Cast video encoder thread"); | 397 base::Thread video_thread("Cast video encoder thread"); |
395 test_thread.Start(); | 398 test_thread.Start(); |
396 audio_thread.Start(); | 399 audio_thread.Start(); |
397 video_thread.Start(); | 400 video_thread.Start(); |
398 | 401 |
399 scoped_ptr<base::TickClock> clock(new base::DefaultTickClock()); | 402 scoped_ptr<base::TickClock> clock(new base::DefaultTickClock()); |
400 base::MessageLoopForIO io_message_loop; | 403 base::MessageLoopForIO io_message_loop; |
401 | 404 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
439 new media::cast::CastEnvironment( | 442 new media::cast::CastEnvironment( |
440 clock.Pass(), | 443 clock.Pass(), |
441 io_message_loop.message_loop_proxy(), | 444 io_message_loop.message_loop_proxy(), |
442 audio_thread.message_loop_proxy(), | 445 audio_thread.message_loop_proxy(), |
443 NULL, | 446 NULL, |
444 video_thread.message_loop_proxy(), | 447 video_thread.message_loop_proxy(), |
445 NULL, | 448 NULL, |
446 io_message_loop.message_loop_proxy(), | 449 io_message_loop.message_loop_proxy(), |
447 media::cast::GetLoggingConfigWithRawEventsAndStatsEnabled())); | 450 media::cast::GetLoggingConfigWithRawEventsAndStatsEnabled())); |
448 | 451 |
449 scoped_ptr<media::cast::CastSender> cast_sender( | 452 scoped_ptr<media::cast::CastSender> cast_sender = |
450 media::cast::CastSender::CreateCastSender( | 453 media::cast::CastSender::Create(cast_environment, transport_sender.get()); |
451 cast_environment, | 454 |
452 &audio_config, | 455 cast_sender->InitializeVideo( |
453 &video_config, | 456 video_config, base::Bind(&InitializationResult), NULL); |
454 NULL, // gpu_factories. | 457 cast_sender->InitializeAudio(audio_config, base::Bind(&InitializationResult)); |
455 base::Bind(&InitializationResult), | |
456 transport_sender.get())); | |
457 | 458 |
458 transport_sender->SetPacketReceiver(cast_sender->packet_receiver()); | 459 transport_sender->SetPacketReceiver(cast_sender->packet_receiver()); |
459 | 460 |
460 media::cast::FrameInput* frame_input = cast_sender->frame_input(); | 461 scoped_refptr<media::cast::AudioFrameInput> audio_frame_input = |
462 cast_sender->audio_frame_input(); | |
463 scoped_refptr<media::cast::VideoFrameInput> video_frame_input = | |
464 cast_sender->video_frame_input(); | |
461 scoped_ptr<media::cast::SendProcess> send_process( | 465 scoped_ptr<media::cast::SendProcess> send_process( |
462 new media::cast::SendProcess(test_thread.message_loop_proxy(), | 466 new media::cast::SendProcess(test_thread.message_loop_proxy(), |
463 cast_environment->Clock(), | 467 cast_environment->Clock(), |
464 video_config, | 468 video_config, |
465 frame_input)); | 469 audio_frame_input, |
470 video_frame_input)); | |
466 | 471 |
467 // Set up event subscribers. | 472 // Set up event subscribers. |
468 // TODO(imcheng): Set up separate subscribers for audio / video / other. | 473 // TODO(imcheng): Set up separate subscribers for audio / video / other. |
469 int logging_duration = media::cast::GetLoggingDuration(); | 474 int logging_duration = media::cast::GetLoggingDuration(); |
470 scoped_ptr<media::cast::EncodingEventSubscriber> video_event_subscriber; | 475 scoped_ptr<media::cast::EncodingEventSubscriber> video_event_subscriber; |
471 scoped_ptr<media::cast::EncodingEventSubscriber> audio_event_subscriber; | 476 scoped_ptr<media::cast::EncodingEventSubscriber> audio_event_subscriber; |
472 if (logging_duration > 0) { | 477 if (logging_duration > 0) { |
473 std::string log_file_name(media::cast::GetLogFileDestination()); | 478 std::string log_file_name(media::cast::GetLogFileDestination()); |
474 video_event_subscriber.reset(new media::cast::EncodingEventSubscriber( | 479 video_event_subscriber.reset(new media::cast::EncodingEventSubscriber( |
475 media::cast::VIDEO_EVENT, 10000)); | 480 media::cast::VIDEO_EVENT, 10000)); |
(...skipping 21 matching lines...) Expand all Loading... | |
497 | 502 |
498 test_thread.message_loop_proxy()->PostTask( | 503 test_thread.message_loop_proxy()->PostTask( |
499 FROM_HERE, | 504 FROM_HERE, |
500 base::Bind(&media::cast::SendProcess::SendFrame, | 505 base::Bind(&media::cast::SendProcess::SendFrame, |
501 base::Unretained(send_process.get()))); | 506 base::Unretained(send_process.get()))); |
502 | 507 |
503 io_message_loop.Run(); | 508 io_message_loop.Run(); |
504 | 509 |
505 return 0; | 510 return 0; |
506 } | 511 } |
OLD | NEW |