| 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/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 177 video_config.max_number_of_video_buffers_used = 1; | 177 video_config.max_number_of_video_buffers_used = 1; |
| 178 video_config.number_of_cores = 1; | 178 video_config.number_of_cores = 1; |
| 179 return video_config; | 179 return video_config; |
| 180 } | 180 } |
| 181 | 181 |
| 182 class SendProcess { | 182 class SendProcess { |
| 183 public: | 183 public: |
| 184 SendProcess(scoped_refptr<base::SingleThreadTaskRunner> thread_proxy, | 184 SendProcess(scoped_refptr<base::SingleThreadTaskRunner> thread_proxy, |
| 185 base::TickClock* clock, | 185 base::TickClock* clock, |
| 186 const VideoSenderConfig& video_config, | 186 const VideoSenderConfig& video_config, |
| 187 FrameInput* frame_input) | 187 scoped_refptr<AudioFrameInput> audio_frame_input, |
| 188 scoped_refptr<VideoFrameInput> video_frame_input) |
| 188 : test_app_thread_proxy_(thread_proxy), | 189 : test_app_thread_proxy_(thread_proxy), |
| 189 video_config_(video_config), | 190 video_config_(video_config), |
| 190 audio_diff_(kFrameTimerMs), | 191 audio_diff_(kFrameTimerMs), |
| 191 frame_input_(frame_input), | 192 audio_frame_input_(audio_frame_input), |
| 193 video_frame_input_(video_frame_input), |
| 192 synthetic_count_(0), | 194 synthetic_count_(0), |
| 193 clock_(clock), | 195 clock_(clock), |
| 194 start_time_(), | 196 start_time_(), |
| 195 send_time_(), | 197 send_time_(), |
| 196 weak_factory_(this) { | 198 weak_factory_(this) { |
| 197 audio_bus_factory_.reset(new TestAudioBusFactory(kAudioChannels, | 199 audio_bus_factory_.reset(new TestAudioBusFactory(kAudioChannels, |
| 198 kAudioSamplingFrequency, | 200 kAudioSamplingFrequency, |
| 199 kSoundFrequency, | 201 kSoundFrequency, |
| 200 kSoundVolume)); | 202 kSoundVolume)); |
| 201 if (ReadFromFile()) { | 203 if (ReadFromFile()) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 217 | 219 |
| 218 void SendFrame() { | 220 void SendFrame() { |
| 219 // Make sure that we don't drift. | 221 // Make sure that we don't drift. |
| 220 int num_10ms_blocks = audio_diff_ / 10; | 222 int num_10ms_blocks = audio_diff_ / 10; |
| 221 // Avoid drift. | 223 // Avoid drift. |
| 222 audio_diff_ += kFrameTimerMs - num_10ms_blocks * 10; | 224 audio_diff_ += kFrameTimerMs - num_10ms_blocks * 10; |
| 223 | 225 |
| 224 scoped_ptr<AudioBus> audio_bus(audio_bus_factory_->NextAudioBus( | 226 scoped_ptr<AudioBus> audio_bus(audio_bus_factory_->NextAudioBus( |
| 225 base::TimeDelta::FromMilliseconds(10) * num_10ms_blocks)); | 227 base::TimeDelta::FromMilliseconds(10) * num_10ms_blocks)); |
| 226 AudioBus* const audio_bus_ptr = audio_bus.get(); | 228 AudioBus* const audio_bus_ptr = audio_bus.get(); |
| 227 frame_input_->InsertAudio( | 229 audio_frame_input_->InsertAudio( |
| 228 audio_bus_ptr, | 230 audio_bus_ptr, |
| 229 clock_->NowTicks(), | 231 clock_->NowTicks(), |
| 230 base::Bind(&OwnThatAudioBus, base::Passed(&audio_bus))); | 232 base::Bind(&OwnThatAudioBus, base::Passed(&audio_bus))); |
| 231 | 233 |
| 232 gfx::Size size(video_config_.width, video_config_.height); | 234 gfx::Size size(video_config_.width, video_config_.height); |
| 233 // TODO(mikhal): Use the provided timestamp. | 235 // TODO(mikhal): Use the provided timestamp. |
| 234 if (start_time_.is_null()) | 236 if (start_time_.is_null()) |
| 235 start_time_ = clock_->NowTicks(); | 237 start_time_ = clock_->NowTicks(); |
| 236 base::TimeDelta time_diff = clock_->NowTicks() - start_time_; | 238 base::TimeDelta time_diff = clock_->NowTicks() - start_time_; |
| 237 scoped_refptr<media::VideoFrame> video_frame = | 239 scoped_refptr<media::VideoFrame> video_frame = |
| (...skipping 11 matching lines...) Expand all Loading... |
| 249 // Sleep if that time has yet to elapse. | 251 // Sleep if that time has yet to elapse. |
| 250 base::TimeTicks now = clock_->NowTicks(); | 252 base::TimeTicks now = clock_->NowTicks(); |
| 251 base::TimeDelta video_frame_time = | 253 base::TimeDelta video_frame_time = |
| 252 base::TimeDelta::FromMilliseconds(kFrameTimerMs); | 254 base::TimeDelta::FromMilliseconds(kFrameTimerMs); |
| 253 base::TimeDelta elapsed_time = now - send_time_; | 255 base::TimeDelta elapsed_time = now - send_time_; |
| 254 if (elapsed_time < video_frame_time) { | 256 if (elapsed_time < video_frame_time) { |
| 255 VLOG(1) << "Wait" << (video_frame_time - elapsed_time).InMilliseconds(); | 257 VLOG(1) << "Wait" << (video_frame_time - elapsed_time).InMilliseconds(); |
| 256 test_app_thread_proxy_->PostDelayedTask( | 258 test_app_thread_proxy_->PostDelayedTask( |
| 257 FROM_HERE, | 259 FROM_HERE, |
| 258 base::Bind(&SendProcess::SendVideoFrameOnTime, | 260 base::Bind(&SendProcess::SendVideoFrameOnTime, |
| 259 base::Unretained(this), | 261 weak_factory_.GetWeakPtr(), |
| 260 video_frame), | 262 video_frame), |
| 261 video_frame_time - elapsed_time); | 263 video_frame_time - elapsed_time); |
| 262 } else { | 264 } else { |
| 263 test_app_thread_proxy_->PostTask( | 265 test_app_thread_proxy_->PostTask( |
| 264 FROM_HERE, | 266 FROM_HERE, |
| 265 base::Bind(&SendProcess::SendVideoFrameOnTime, | 267 base::Bind(&SendProcess::SendVideoFrameOnTime, |
| 266 base::Unretained(this), | 268 weak_factory_.GetWeakPtr(), |
| 267 video_frame)); | 269 video_frame)); |
| 268 } | 270 } |
| 269 } | 271 } |
| 270 | 272 |
| 271 void SendVideoFrameOnTime(scoped_refptr<media::VideoFrame> video_frame) { | 273 void SendVideoFrameOnTime(scoped_refptr<media::VideoFrame> video_frame) { |
| 272 send_time_ = clock_->NowTicks(); | 274 send_time_ = clock_->NowTicks(); |
| 273 frame_input_->InsertRawVideoFrame(video_frame, send_time_); | 275 video_frame_input_->InsertRawVideoFrame(video_frame, send_time_); |
| 274 test_app_thread_proxy_->PostTask( | 276 test_app_thread_proxy_->PostTask( |
| 275 FROM_HERE, base::Bind(&SendProcess::SendFrame, base::Unretained(this))); | 277 FROM_HERE, base::Bind(&SendProcess::SendFrame, base::Unretained(this))); |
| 276 } | 278 } |
| 277 | 279 |
| 278 private: | 280 private: |
| 279 scoped_refptr<base::SingleThreadTaskRunner> test_app_thread_proxy_; | 281 scoped_refptr<base::SingleThreadTaskRunner> test_app_thread_proxy_; |
| 280 const VideoSenderConfig video_config_; | 282 const VideoSenderConfig video_config_; |
| 281 int audio_diff_; | 283 int audio_diff_; |
| 282 const scoped_refptr<FrameInput> frame_input_; | 284 const scoped_refptr<AudioFrameInput> audio_frame_input_; |
| 285 const scoped_refptr<VideoFrameInput> video_frame_input_; |
| 283 FILE* video_file_; | 286 FILE* video_file_; |
| 284 uint8 synthetic_count_; | 287 uint8 synthetic_count_; |
| 285 base::TickClock* const clock_; // Not owned by this class. | 288 base::TickClock* const clock_; // Not owned by this class. |
| 286 base::TimeTicks start_time_; | 289 base::TimeTicks start_time_; |
| 287 base::TimeTicks send_time_; | 290 base::TimeTicks send_time_; |
| 288 scoped_ptr<TestAudioBusFactory> audio_bus_factory_; | 291 scoped_ptr<TestAudioBusFactory> audio_bus_factory_; |
| 289 base::WeakPtrFactory<SendProcess> weak_factory_; | 292 base::WeakPtrFactory<SendProcess> weak_factory_; |
| 290 }; | 293 }; |
| 291 | 294 |
| 292 } // namespace cast | 295 } // namespace cast |
| 293 } // namespace media | 296 } // namespace media |
| 294 | 297 |
| 295 namespace { | 298 namespace { |
| 296 void UpdateCastTransportStatus( | 299 void UpdateCastTransportStatus( |
| 297 media::cast::transport::CastTransportStatus status) {} | 300 media::cast::transport::CastTransportStatus status) {} |
| 298 | 301 |
| 299 void InitializationResult(media::cast::CastInitializationStatus result) { | 302 void InitializationResult(media::cast::CastInitializationStatus result) { |
| 300 CHECK_EQ(result, media::cast::STATUS_INITIALIZED); | 303 bool end_result = result == media::cast::STATUS_AUDIO_INITIALIZED || |
| 301 VLOG(1) << "Cast Sender initialized"; | 304 result == media::cast::STATUS_VIDEO_INITIALIZED; |
| 305 CHECK(end_result); |
| 302 } | 306 } |
| 303 | 307 |
| 304 net::IPEndPoint CreateUDPAddress(std::string ip_str, int port) { | 308 net::IPEndPoint CreateUDPAddress(std::string ip_str, int port) { |
| 305 net::IPAddressNumber ip_number; | 309 net::IPAddressNumber ip_number; |
| 306 CHECK(net::ParseIPLiteralToNumber(ip_str, &ip_number)); | 310 CHECK(net::ParseIPLiteralToNumber(ip_str, &ip_number)); |
| 307 return net::IPEndPoint(ip_number, port); | 311 return net::IPEndPoint(ip_number, port); |
| 308 } | 312 } |
| 309 | 313 |
| 310 } // namespace | 314 } // namespace |
| 311 | 315 |
| 312 int main(int argc, char** argv) { | 316 int main(int argc, char** argv) { |
| 313 base::AtExitManager at_exit; | 317 base::AtExitManager at_exit; |
| 314 VLOG(1) << "Cast Sender"; | |
| 315 base::Thread test_thread("Cast sender test app thread"); | 318 base::Thread test_thread("Cast sender test app thread"); |
| 316 base::Thread audio_thread("Cast audio encoder thread"); | 319 base::Thread audio_thread("Cast audio encoder thread"); |
| 317 base::Thread video_thread("Cast video encoder thread"); | 320 base::Thread video_thread("Cast video encoder thread"); |
| 318 test_thread.Start(); | 321 test_thread.Start(); |
| 319 audio_thread.Start(); | 322 audio_thread.Start(); |
| 320 video_thread.Start(); | 323 video_thread.Start(); |
| 321 | 324 |
| 322 scoped_ptr<base::TickClock> clock(new base::DefaultTickClock()); | 325 scoped_ptr<base::TickClock> clock(new base::DefaultTickClock()); |
| 323 base::MessageLoopForIO io_message_loop; | 326 base::MessageLoopForIO io_message_loop; |
| 324 | 327 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 335 | 338 |
| 336 // Setting up transport config. | 339 // Setting up transport config. |
| 337 media::cast::transport::CastTransportConfig config; | 340 media::cast::transport::CastTransportConfig config; |
| 338 config.receiver_endpoint = CreateUDPAddress(remote_ip_address, remote_port); | 341 config.receiver_endpoint = CreateUDPAddress(remote_ip_address, remote_port); |
| 339 config.local_endpoint = CreateUDPAddress("0.0.0.0", 0); | 342 config.local_endpoint = CreateUDPAddress("0.0.0.0", 0); |
| 340 config.audio_ssrc = audio_config.sender_ssrc; | 343 config.audio_ssrc = audio_config.sender_ssrc; |
| 341 config.video_ssrc = video_config.sender_ssrc; | 344 config.video_ssrc = video_config.sender_ssrc; |
| 342 config.audio_rtp_config = audio_config.rtp_config; | 345 config.audio_rtp_config = audio_config.rtp_config; |
| 343 config.video_rtp_config = video_config.rtp_config; | 346 config.video_rtp_config = video_config.rtp_config; |
| 344 | 347 |
| 345 scoped_ptr<media::cast::transport::CastTransportSender> transport_sender( | 348 scoped_ptr<media::cast::transport::CastTransportSender> transport_sender = |
| 346 media::cast::transport::CastTransportSender::CreateCastTransportSender( | 349 media::cast::transport::CastTransportSender::Create( |
| 347 clock.get(), | 350 clock.get(), |
| 348 config, | 351 config, |
| 349 base::Bind(&UpdateCastTransportStatus), | 352 base::Bind(&UpdateCastTransportStatus), |
| 350 io_message_loop.message_loop_proxy())); | 353 io_message_loop.message_loop_proxy()); |
| 351 | 354 |
| 352 // Enable main and send side threads only. Disable logging. | 355 // Enable main and send side threads only. Disable logging. |
| 353 // Running transport on the main thread. | 356 // Running transport on the main thread. |
| 354 scoped_refptr<media::cast::CastEnvironment> cast_environment( | 357 scoped_refptr<media::cast::CastEnvironment> cast_environment( |
| 355 new media::cast::CastEnvironment( | 358 new media::cast::CastEnvironment( |
| 356 clock.Pass(), | 359 clock.Pass(), |
| 357 io_message_loop.message_loop_proxy(), | 360 io_message_loop.message_loop_proxy(), |
| 358 audio_thread.message_loop_proxy(), | 361 audio_thread.message_loop_proxy(), |
| 359 NULL, | 362 NULL, |
| 360 video_thread.message_loop_proxy(), | 363 video_thread.message_loop_proxy(), |
| 361 NULL, | 364 NULL, |
| 362 io_message_loop.message_loop_proxy(), | 365 io_message_loop.message_loop_proxy(), |
| 363 media::cast::GetDefaultCastSenderLoggingConfig())); | 366 media::cast::GetDefaultCastSenderLoggingConfig())); |
| 364 | 367 |
| 365 scoped_ptr<media::cast::CastSender> cast_sender( | 368 scoped_ptr<media::cast::CastSender> cast_sender = |
| 366 media::cast::CastSender::CreateCastSender( | 369 media::cast::CastSender::Create(cast_environment, |
| 367 cast_environment, | 370 base::Bind(&InitializationResult), |
| 368 &audio_config, | 371 transport_sender.get()); |
| 369 &video_config, | 372 |
| 370 NULL, // gpu_factories. | 373 cast_sender->InitializeVideo(video_config, NULL); |
| 371 base::Bind(&InitializationResult), | 374 cast_sender->InitializeAudio(audio_config); |
| 372 transport_sender.get())); | |
| 373 | 375 |
| 374 transport_sender->SetPacketReceiver(cast_sender->packet_receiver()); | 376 transport_sender->SetPacketReceiver(cast_sender->packet_receiver()); |
| 375 | 377 |
| 376 media::cast::FrameInput* frame_input = cast_sender->frame_input(); | 378 scoped_refptr<media::cast::AudioFrameInput> audio_frame_input = |
| 379 cast_sender->audio_frame_input(); |
| 380 scoped_refptr<media::cast::VideoFrameInput> video_frame_input = |
| 381 cast_sender->video_frame_input(); |
| 377 scoped_ptr<media::cast::SendProcess> send_process( | 382 scoped_ptr<media::cast::SendProcess> send_process( |
| 378 new media::cast::SendProcess(test_thread.message_loop_proxy(), | 383 new media::cast::SendProcess(test_thread.message_loop_proxy(), |
| 379 cast_environment->Clock(), | 384 cast_environment->Clock(), |
| 380 video_config, | 385 video_config, |
| 381 frame_input)); | 386 audio_frame_input, |
| 387 video_frame_input)); |
| 382 | 388 |
| 383 test_thread.message_loop_proxy()->PostTask( | 389 test_thread.message_loop_proxy()->PostTask( |
| 384 FROM_HERE, | 390 FROM_HERE, |
| 385 base::Bind(&media::cast::SendProcess::SendFrame, | 391 base::Bind(&media::cast::SendProcess::SendFrame, |
| 386 base::Unretained(send_process.get()))); | 392 base::Unretained(send_process.get()))); |
| 387 | 393 |
| 388 io_message_loop.Run(); | 394 io_message_loop.Run(); |
| 389 return 0; | 395 return 0; |
| 390 } | 396 } |
| OLD | NEW |