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 |