OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 #include "media/base/pipeline.h" | 5 #include "media/base/pipeline.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback.h" | 10 #include "base/callback.h" |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 DCHECK(stop_cb_.is_null()) | 284 DCHECK(stop_cb_.is_null()) |
285 << "State transitions don't happen when stopping"; | 285 << "State transitions don't happen when stopping"; |
286 DCHECK_EQ(status_, PIPELINE_OK) | 286 DCHECK_EQ(status_, PIPELINE_OK) |
287 << "State transitions don't happen when there's an error: " << status_; | 287 << "State transitions don't happen when there's an error: " << status_; |
288 | 288 |
289 switch (state_) { | 289 switch (state_) { |
290 case kCreated: | 290 case kCreated: |
291 return kInitDemuxer; | 291 return kInitDemuxer; |
292 | 292 |
293 case kInitDemuxer: | 293 case kInitDemuxer: |
294 if (demuxer_->GetStream(DemuxerStream::AUDIO)) | 294 if (demuxer_->GetStream(DemuxerStream::AUDIO).get()) |
295 return kInitAudioRenderer; | 295 return kInitAudioRenderer; |
296 if (demuxer_->GetStream(DemuxerStream::VIDEO)) | 296 if (demuxer_->GetStream(DemuxerStream::VIDEO).get()) |
297 return kInitVideoRenderer; | 297 return kInitVideoRenderer; |
298 return kInitPrerolling; | 298 return kInitPrerolling; |
299 | 299 |
300 case kInitAudioRenderer: | 300 case kInitAudioRenderer: |
301 if (demuxer_->GetStream(DemuxerStream::VIDEO)) | 301 if (demuxer_->GetStream(DemuxerStream::VIDEO).get()) |
302 return kInitVideoRenderer; | 302 return kInitVideoRenderer; |
303 return kInitPrerolling; | 303 return kInitPrerolling; |
304 | 304 |
305 case kInitVideoRenderer: | 305 case kInitVideoRenderer: |
306 return kInitPrerolling; | 306 return kInitPrerolling; |
307 | 307 |
308 case kInitPrerolling: | 308 case kInitPrerolling: |
309 return kStarting; | 309 return kStarting; |
310 | 310 |
311 case kSeeking: | 311 case kSeeking: |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
471 { | 471 { |
472 base::AutoLock l(lock_); | 472 base::AutoLock l(lock_); |
473 // We do not want to start the clock running. We only want to set the | 473 // We do not want to start the clock running. We only want to set the |
474 // base media time so our timestamp calculations will be correct. | 474 // base media time so our timestamp calculations will be correct. |
475 clock_->SetTime(demuxer_->GetStartTime(), demuxer_->GetStartTime()); | 475 clock_->SetTime(demuxer_->GetStartTime(), demuxer_->GetStartTime()); |
476 | 476 |
477 // TODO(scherkus): |has_audio_| should be true no matter what -- | 477 // TODO(scherkus): |has_audio_| should be true no matter what -- |
478 // otherwise people with muted/disabled sound cards will make our | 478 // otherwise people with muted/disabled sound cards will make our |
479 // default controls look as if every video doesn't contain an audio | 479 // default controls look as if every video doesn't contain an audio |
480 // track. | 480 // track. |
481 has_audio_ = audio_renderer_ != NULL && !audio_disabled_; | 481 has_audio_ = audio_renderer_.get() != NULL && !audio_disabled_; |
482 has_video_ = video_renderer_ != NULL; | 482 has_video_ = video_renderer_.get() != NULL; |
483 } | 483 } |
484 if (!audio_renderer_ && !video_renderer_) { | 484 if (!audio_renderer_.get() && !video_renderer_.get()) { |
485 done_cb.Run(PIPELINE_ERROR_COULD_NOT_RENDER); | 485 done_cb.Run(PIPELINE_ERROR_COULD_NOT_RENDER); |
486 return; | 486 return; |
487 } | 487 } |
488 | 488 |
489 buffering_state_cb_.Run(kHaveMetadata); | 489 buffering_state_cb_.Run(kHaveMetadata); |
490 | 490 |
491 return DoInitialPreroll(done_cb); | 491 return DoInitialPreroll(done_cb); |
492 | 492 |
493 case kStarting: | 493 case kStarting: |
494 return DoPlay(done_cb); | 494 return DoPlay(done_cb); |
(...skipping 29 matching lines...) Expand all Loading... |
524 } | 524 } |
525 | 525 |
526 void Pipeline::DoInitialPreroll(const PipelineStatusCB& done_cb) { | 526 void Pipeline::DoInitialPreroll(const PipelineStatusCB& done_cb) { |
527 DCHECK(message_loop_->BelongsToCurrentThread()); | 527 DCHECK(message_loop_->BelongsToCurrentThread()); |
528 DCHECK(!pending_callbacks_.get()); | 528 DCHECK(!pending_callbacks_.get()); |
529 SerialRunner::Queue bound_fns; | 529 SerialRunner::Queue bound_fns; |
530 | 530 |
531 base::TimeDelta seek_timestamp = demuxer_->GetStartTime(); | 531 base::TimeDelta seek_timestamp = demuxer_->GetStartTime(); |
532 | 532 |
533 // Preroll renderers. | 533 // Preroll renderers. |
534 if (audio_renderer_) { | 534 if (audio_renderer_.get()) { |
535 bound_fns.Push(base::Bind( | 535 bound_fns.Push(base::Bind( |
536 &AudioRenderer::Preroll, audio_renderer_, seek_timestamp)); | 536 &AudioRenderer::Preroll, audio_renderer_, seek_timestamp)); |
537 } | 537 } |
538 | 538 |
539 if (video_renderer_) { | 539 if (video_renderer_.get()) { |
540 bound_fns.Push(base::Bind( | 540 bound_fns.Push(base::Bind( |
541 &VideoRenderer::Preroll, video_renderer_, seek_timestamp)); | 541 &VideoRenderer::Preroll, video_renderer_, seek_timestamp)); |
542 } | 542 } |
543 | 543 |
544 pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb); | 544 pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb); |
545 } | 545 } |
546 | 546 |
547 void Pipeline::DoSeek( | 547 void Pipeline::DoSeek( |
548 base::TimeDelta seek_timestamp, | 548 base::TimeDelta seek_timestamp, |
549 const PipelineStatusCB& done_cb) { | 549 const PipelineStatusCB& done_cb) { |
550 DCHECK(message_loop_->BelongsToCurrentThread()); | 550 DCHECK(message_loop_->BelongsToCurrentThread()); |
551 DCHECK(!pending_callbacks_.get()); | 551 DCHECK(!pending_callbacks_.get()); |
552 SerialRunner::Queue bound_fns; | 552 SerialRunner::Queue bound_fns; |
553 | 553 |
554 // Pause. | 554 // Pause. |
555 if (audio_renderer_) | 555 if (audio_renderer_.get()) |
556 bound_fns.Push(base::Bind(&AudioRenderer::Pause, audio_renderer_)); | 556 bound_fns.Push(base::Bind(&AudioRenderer::Pause, audio_renderer_)); |
557 if (video_renderer_) | 557 if (video_renderer_.get()) |
558 bound_fns.Push(base::Bind(&VideoRenderer::Pause, video_renderer_)); | 558 bound_fns.Push(base::Bind(&VideoRenderer::Pause, video_renderer_)); |
559 | 559 |
560 // Flush. | 560 // Flush. |
561 if (audio_renderer_) | 561 if (audio_renderer_.get()) |
562 bound_fns.Push(base::Bind(&AudioRenderer::Flush, audio_renderer_)); | 562 bound_fns.Push(base::Bind(&AudioRenderer::Flush, audio_renderer_)); |
563 if (video_renderer_) | 563 if (video_renderer_.get()) |
564 bound_fns.Push(base::Bind(&VideoRenderer::Flush, video_renderer_)); | 564 bound_fns.Push(base::Bind(&VideoRenderer::Flush, video_renderer_)); |
565 | 565 |
566 // Seek demuxer. | 566 // Seek demuxer. |
567 bound_fns.Push(base::Bind( | 567 bound_fns.Push(base::Bind( |
568 &Demuxer::Seek, demuxer_, seek_timestamp)); | 568 &Demuxer::Seek, demuxer_, seek_timestamp)); |
569 | 569 |
570 // Preroll renderers. | 570 // Preroll renderers. |
571 if (audio_renderer_) { | 571 if (audio_renderer_.get()) { |
572 bound_fns.Push(base::Bind( | 572 bound_fns.Push(base::Bind( |
573 &AudioRenderer::Preroll, audio_renderer_, seek_timestamp)); | 573 &AudioRenderer::Preroll, audio_renderer_, seek_timestamp)); |
574 } | 574 } |
575 | 575 |
576 if (video_renderer_) { | 576 if (video_renderer_.get()) { |
577 bound_fns.Push(base::Bind( | 577 bound_fns.Push(base::Bind( |
578 &VideoRenderer::Preroll, video_renderer_, seek_timestamp)); | 578 &VideoRenderer::Preroll, video_renderer_, seek_timestamp)); |
579 } | 579 } |
580 | 580 |
581 pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb); | 581 pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb); |
582 } | 582 } |
583 | 583 |
584 void Pipeline::DoPlay(const PipelineStatusCB& done_cb) { | 584 void Pipeline::DoPlay(const PipelineStatusCB& done_cb) { |
585 DCHECK(message_loop_->BelongsToCurrentThread()); | 585 DCHECK(message_loop_->BelongsToCurrentThread()); |
586 DCHECK(!pending_callbacks_.get()); | 586 DCHECK(!pending_callbacks_.get()); |
587 SerialRunner::Queue bound_fns; | 587 SerialRunner::Queue bound_fns; |
588 | 588 |
589 PlaybackRateChangedTask(GetPlaybackRate()); | 589 PlaybackRateChangedTask(GetPlaybackRate()); |
590 VolumeChangedTask(GetVolume()); | 590 VolumeChangedTask(GetVolume()); |
591 | 591 |
592 if (audio_renderer_) | 592 if (audio_renderer_.get()) |
593 bound_fns.Push(base::Bind(&AudioRenderer::Play, audio_renderer_)); | 593 bound_fns.Push(base::Bind(&AudioRenderer::Play, audio_renderer_)); |
594 | 594 |
595 if (video_renderer_) | 595 if (video_renderer_.get()) |
596 bound_fns.Push(base::Bind(&VideoRenderer::Play, video_renderer_)); | 596 bound_fns.Push(base::Bind(&VideoRenderer::Play, video_renderer_)); |
597 | 597 |
598 pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb); | 598 pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb); |
599 } | 599 } |
600 | 600 |
601 void Pipeline::DoStop(const PipelineStatusCB& done_cb) { | 601 void Pipeline::DoStop(const PipelineStatusCB& done_cb) { |
602 DCHECK(message_loop_->BelongsToCurrentThread()); | 602 DCHECK(message_loop_->BelongsToCurrentThread()); |
603 DCHECK(!pending_callbacks_.get()); | 603 DCHECK(!pending_callbacks_.get()); |
604 SerialRunner::Queue bound_fns; | 604 SerialRunner::Queue bound_fns; |
605 | 605 |
606 if (demuxer_) | 606 if (demuxer_.get()) |
607 bound_fns.Push(base::Bind(&Demuxer::Stop, demuxer_)); | 607 bound_fns.Push(base::Bind(&Demuxer::Stop, demuxer_)); |
608 | 608 |
609 if (audio_renderer_) | 609 if (audio_renderer_.get()) |
610 bound_fns.Push(base::Bind(&AudioRenderer::Stop, audio_renderer_)); | 610 bound_fns.Push(base::Bind(&AudioRenderer::Stop, audio_renderer_)); |
611 | 611 |
612 if (video_renderer_) | 612 if (video_renderer_.get()) |
613 bound_fns.Push(base::Bind(&VideoRenderer::Stop, video_renderer_)); | 613 bound_fns.Push(base::Bind(&VideoRenderer::Stop, video_renderer_)); |
614 | 614 |
615 pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb); | 615 pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb); |
616 } | 616 } |
617 | 617 |
618 void Pipeline::OnStopCompleted(PipelineStatus status) { | 618 void Pipeline::OnStopCompleted(PipelineStatus status) { |
619 DCHECK(message_loop_->BelongsToCurrentThread()); | 619 DCHECK(message_loop_->BelongsToCurrentThread()); |
620 DCHECK_EQ(state_, kStopping); | 620 DCHECK_EQ(state_, kStopping); |
621 { | 621 { |
622 base::AutoLock l(lock_); | 622 base::AutoLock l(lock_); |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
746 | 746 |
747 // Playback rate changes are only carried out while playing. | 747 // Playback rate changes are only carried out while playing. |
748 if (state_ != kStarting && state_ != kStarted) | 748 if (state_ != kStarting && state_ != kStarted) |
749 return; | 749 return; |
750 | 750 |
751 { | 751 { |
752 base::AutoLock auto_lock(lock_); | 752 base::AutoLock auto_lock(lock_); |
753 clock_->SetPlaybackRate(playback_rate); | 753 clock_->SetPlaybackRate(playback_rate); |
754 } | 754 } |
755 | 755 |
756 if (demuxer_) | 756 if (demuxer_.get()) |
757 demuxer_->SetPlaybackRate(playback_rate); | 757 demuxer_->SetPlaybackRate(playback_rate); |
758 if (audio_renderer_) | 758 if (audio_renderer_.get()) |
759 audio_renderer_->SetPlaybackRate(playback_rate_); | 759 audio_renderer_->SetPlaybackRate(playback_rate_); |
760 if (video_renderer_) | 760 if (video_renderer_.get()) |
761 video_renderer_->SetPlaybackRate(playback_rate_); | 761 video_renderer_->SetPlaybackRate(playback_rate_); |
762 } | 762 } |
763 | 763 |
764 void Pipeline::VolumeChangedTask(float volume) { | 764 void Pipeline::VolumeChangedTask(float volume) { |
765 DCHECK(message_loop_->BelongsToCurrentThread()); | 765 DCHECK(message_loop_->BelongsToCurrentThread()); |
766 | 766 |
767 // Volume changes are only carried out while playing. | 767 // Volume changes are only carried out while playing. |
768 if (state_ != kStarting && state_ != kStarted) | 768 if (state_ != kStarting && state_ != kStarted) |
769 return; | 769 return; |
770 | 770 |
771 if (audio_renderer_) | 771 if (audio_renderer_.get()) |
772 audio_renderer_->SetVolume(volume); | 772 audio_renderer_->SetVolume(volume); |
773 } | 773 } |
774 | 774 |
775 void Pipeline::SeekTask(TimeDelta time, const PipelineStatusCB& seek_cb) { | 775 void Pipeline::SeekTask(TimeDelta time, const PipelineStatusCB& seek_cb) { |
776 DCHECK(message_loop_->BelongsToCurrentThread()); | 776 DCHECK(message_loop_->BelongsToCurrentThread()); |
777 DCHECK(stop_cb_.is_null()); | 777 DCHECK(stop_cb_.is_null()); |
778 | 778 |
779 // Suppress seeking if we're not fully started. | 779 // Suppress seeking if we're not fully started. |
780 if (state_ != kStarted) { | 780 if (state_ != kStarted) { |
781 DCHECK(state_ == kStopping || state_ == kStopped) | 781 DCHECK(state_ == kStopping || state_ == kStopped) |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
833 | 833 |
834 DCHECK(!video_ended_); | 834 DCHECK(!video_ended_); |
835 video_ended_ = true; | 835 video_ended_ = true; |
836 | 836 |
837 RunEndedCallbackIfNeeded(); | 837 RunEndedCallbackIfNeeded(); |
838 } | 838 } |
839 | 839 |
840 void Pipeline::RunEndedCallbackIfNeeded() { | 840 void Pipeline::RunEndedCallbackIfNeeded() { |
841 DCHECK(message_loop_->BelongsToCurrentThread()); | 841 DCHECK(message_loop_->BelongsToCurrentThread()); |
842 | 842 |
843 if (audio_renderer_ && !audio_ended_ && !audio_disabled_) | 843 if (audio_renderer_.get() && !audio_ended_ && !audio_disabled_) |
844 return; | 844 return; |
845 | 845 |
846 if (video_renderer_ && !video_ended_) | 846 if (video_renderer_.get() && !video_ended_) |
847 return; | 847 return; |
848 | 848 |
849 { | 849 { |
850 base::AutoLock auto_lock(lock_); | 850 base::AutoLock auto_lock(lock_); |
851 clock_->EndOfStream(); | 851 clock_->EndOfStream(); |
852 } | 852 } |
853 | 853 |
854 // TODO(scherkus): Change |ended_cb_| into a Closure. | 854 // TODO(scherkus): Change |ended_cb_| into a Closure. |
855 DCHECK_EQ(status_, PIPELINE_OK); | 855 DCHECK_EQ(status_, PIPELINE_OK); |
856 ended_cb_.Run(status_); | 856 ended_cb_.Run(status_); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
931 void Pipeline::OnAudioUnderflow() { | 931 void Pipeline::OnAudioUnderflow() { |
932 if (!message_loop_->BelongsToCurrentThread()) { | 932 if (!message_loop_->BelongsToCurrentThread()) { |
933 message_loop_->PostTask(FROM_HERE, base::Bind( | 933 message_loop_->PostTask(FROM_HERE, base::Bind( |
934 &Pipeline::OnAudioUnderflow, this)); | 934 &Pipeline::OnAudioUnderflow, this)); |
935 return; | 935 return; |
936 } | 936 } |
937 | 937 |
938 if (state_ != kStarted) | 938 if (state_ != kStarted) |
939 return; | 939 return; |
940 | 940 |
941 if (audio_renderer_) | 941 if (audio_renderer_.get()) |
942 audio_renderer_->ResumeAfterUnderflow(true); | 942 audio_renderer_->ResumeAfterUnderflow(true); |
943 } | 943 } |
944 | 944 |
945 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { | 945 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { |
946 lock_.AssertAcquired(); | 946 lock_.AssertAcquired(); |
947 if (!waiting_for_clock_update_) | 947 if (!waiting_for_clock_update_) |
948 return; | 948 return; |
949 | 949 |
950 waiting_for_clock_update_ = false; | 950 waiting_for_clock_update_ = false; |
951 clock_->Play(); | 951 clock_->Play(); |
952 } | 952 } |
953 | 953 |
954 } // namespace media | 954 } // namespace media |
OLD | NEW |