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 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
148 synthetic_count_(0), | 148 synthetic_count_(0), |
149 clock_(clock), | 149 clock_(clock), |
150 audio_frame_count_(0), | 150 audio_frame_count_(0), |
151 video_frame_count_(0), | 151 video_frame_count_(0), |
152 weak_factory_(this), | 152 weak_factory_(this), |
153 av_format_context_(NULL), | 153 av_format_context_(NULL), |
154 audio_stream_index_(-1), | 154 audio_stream_index_(-1), |
155 playback_rate_(1.0), | 155 playback_rate_(1.0), |
156 video_stream_index_(-1), | 156 video_stream_index_(-1), |
157 video_frame_rate_numerator_(video_config.max_frame_rate), | 157 video_frame_rate_numerator_(video_config.max_frame_rate), |
158 video_frame_rate_denominator_(1) { | 158 video_frame_rate_denominator_(1), |
159 video_first_pts_(0), | |
160 video_first_pts_set_(false) { | |
159 audio_bus_factory_.reset(new TestAudioBusFactory(kAudioChannels, | 161 audio_bus_factory_.reset(new TestAudioBusFactory(kAudioChannels, |
160 kAudioSamplingFrequency, | 162 kAudioSamplingFrequency, |
161 kSoundFrequency, | 163 kSoundFrequency, |
162 kSoundVolume)); | 164 kSoundVolume)); |
163 const CommandLine* cmd = CommandLine::ForCurrentProcess(); | 165 const CommandLine* cmd = CommandLine::ForCurrentProcess(); |
164 int override_fps = 0; | 166 int override_fps = 0; |
165 if (base::StringToInt(cmd->GetSwitchValueASCII(kSwitchFps), | 167 if (base::StringToInt(cmd->GetSwitchValueASCII(kSwitchFps), |
166 &override_fps)) { | 168 &override_fps)) { |
167 video_config_.max_frame_rate = override_fps; | 169 video_config_.max_frame_rate = override_fps; |
168 video_frame_rate_numerator_ = override_fps; | 170 video_frame_rate_numerator_ = override_fps; |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
281 void Start(scoped_refptr<AudioFrameInput> audio_frame_input, | 283 void Start(scoped_refptr<AudioFrameInput> audio_frame_input, |
282 scoped_refptr<VideoFrameInput> video_frame_input) { | 284 scoped_refptr<VideoFrameInput> video_frame_input) { |
283 audio_frame_input_ = audio_frame_input; | 285 audio_frame_input_ = audio_frame_input; |
284 video_frame_input_ = video_frame_input; | 286 video_frame_input_ = video_frame_input; |
285 | 287 |
286 LOG(INFO) << "Max Frame rate: " << video_config_.max_frame_rate; | 288 LOG(INFO) << "Max Frame rate: " << video_config_.max_frame_rate; |
287 LOG(INFO) << "Real Frame rate: " | 289 LOG(INFO) << "Real Frame rate: " |
288 << video_frame_rate_numerator_ << "/" | 290 << video_frame_rate_numerator_ << "/" |
289 << video_frame_rate_denominator_ << " fps."; | 291 << video_frame_rate_denominator_ << " fps."; |
290 LOG(INFO) << "Audio playback rate: " << playback_rate_; | 292 LOG(INFO) << "Audio playback rate: " << playback_rate_; |
293 | |
294 if (!is_transcoding_audio() && !is_transcoding_video()) { | |
295 // Send fake patterns. | |
296 test_app_thread_proxy_->PostTask( | |
297 FROM_HERE, | |
298 base::Bind( | |
299 &SendProcess::SendNextFakeFrame, | |
300 base::Unretained(this))); | |
301 return; | |
302 } | |
303 | |
304 // Send transcoding streams. | |
291 audio_algo_.Initialize(playback_rate_, audio_params_); | 305 audio_algo_.Initialize(playback_rate_, audio_params_); |
292 audio_algo_.FlushBuffers(); | 306 audio_algo_.FlushBuffers(); |
293 audio_fifo_input_bus_ = | 307 audio_fifo_input_bus_ = |
294 AudioBus::Create( | 308 AudioBus::Create( |
295 audio_params_.channels(), audio_params_.frames_per_buffer()); | 309 audio_params_.channels(), audio_params_.frames_per_buffer()); |
296 // Audio FIFO can carry all data fron AudioRendererAlgorithm. | 310 // Audio FIFO can carry all data fron AudioRendererAlgorithm. |
297 audio_fifo_.reset( | 311 audio_fifo_.reset( |
298 new AudioFifo(audio_params_.channels(), | 312 new AudioFifo(audio_params_.channels(), |
299 audio_algo_.QueueCapacity())); | 313 audio_algo_.QueueCapacity())); |
300 audio_resampler_.reset(new media::MultiChannelResampler( | 314 audio_resampler_.reset(new media::MultiChannelResampler( |
301 audio_params_.channels(), | 315 audio_params_.channels(), |
302 static_cast<double>(audio_params_.sample_rate()) / | 316 static_cast<double>(audio_params_.sample_rate()) / |
303 kAudioSamplingFrequency, | 317 kAudioSamplingFrequency, |
304 audio_params_.frames_per_buffer(), | 318 audio_params_.frames_per_buffer(), |
305 base::Bind(&SendProcess::ProvideData, base::Unretained(this)))); | 319 base::Bind(&SendProcess::ProvideData, base::Unretained(this)))); |
306 audio_decoded_ts_.reset( | |
307 new AudioTimestampHelper(audio_params_.sample_rate())); | |
308 audio_decoded_ts_->SetBaseTimestamp(base::TimeDelta()); | |
309 audio_scaled_ts_.reset( | |
310 new AudioTimestampHelper(audio_params_.sample_rate())); | |
311 audio_scaled_ts_->SetBaseTimestamp(base::TimeDelta()); | |
312 audio_resampled_ts_.reset( | |
313 new AudioTimestampHelper(kAudioSamplingFrequency)); | |
314 audio_resampled_ts_->SetBaseTimestamp(base::TimeDelta()); | |
315 test_app_thread_proxy_->PostTask( | 320 test_app_thread_proxy_->PostTask( |
316 FROM_HERE, | 321 FROM_HERE, |
317 base::Bind(&SendProcess::SendNextFrame, base::Unretained(this))); | 322 base::Bind( |
323 &SendProcess::SendNextFrame, | |
324 base::Unretained(this))); | |
318 } | 325 } |
319 | 326 |
320 void SendNextFrame() { | 327 void SendNextFakeFrame() { |
321 gfx::Size size(video_config_.width, video_config_.height); | 328 gfx::Size size(video_config_.width, video_config_.height); |
322 scoped_refptr<VideoFrame> video_frame = | 329 scoped_refptr<VideoFrame> video_frame = |
323 VideoFrame::CreateBlackFrame(size); | 330 VideoFrame::CreateBlackFrame(size); |
324 if (is_transcoding_video()) { | 331 PopulateVideoFrame(video_frame, synthetic_count_); |
325 Decode(false); | |
326 CHECK(!video_frame_queue_.empty()) << "No video frame."; | |
327 scoped_refptr<VideoFrame> decoded_frame = | |
328 video_frame_queue_.front(); | |
329 video_frame->set_timestamp(decoded_frame->timestamp()); | |
330 video_frame_queue_.pop(); | |
331 media::CopyPlane(VideoFrame::kYPlane, | |
332 decoded_frame->data(VideoFrame::kYPlane), | |
333 decoded_frame->stride(VideoFrame::kYPlane), | |
334 decoded_frame->rows(VideoFrame::kYPlane), | |
335 video_frame); | |
336 media::CopyPlane(VideoFrame::kUPlane, | |
337 decoded_frame->data(VideoFrame::kUPlane), | |
338 decoded_frame->stride(VideoFrame::kUPlane), | |
339 decoded_frame->rows(VideoFrame::kUPlane), | |
340 video_frame); | |
341 media::CopyPlane(VideoFrame::kVPlane, | |
342 decoded_frame->data(VideoFrame::kVPlane), | |
343 decoded_frame->stride(VideoFrame::kVPlane), | |
344 decoded_frame->rows(VideoFrame::kVPlane), | |
345 video_frame); | |
346 } else { | |
347 PopulateVideoFrame(video_frame, synthetic_count_); | |
348 } | |
349 ++synthetic_count_; | 332 ++synthetic_count_; |
350 | 333 |
351 base::TimeTicks now = clock_->NowTicks(); | 334 base::TimeTicks now = clock_->NowTicks(); |
352 if (start_time_.is_null()) | 335 if (start_time_.is_null()) |
353 start_time_ = now; | 336 start_time_ = now; |
354 | 337 |
355 base::TimeDelta video_time; | 338 base::TimeDelta video_time = VideoFrameTime(video_frame_count_); |
356 if (is_transcoding_video()) { | |
357 // Use the timestamp from the file if we're transcoding and | |
358 // playback rate is 1.0. | |
359 video_time = ScaleTimestamp(video_frame->timestamp()); | |
360 } else { | |
361 VideoFrameTime(video_frame_count_); | |
362 } | |
363 | |
364 video_frame->set_timestamp(video_time); | 339 video_frame->set_timestamp(video_time); |
365 video_frame_input_->InsertRawVideoFrame(video_frame, | 340 video_frame_input_->InsertRawVideoFrame(video_frame, |
366 start_time_ + video_time); | 341 start_time_ + video_time); |
367 | 342 |
368 if (is_transcoding_video()) { | |
369 // Decode next video frame to get the next frame's timestamp. | |
370 Decode(false); | |
371 CHECK(!video_frame_queue_.empty()) << "No video frame."; | |
372 video_time = ScaleTimestamp(video_frame_queue_.front()->timestamp()); | |
373 } else { | |
374 video_time = VideoFrameTime(++video_frame_count_); | |
375 } | |
376 | |
377 // Send just enough audio data to match next video frame's time. | 343 // Send just enough audio data to match next video frame's time. |
378 base::TimeDelta audio_time = AudioFrameTime(audio_frame_count_); | 344 base::TimeDelta audio_time = AudioFrameTime(audio_frame_count_); |
379 while (audio_time < video_time) { | 345 while (audio_time < video_time) { |
380 if (is_transcoding_audio()) { | 346 if (is_transcoding_audio()) { |
381 Decode(true); | 347 Decode(true); |
382 CHECK(!audio_bus_queue_.empty()) << "No audio decoded."; | 348 CHECK(!audio_bus_queue_.empty()) << "No audio decoded."; |
383 scoped_ptr<AudioBus> bus(audio_bus_queue_.front()); | 349 scoped_ptr<AudioBus> bus(audio_bus_queue_.front()); |
384 audio_bus_queue_.pop(); | 350 audio_bus_queue_.pop(); |
385 audio_frame_input_->InsertAudio( | 351 audio_frame_input_->InsertAudio( |
386 bus.Pass(), start_time_ + audio_time); | 352 bus.Pass(), start_time_ + audio_time); |
387 } else { | 353 } else { |
388 audio_frame_input_->InsertAudio( | 354 audio_frame_input_->InsertAudio( |
389 audio_bus_factory_->NextAudioBus( | 355 audio_bus_factory_->NextAudioBus( |
390 base::TimeDelta::FromMilliseconds(kAudioFrameMs)), | 356 base::TimeDelta::FromMilliseconds(kAudioFrameMs)), |
391 start_time_ + audio_time); | 357 start_time_ + audio_time); |
392 } | 358 } |
393 audio_time = AudioFrameTime(++audio_frame_count_); | 359 audio_time = AudioFrameTime(++audio_frame_count_); |
394 } | 360 } |
395 | 361 |
396 // This is the time since the stream started. | 362 // This is the time since the stream started. |
397 const base::TimeDelta elapsed_time = now - start_time_; | 363 const base::TimeDelta elapsed_time = now - start_time_; |
398 | 364 |
399 // Handle the case when decoding or frame generation cannot keep up. | 365 // Handle the case when frame generation cannot keep up. |
400 // Move the time ahead to match the next frame. | 366 // Move the time ahead to match the next frame. |
401 while (video_time < elapsed_time) { | 367 while (video_time < elapsed_time) { |
402 LOG(WARNING) << "Skipping one frame."; | 368 LOG(WARNING) << "Skipping one frame."; |
403 video_time = VideoFrameTime(++video_frame_count_); | 369 video_time = VideoFrameTime(++video_frame_count_); |
404 } | 370 } |
405 | 371 |
406 test_app_thread_proxy_->PostDelayedTask( | 372 test_app_thread_proxy_->PostDelayedTask( |
407 FROM_HERE, | 373 FROM_HERE, |
408 base::Bind(&SendProcess::SendNextFrame, | 374 base::Bind(&SendProcess::SendNextFakeFrame, |
409 weak_factory_.GetWeakPtr()), | 375 weak_factory_.GetWeakPtr()), |
410 video_time - elapsed_time); | 376 video_time - elapsed_time); |
411 } | 377 } |
412 | 378 |
379 // Return true if a frame was sent. | |
380 bool SendNextTranscodedVideo(base::TimeDelta elapsed_time) { | |
381 if (!is_transcoding_video()) | |
382 return false; | |
383 | |
384 Decode(false); | |
385 if (video_frame_queue_.empty()) | |
386 return false; | |
387 | |
388 scoped_refptr<VideoFrame> decoded_frame = | |
389 video_frame_queue_.front(); | |
390 if (elapsed_time < decoded_frame->timestamp()) | |
391 return false; | |
392 | |
393 gfx::Size size(video_config_.width, video_config_.height); | |
394 scoped_refptr<VideoFrame> video_frame = | |
395 VideoFrame::CreateBlackFrame(size); | |
396 video_frame_queue_.pop(); | |
397 media::CopyPlane(VideoFrame::kYPlane, | |
398 decoded_frame->data(VideoFrame::kYPlane), | |
399 decoded_frame->stride(VideoFrame::kYPlane), | |
400 decoded_frame->rows(VideoFrame::kYPlane), | |
401 video_frame); | |
402 media::CopyPlane(VideoFrame::kUPlane, | |
403 decoded_frame->data(VideoFrame::kUPlane), | |
404 decoded_frame->stride(VideoFrame::kUPlane), | |
405 decoded_frame->rows(VideoFrame::kUPlane), | |
406 video_frame); | |
407 media::CopyPlane(VideoFrame::kVPlane, | |
408 decoded_frame->data(VideoFrame::kVPlane), | |
409 decoded_frame->stride(VideoFrame::kVPlane), | |
410 decoded_frame->rows(VideoFrame::kVPlane), | |
411 video_frame); | |
412 | |
413 base::TimeDelta video_time; | |
414 // Use the timestamp from the file if we're transcoding and | |
415 // playback rate is 1.0. | |
hubbe
2014/04/24 22:32:51
Odd comment, what do we use if playback rate is no
| |
416 video_time = ScaleTimestamp(decoded_frame->timestamp()); | |
417 video_frame_input_->InsertRawVideoFrame( | |
418 video_frame, start_time_ + video_time); | |
419 | |
420 // Make sure queue is not empty. | |
421 Decode(false); | |
422 return true; | |
423 } | |
424 | |
425 // Return true if a frame was sent. | |
426 bool SendNextTranscodedAudio(base::TimeDelta elapsed_time) { | |
427 if (!is_transcoding_audio()) | |
428 return false; | |
429 | |
430 Decode(true); | |
431 if (audio_bus_queue_.empty()) | |
432 return false; | |
433 | |
434 base::TimeDelta audio_time = audio_sent_ts_->GetTimestamp(); | |
435 if (elapsed_time < audio_time) | |
436 return false; | |
437 scoped_ptr<AudioBus> bus(audio_bus_queue_.front()); | |
438 audio_bus_queue_.pop(); | |
439 audio_sent_ts_->AddFrames(bus->frames()); | |
440 audio_frame_input_->InsertAudio( | |
441 bus.Pass(), start_time_ + audio_time); | |
442 | |
443 // Make sure queue is not empty. | |
444 Decode(true); | |
445 return true; | |
446 } | |
447 | |
448 void SendNextFrame() { | |
449 if (start_time_.is_null()) | |
450 start_time_ = clock_->NowTicks(); | |
451 if (start_time_.is_null()) | |
452 start_time_ = clock_->NowTicks(); | |
453 | |
454 // Send as much as possible. Audio is sent according to | |
455 // system time. | |
456 while (SendNextTranscodedAudio( | |
457 clock_->NowTicks() - start_time_)); | |
hubbe
2014/04/24 22:32:51
weird indentation.
| |
458 // Video is sync'ed to audio. | |
459 while (SendNextTranscodedVideo( | |
460 audio_sent_ts_->GetTimestamp())); | |
hubbe
2014/04/24 22:32:51
weird indentation
| |
461 | |
462 if (audio_bus_queue_.empty() && video_frame_queue_.empty()) { | |
463 // Both queues are empty can only mean that we have reached | |
464 // the end of the stream. | |
465 LOG(INFO) << "Rewind."; | |
466 Rewind(); | |
467 start_time_ = base::TimeTicks(); | |
468 audio_sent_ts_.reset(); | |
469 video_first_pts_set_ = false; | |
470 } | |
471 | |
472 // Send next send. | |
473 test_app_thread_proxy_->PostDelayedTask( | |
474 FROM_HERE, | |
475 base::Bind( | |
476 &SendProcess::SendNextFrame, | |
477 base::Unretained(this)), | |
478 base::TimeDelta::FromMilliseconds(kAudioFrameMs)); | |
479 } | |
480 | |
413 const VideoSenderConfig& get_video_config() const { return video_config_; } | 481 const VideoSenderConfig& get_video_config() const { return video_config_; } |
414 | 482 |
415 private: | 483 private: |
416 bool is_transcoding_audio() { return audio_stream_index_ >= 0; } | 484 bool is_transcoding_audio() { return audio_stream_index_ >= 0; } |
417 bool is_transcoding_video() { return video_stream_index_ >= 0; } | 485 bool is_transcoding_video() { return video_stream_index_ >= 0; } |
418 | 486 |
419 // Helper methods to compute timestamps for the frame number specified. | 487 // Helper methods to compute timestamps for the frame number specified. |
420 base::TimeDelta VideoFrameTime(int frame_number) { | 488 base::TimeDelta VideoFrameTime(int frame_number) { |
421 return frame_number * base::TimeDelta::FromSeconds(1) * | 489 return frame_number * base::TimeDelta::FromSeconds(1) * |
422 video_frame_rate_denominator_ / video_frame_rate_numerator_; | 490 video_frame_rate_denominator_ / video_frame_rate_numerator_; |
(...skipping 11 matching lines...) Expand all Loading... | |
434 // Go to the beginning of the stream. | 502 // Go to the beginning of the stream. |
435 void Rewind() { | 503 void Rewind() { |
436 CHECK(av_seek_frame(av_format_context_, -1, 0, AVSEEK_FLAG_BACKWARD) >= 0) | 504 CHECK(av_seek_frame(av_format_context_, -1, 0, AVSEEK_FLAG_BACKWARD) >= 0) |
437 << "Failed to rewind to the beginning."; | 505 << "Failed to rewind to the beginning."; |
438 } | 506 } |
439 | 507 |
440 // Call FFmpeg to fetch one packet. | 508 // Call FFmpeg to fetch one packet. |
441 ScopedAVPacket DemuxOnePacket(bool* audio) { | 509 ScopedAVPacket DemuxOnePacket(bool* audio) { |
442 ScopedAVPacket packet(new AVPacket()); | 510 ScopedAVPacket packet(new AVPacket()); |
443 if (av_read_frame(av_format_context_, packet.get()) < 0) { | 511 if (av_read_frame(av_format_context_, packet.get()) < 0) { |
444 LOG(ERROR) << "Failed to read one AVPacket"; | 512 LOG(ERROR) << "Failed to read one AVPacket."; |
445 packet.reset(); | 513 packet.reset(); |
446 return packet.Pass(); | 514 return packet.Pass(); |
447 } | 515 } |
448 | 516 |
449 int stream_index = static_cast<int>(packet->stream_index); | 517 int stream_index = static_cast<int>(packet->stream_index); |
450 if (stream_index == audio_stream_index_) { | 518 if (stream_index == audio_stream_index_) { |
451 *audio = true; | 519 *audio = true; |
452 } else if (stream_index == video_stream_index_) { | 520 } else if (stream_index == video_stream_index_) { |
453 *audio = false; | 521 *audio = false; |
454 } else { | 522 } else { |
(...skipping 19 matching lines...) Expand all Loading... | |
474 CHECK(result >= 0) << "Failed to decode audio."; | 542 CHECK(result >= 0) << "Failed to decode audio."; |
475 packet_temp.size -= result; | 543 packet_temp.size -= result; |
476 packet_temp.data += result; | 544 packet_temp.data += result; |
477 if (!frame_decoded) | 545 if (!frame_decoded) |
478 continue; | 546 continue; |
479 | 547 |
480 int frames_read = avframe->nb_samples; | 548 int frames_read = avframe->nb_samples; |
481 if (frames_read < 0) | 549 if (frames_read < 0) |
482 break; | 550 break; |
483 | 551 |
552 if (!audio_sent_ts_) { | |
553 // Initialize the base time to the first packet in the file. | |
554 // This is set to the frequency we send to the receiver. | |
555 // Not the frequency of the source file. This is because we | |
556 // increment the frame count by samples we sent. | |
557 audio_sent_ts_.reset( | |
558 new AudioTimestampHelper(kAudioSamplingFrequency)); | |
559 // For some files this is an invalid value. | |
560 base::TimeDelta base_ts; | |
561 audio_sent_ts_->SetBaseTimestamp(base_ts); | |
562 } | |
563 | |
484 scoped_refptr<AudioBuffer> buffer = | 564 scoped_refptr<AudioBuffer> buffer = |
485 AudioBuffer::CopyFrom( | 565 AudioBuffer::CopyFrom( |
486 AVSampleFormatToSampleFormat( | 566 AVSampleFormatToSampleFormat( |
487 av_audio_context()->sample_fmt), | 567 av_audio_context()->sample_fmt), |
488 ChannelLayoutToChromeChannelLayout( | 568 ChannelLayoutToChromeChannelLayout( |
489 av_audio_context()->channel_layout, | 569 av_audio_context()->channel_layout, |
490 av_audio_context()->channels), | 570 av_audio_context()->channels), |
491 av_audio_context()->channels, | 571 av_audio_context()->channels, |
492 av_audio_context()->sample_rate, | 572 av_audio_context()->sample_rate, |
493 frames_read, | 573 frames_read, |
494 &avframe->data[0], | 574 &avframe->data[0], |
495 audio_decoded_ts_->GetTimestamp(), | 575 // Note: Not all files have correct values for pkt_pts. |
496 audio_decoded_ts_->GetFrameDuration(frames_read)); | 576 base::TimeDelta::FromMilliseconds(avframe->pkt_pts), |
577 // TODO(hclam): Give accurate duration based on samples. | |
578 base::TimeDelta()); | |
497 audio_algo_.EnqueueBuffer(buffer); | 579 audio_algo_.EnqueueBuffer(buffer); |
498 audio_decoded_ts_->AddFrames(frames_read); | |
499 } while (packet_temp.size > 0); | 580 } while (packet_temp.size > 0); |
500 avcodec_free_frame(&avframe); | 581 avcodec_free_frame(&avframe); |
501 | 582 |
502 const int frames_needed_to_scale = | 583 const int frames_needed_to_scale = |
503 playback_rate_ * av_audio_context()->sample_rate / | 584 playback_rate_ * av_audio_context()->sample_rate / |
504 kAudioPacketsPerSecond; | 585 kAudioPacketsPerSecond; |
505 while (frames_needed_to_scale <= audio_algo_.frames_buffered()) { | 586 while (frames_needed_to_scale <= audio_algo_.frames_buffered()) { |
506 if (!audio_algo_.FillBuffer(audio_fifo_input_bus_.get(), | 587 if (!audio_algo_.FillBuffer(audio_fifo_input_bus_.get(), |
507 audio_fifo_input_bus_->frames())) { | 588 audio_fifo_input_bus_->frames())) { |
508 // Nothing can be scaled. Decode some more. | 589 // Nothing can be scaled. Decode some more. |
509 return; | 590 return; |
510 } | 591 } |
511 audio_scaled_ts_->AddFrames(audio_fifo_input_bus_->frames()); | |
512 | 592 |
513 // Prevent overflow of audio data in the FIFO. | 593 // Prevent overflow of audio data in the FIFO. |
514 if (audio_fifo_input_bus_->frames() + audio_fifo_->frames() | 594 if (audio_fifo_input_bus_->frames() + audio_fifo_->frames() |
515 <= audio_fifo_->max_frames()) { | 595 <= audio_fifo_->max_frames()) { |
516 audio_fifo_->Push(audio_fifo_input_bus_.get()); | 596 audio_fifo_->Push(audio_fifo_input_bus_.get()); |
517 } else { | 597 } else { |
518 LOG(WARNING) << "Audio FIFO full; dropping samples."; | 598 LOG(WARNING) << "Audio FIFO full; dropping samples."; |
519 } | 599 } |
520 | 600 |
521 // Make sure there's enough data to resample audio. | 601 // Make sure there's enough data to resample audio. |
522 if (audio_fifo_->frames() < | 602 if (audio_fifo_->frames() < |
523 2 * audio_params_.sample_rate() / kAudioPacketsPerSecond) { | 603 2 * audio_params_.sample_rate() / kAudioPacketsPerSecond) { |
524 continue; | 604 continue; |
525 } | 605 } |
526 | 606 |
527 scoped_ptr<media::AudioBus> resampled_bus( | 607 scoped_ptr<media::AudioBus> resampled_bus( |
528 media::AudioBus::Create( | 608 media::AudioBus::Create( |
529 audio_params_.channels(), | 609 audio_params_.channels(), |
530 kAudioSamplingFrequency / kAudioPacketsPerSecond)); | 610 kAudioSamplingFrequency / kAudioPacketsPerSecond)); |
531 audio_resampler_->Resample(resampled_bus->frames(), | 611 audio_resampler_->Resample(resampled_bus->frames(), |
532 resampled_bus.get()); | 612 resampled_bus.get()); |
533 audio_resampled_ts_->AddFrames(resampled_bus->frames()); | |
534 audio_bus_queue_.push(resampled_bus.release()); | 613 audio_bus_queue_.push(resampled_bus.release()); |
535 } | 614 } |
536 } | 615 } |
537 | 616 |
538 void DecodeVideo(ScopedAVPacket packet) { | 617 void DecodeVideo(ScopedAVPacket packet) { |
539 // Video. | 618 // Video. |
540 int got_picture; | 619 int got_picture; |
541 AVFrame* avframe = av_frame_alloc(); | 620 AVFrame* avframe = av_frame_alloc(); |
542 avcodec_get_frame_defaults(avframe); | 621 avcodec_get_frame_defaults(avframe); |
543 // Tell the decoder to reorder for us. | 622 // Tell the decoder to reorder for us. |
544 avframe->reordered_opaque = | 623 avframe->reordered_opaque = |
545 av_video_context()->reordered_opaque = packet->pts; | 624 av_video_context()->reordered_opaque = packet->pts; |
546 CHECK(avcodec_decode_video2( | 625 CHECK(avcodec_decode_video2( |
547 av_video_context(), avframe, &got_picture, packet.get()) >= 0) | 626 av_video_context(), avframe, &got_picture, packet.get()) >= 0) |
548 << "Video decode error."; | 627 << "Video decode error."; |
549 if (!got_picture) | 628 if (!got_picture) |
550 return; | 629 return; |
551 gfx::Size size(av_video_context()->width, av_video_context()->height); | 630 gfx::Size size(av_video_context()->width, av_video_context()->height); |
631 if (!video_first_pts_set_ || | |
632 avframe->reordered_opaque < video_first_pts_) { | |
633 video_first_pts_set_ = true; | |
634 video_first_pts_ = avframe->reordered_opaque; | |
635 } | |
636 int64 pts = avframe->reordered_opaque - video_first_pts_; | |
552 video_frame_queue_.push( | 637 video_frame_queue_.push( |
553 VideoFrame::WrapExternalYuvData( | 638 VideoFrame::WrapExternalYuvData( |
554 media::VideoFrame::YV12, | 639 media::VideoFrame::YV12, |
555 size, | 640 size, |
556 gfx::Rect(size), | 641 gfx::Rect(size), |
557 size, | 642 size, |
558 avframe->linesize[0], | 643 avframe->linesize[0], |
559 avframe->linesize[1], | 644 avframe->linesize[1], |
560 avframe->linesize[2], | 645 avframe->linesize[2], |
561 avframe->data[0], | 646 avframe->data[0], |
562 avframe->data[1], | 647 avframe->data[1], |
563 avframe->data[2], | 648 avframe->data[2], |
564 base::TimeDelta::FromMilliseconds(avframe->reordered_opaque), | 649 base::TimeDelta::FromMilliseconds(pts), |
565 base::Bind(&AVFreeFrame, avframe))); | 650 base::Bind(&AVFreeFrame, avframe))); |
566 } | 651 } |
567 | 652 |
568 void Decode(bool decode_audio) { | 653 void Decode(bool decode_audio) { |
569 // Read the stream until one video frame can be decoded. | 654 // Read the stream until one video frame can be decoded. |
570 while (true) { | 655 while (true) { |
571 if (decode_audio && !audio_bus_queue_.empty()) | 656 if (decode_audio && !audio_bus_queue_.empty()) |
572 return; | 657 return; |
573 if (!decode_audio && !video_frame_queue_.empty()) | 658 if (!decode_audio && !video_frame_queue_.empty()) |
574 return; | 659 return; |
575 | 660 |
576 bool audio_packet = false; | 661 bool audio_packet = false; |
577 ScopedAVPacket packet = DemuxOnePacket(&audio_packet); | 662 ScopedAVPacket packet = DemuxOnePacket(&audio_packet); |
578 if (!packet) { | 663 if (!packet) { |
579 LOG(INFO) << "End of stream; Rewind."; | 664 LOG(INFO) << "End of stream."; |
580 Rewind(); | 665 return; |
581 continue; | |
582 } | 666 } |
583 | 667 |
584 if (audio_packet) | 668 if (audio_packet) |
585 DecodeAudio(packet.Pass()); | 669 DecodeAudio(packet.Pass()); |
586 else | 670 else |
587 DecodeVideo(packet.Pass()); | 671 DecodeVideo(packet.Pass()); |
588 } | 672 } |
589 } | 673 } |
590 | 674 |
591 void ProvideData(int frame_delay, media::AudioBus* output_bus) { | 675 void ProvideData(int frame_delay, media::AudioBus* output_bus) { |
(...skipping 13 matching lines...) Expand all Loading... | |
605 } | 689 } |
606 AVCodecContext* av_audio_context() { return av_audio_stream()->codec; } | 690 AVCodecContext* av_audio_context() { return av_audio_stream()->codec; } |
607 AVCodecContext* av_video_context() { return av_video_stream()->codec; } | 691 AVCodecContext* av_video_context() { return av_video_stream()->codec; } |
608 | 692 |
609 scoped_refptr<base::SingleThreadTaskRunner> test_app_thread_proxy_; | 693 scoped_refptr<base::SingleThreadTaskRunner> test_app_thread_proxy_; |
610 VideoSenderConfig video_config_; | 694 VideoSenderConfig video_config_; |
611 scoped_refptr<AudioFrameInput> audio_frame_input_; | 695 scoped_refptr<AudioFrameInput> audio_frame_input_; |
612 scoped_refptr<VideoFrameInput> video_frame_input_; | 696 scoped_refptr<VideoFrameInput> video_frame_input_; |
613 uint8 synthetic_count_; | 697 uint8 synthetic_count_; |
614 base::TickClock* const clock_; // Not owned by this class. | 698 base::TickClock* const clock_; // Not owned by this class. |
699 | |
700 // Time when the stream starts. | |
615 base::TimeTicks start_time_; | 701 base::TimeTicks start_time_; |
702 | |
703 // The following three members are used only for fake frames. | |
616 int audio_frame_count_; // Each audio frame is exactly 10ms. | 704 int audio_frame_count_; // Each audio frame is exactly 10ms. |
617 int video_frame_count_; | 705 int video_frame_count_; |
618 scoped_ptr<TestAudioBusFactory> audio_bus_factory_; | 706 scoped_ptr<TestAudioBusFactory> audio_bus_factory_; |
619 | 707 |
620 // NOTE: Weak pointers must be invalidated before all other member variables. | 708 // NOTE: Weak pointers must be invalidated before all other member variables. |
621 base::WeakPtrFactory<SendProcess> weak_factory_; | 709 base::WeakPtrFactory<SendProcess> weak_factory_; |
622 | 710 |
623 base::MemoryMappedFile file_data_; | 711 base::MemoryMappedFile file_data_; |
624 scoped_ptr<InMemoryUrlProtocol> protocol_; | 712 scoped_ptr<InMemoryUrlProtocol> protocol_; |
625 scoped_ptr<FFmpegGlue> glue_; | 713 scoped_ptr<FFmpegGlue> glue_; |
626 AVFormatContext* av_format_context_; | 714 AVFormatContext* av_format_context_; |
627 | 715 |
628 int audio_stream_index_; | 716 int audio_stream_index_; |
629 AudioParameters audio_params_; | 717 AudioParameters audio_params_; |
630 double playback_rate_; | 718 double playback_rate_; |
631 | 719 |
632 int video_stream_index_; | 720 int video_stream_index_; |
633 int video_frame_rate_numerator_; | 721 int video_frame_rate_numerator_; |
634 int video_frame_rate_denominator_; | 722 int video_frame_rate_denominator_; |
635 | 723 |
636 // These are used for audio resampling. | 724 // These are used for audio resampling. |
637 scoped_ptr<media::MultiChannelResampler> audio_resampler_; | 725 scoped_ptr<media::MultiChannelResampler> audio_resampler_; |
638 scoped_ptr<media::AudioFifo> audio_fifo_; | 726 scoped_ptr<media::AudioFifo> audio_fifo_; |
639 scoped_ptr<media::AudioBus> audio_fifo_input_bus_; | 727 scoped_ptr<media::AudioBus> audio_fifo_input_bus_; |
640 media::AudioRendererAlgorithm audio_algo_; | 728 media::AudioRendererAlgorithm audio_algo_; |
641 | 729 |
642 // These helpers are used to track frames generated. | 730 // Track the timestamp of audio sent to the receiver. |
643 // They are: | 731 scoped_ptr<media::AudioTimestampHelper> audio_sent_ts_; |
644 // * Frames decoded from the file. | |
645 // * Frames scaled according to playback rate. | |
646 // * Frames resampled to output frequency. | |
647 scoped_ptr<media::AudioTimestampHelper> audio_decoded_ts_; | |
648 scoped_ptr<media::AudioTimestampHelper> audio_scaled_ts_; | |
649 scoped_ptr<media::AudioTimestampHelper> audio_resampled_ts_; | |
650 | 732 |
651 std::queue<scoped_refptr<VideoFrame> > video_frame_queue_; | 733 std::queue<scoped_refptr<VideoFrame> > video_frame_queue_; |
734 int64 video_first_pts_; | |
735 bool video_first_pts_set_; | |
736 | |
652 std::queue<AudioBus*> audio_bus_queue_; | 737 std::queue<AudioBus*> audio_bus_queue_; |
653 | 738 |
654 DISALLOW_COPY_AND_ASSIGN(SendProcess); | 739 DISALLOW_COPY_AND_ASSIGN(SendProcess); |
655 }; | 740 }; |
656 | 741 |
657 } // namespace cast | 742 } // namespace cast |
658 } // namespace media | 743 } // namespace media |
659 | 744 |
660 namespace { | 745 namespace { |
661 void UpdateCastTransportStatus( | 746 void UpdateCastTransportStatus( |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
879 base::Passed(&video_event_subscriber), | 964 base::Passed(&video_event_subscriber), |
880 base::Passed(&audio_event_subscriber), | 965 base::Passed(&audio_event_subscriber), |
881 base::Passed(&video_log_file), | 966 base::Passed(&video_log_file), |
882 base::Passed(&audio_log_file)), | 967 base::Passed(&audio_log_file)), |
883 base::TimeDelta::FromSeconds(logging_duration_seconds)); | 968 base::TimeDelta::FromSeconds(logging_duration_seconds)); |
884 send_process->Start(cast_sender->audio_frame_input(), | 969 send_process->Start(cast_sender->audio_frame_input(), |
885 cast_sender->video_frame_input()); | 970 cast_sender->video_frame_input()); |
886 io_message_loop.Run(); | 971 io_message_loop.Run(); |
887 return 0; | 972 return 0; |
888 } | 973 } |
OLD | NEW |