Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(225)

Side by Side Diff: media/base/pipeline_impl.cc

Issue 6026013: Revert 70267 - Refactor PipelineImpl to use CompositeFilter to manage Filter ... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « media/base/pipeline_impl.h ('k') | media/media.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 // TODO(scherkus): clean up PipelineImpl... too many crazy function names, 5 // TODO(scherkus): clean up PipelineImpl... too many crazy function names,
6 // potential deadlocks, etc... 6 // potential deadlocks, etc...
7 7
8 #include "base/callback.h" 8 #include "base/callback.h"
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/condition_variable.h" 10 #include "base/condition_variable.h"
11 #include "base/stl_util-inl.h" 11 #include "base/stl_util-inl.h"
12 #include "media/base/clock_impl.h" 12 #include "media/base/clock_impl.h"
13 #include "media/base/filter_collection.h" 13 #include "media/base/filter_collection.h"
14 #include "media/base/media_format.h" 14 #include "media/base/media_format.h"
15 #include "media/base/pipeline_impl.h" 15 #include "media/base/pipeline_impl.h"
16 16
17 namespace media { 17 namespace media {
18 18
19 class PipelineImpl::PipelineInitState { 19 class PipelineImpl::PipelineInitState {
20 public: 20 public:
21 scoped_refptr<DataSource> data_source_; 21 scoped_refptr<DataSource> data_source_;
22 scoped_refptr<Demuxer> demuxer_; 22 scoped_refptr<Demuxer> demuxer_;
23 scoped_refptr<AudioDecoder> audio_decoder_; 23 scoped_refptr<AudioDecoder> audio_decoder_;
24 scoped_refptr<VideoDecoder> video_decoder_; 24 scoped_refptr<VideoDecoder> video_decoder_;
25 scoped_refptr<CompositeFilter> composite_;
26 }; 25 };
27 26
28 PipelineImpl::PipelineImpl(MessageLoop* message_loop) 27 PipelineImpl::PipelineImpl(MessageLoop* message_loop)
29 : message_loop_(message_loop), 28 : message_loop_(message_loop),
30 clock_(new ClockImpl(&base::Time::Now)), 29 clock_(new ClockImpl(&base::Time::Now)),
31 waiting_for_clock_update_(false), 30 waiting_for_clock_update_(false),
32 state_(kCreated), 31 state_(kCreated),
32 remaining_transitions_(0),
33 current_bytes_(0) { 33 current_bytes_(0) {
34 ResetState(); 34 ResetState();
35 } 35 }
36 36
37 PipelineImpl::~PipelineImpl() { 37 PipelineImpl::~PipelineImpl() {
38 AutoLock auto_lock(lock_); 38 AutoLock auto_lock(lock_);
39 DCHECK(!running_) << "Stop() must complete before destroying object"; 39 DCHECK(!running_) << "Stop() must complete before destroying object";
40 DCHECK(!stop_pending_); 40 DCHECK(!stop_pending_);
41 DCHECK(!seek_pending_); 41 DCHECK(!seek_pending_);
42 } 42 }
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 video_height_ = 0; 310 video_height_ = 0;
311 volume_ = 1.0f; 311 volume_ = 1.0f;
312 playback_rate_ = 0.0f; 312 playback_rate_ = 0.0f;
313 error_ = PIPELINE_OK; 313 error_ = PIPELINE_OK;
314 waiting_for_clock_update_ = false; 314 waiting_for_clock_update_ = false;
315 audio_disabled_ = false; 315 audio_disabled_ = false;
316 clock_->SetTime(kZero); 316 clock_->SetTime(kZero);
317 rendered_mime_types_.clear(); 317 rendered_mime_types_.clear();
318 } 318 }
319 319
320 void PipelineImpl::set_state(State next_state) {
321 state_ = next_state;
322 }
323
324 bool PipelineImpl::IsPipelineOk() { 320 bool PipelineImpl::IsPipelineOk() {
325 return PIPELINE_OK == GetError(); 321 return PIPELINE_OK == GetError();
326 } 322 }
327 323
328 bool PipelineImpl::IsPipelineInitializing() { 324 bool PipelineImpl::IsPipelineInitializing() {
329 DCHECK_EQ(MessageLoop::current(), message_loop_); 325 DCHECK_EQ(MessageLoop::current(), message_loop_);
330 return state_ == kInitDataSource || 326 return state_ == kInitDataSource ||
331 state_ == kInitDemuxer || 327 state_ == kInitDemuxer ||
332 state_ == kInitAudioDecoder || 328 state_ == kInitAudioDecoder ||
333 state_ == kInitAudioRenderer || 329 state_ == kInitAudioRenderer ||
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 if (IsPipelineStopPending() || 565 if (IsPipelineStopPending() ||
570 IsPipelineStopped() || 566 IsPipelineStopped() ||
571 PIPELINE_OK != GetError()) { 567 PIPELINE_OK != GetError()) {
572 return; 568 return;
573 } 569 }
574 570
575 DCHECK(state_ == kCreated || IsPipelineInitializing()); 571 DCHECK(state_ == kCreated || IsPipelineInitializing());
576 572
577 // Just created, create data source. 573 // Just created, create data source.
578 if (state_ == kCreated) { 574 if (state_ == kCreated) {
579 set_state(kInitDataSource); 575 state_ = kInitDataSource;
580 pipeline_init_state_.reset(new PipelineInitState()); 576 pipeline_init_state_.reset(new PipelineInitState());
581 pipeline_init_state_->composite_ = new CompositeFilter(message_loop_);
582 pipeline_init_state_->composite_->set_host(this);
583
584 InitializeDataSource(); 577 InitializeDataSource();
585 return; 578 return;
586 } 579 }
587 580
588 // Data source created, create demuxer. 581 // Data source created, create demuxer.
589 if (state_ == kInitDataSource) { 582 if (state_ == kInitDataSource) {
590 set_state(kInitDemuxer); 583 state_ = kInitDemuxer;
591 InitializeDemuxer(pipeline_init_state_->data_source_); 584 InitializeDemuxer(pipeline_init_state_->data_source_);
592 return; 585 return;
593 } 586 }
594 587
595 // Demuxer created, create audio decoder. 588 // Demuxer created, create audio decoder.
596 if (state_ == kInitDemuxer) { 589 if (state_ == kInitDemuxer) {
597 set_state(kInitAudioDecoder); 590 state_ = kInitAudioDecoder;
598 // If this method returns false, then there's no audio stream. 591 // If this method returns false, then there's no audio stream.
599 if (InitializeAudioDecoder(pipeline_init_state_->demuxer_)) 592 if (InitializeAudioDecoder(pipeline_init_state_->demuxer_))
600 return; 593 return;
601 } 594 }
602 595
603 // Assuming audio decoder was created, create audio renderer. 596 // Assuming audio decoder was created, create audio renderer.
604 if (state_ == kInitAudioDecoder) { 597 if (state_ == kInitAudioDecoder) {
605 set_state(kInitAudioRenderer); 598 state_ = kInitAudioRenderer;
606 // Returns false if there's no audio stream. 599 // Returns false if there's no audio stream.
607 if (InitializeAudioRenderer(pipeline_init_state_->audio_decoder_)) { 600 if (InitializeAudioRenderer(pipeline_init_state_->audio_decoder_)) {
608 InsertRenderedMimeType(mime_type::kMajorTypeAudio); 601 InsertRenderedMimeType(mime_type::kMajorTypeAudio);
609 return; 602 return;
610 } 603 }
611 } 604 }
612 605
613 // Assuming audio renderer was created, create video decoder. 606 // Assuming audio renderer was created, create video decoder.
614 if (state_ == kInitAudioRenderer) { 607 if (state_ == kInitAudioRenderer) {
615 // Then perform the stage of initialization, i.e. initialize video decoder. 608 // Then perform the stage of initialization, i.e. initialize video decoder.
616 set_state(kInitVideoDecoder); 609 state_ = kInitVideoDecoder;
617 if (InitializeVideoDecoder(pipeline_init_state_->demuxer_)) 610 if (InitializeVideoDecoder(pipeline_init_state_->demuxer_))
618 return; 611 return;
619 } 612 }
620 613
621 // Assuming video decoder was created, create video renderer. 614 // Assuming video decoder was created, create video renderer.
622 if (state_ == kInitVideoDecoder) { 615 if (state_ == kInitVideoDecoder) {
623 set_state(kInitVideoRenderer); 616 state_ = kInitVideoRenderer;
624 if (InitializeVideoRenderer(pipeline_init_state_->video_decoder_)) { 617 if (InitializeVideoRenderer(pipeline_init_state_->video_decoder_)) {
625 InsertRenderedMimeType(mime_type::kMajorTypeVideo); 618 InsertRenderedMimeType(mime_type::kMajorTypeVideo);
626 return; 619 return;
627 } 620 }
628 } 621 }
629 622
630 if (state_ == kInitVideoRenderer) { 623 if (state_ == kInitVideoRenderer) {
631 if (!IsPipelineOk() || !HasRenderedMimeTypes()) { 624 if (!IsPipelineOk() || !HasRenderedMimeTypes()) {
632 SetError(PIPELINE_ERROR_COULD_NOT_RENDER); 625 SetError(PIPELINE_ERROR_COULD_NOT_RENDER);
633 return; 626 return;
634 } 627 }
635 628
636 // Clear the collection of filters. 629 // Clear the collection of filters.
637 filter_collection_->Clear(); 630 filter_collection_->Clear();
638 631
639 pipeline_filter_ = pipeline_init_state_->composite_;
640
641 // Clear init state since we're done initializing. 632 // Clear init state since we're done initializing.
642 pipeline_init_state_.reset(); 633 pipeline_init_state_.reset();
643 634
644 // Initialization was successful, we are now considered paused, so it's safe 635 // Initialization was successful, we are now considered paused, so it's safe
645 // to set the initial playback rate and volume. 636 // to set the initial playback rate and volume.
646 PlaybackRateChangedTask(GetPlaybackRate()); 637 PlaybackRateChangedTask(GetPlaybackRate());
647 VolumeChangedTask(GetVolume()); 638 VolumeChangedTask(GetVolume());
648 639
649 // Fire the seek request to get the filters to preroll. 640 // Fire the initial seek request to get the filters to preroll.
650 seek_pending_ = true; 641 seek_pending_ = true;
651 set_state(kSeeking); 642 state_ = kSeeking;
643 remaining_transitions_ = filters_.size();
652 seek_timestamp_ = base::TimeDelta(); 644 seek_timestamp_ = base::TimeDelta();
653 pipeline_filter_->Seek(seek_timestamp_, 645 filters_.front()->Seek(seek_timestamp_,
654 NewCallback(this, &PipelineImpl::OnFilterStateTransition)); 646 NewCallback(this, &PipelineImpl::OnFilterStateTransition));
655 } 647 }
656 } 648 }
657 649
658 // This method is called as a result of the client calling Pipeline::Stop() or 650 // This method is called as a result of the client calling Pipeline::Stop() or
659 // as the result of an error condition. 651 // as the result of an error condition.
660 // We stop the filters in the reverse order. 652 // We stop the filters in the reverse order.
661 // 653 //
662 // TODO(scherkus): beware! this can get posted multiple times since we post 654 // TODO(scherkus): beware! this can get posted multiple times since we post
663 // Stop() tasks even if we've already stopped. Perhaps this should no-op for 655 // Stop() tasks even if we've already stopped. Perhaps this should no-op for
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 698
707 TearDownPipeline(); 699 TearDownPipeline();
708 } 700 }
709 701
710 void PipelineImpl::PlaybackRateChangedTask(float playback_rate) { 702 void PipelineImpl::PlaybackRateChangedTask(float playback_rate) {
711 DCHECK_EQ(MessageLoop::current(), message_loop_); 703 DCHECK_EQ(MessageLoop::current(), message_loop_);
712 { 704 {
713 AutoLock auto_lock(lock_); 705 AutoLock auto_lock(lock_);
714 clock_->SetPlaybackRate(playback_rate); 706 clock_->SetPlaybackRate(playback_rate);
715 } 707 }
716 pipeline_filter_->SetPlaybackRate(playback_rate); 708 for (FilterVector::iterator iter = filters_.begin();
709 iter != filters_.end();
710 ++iter) {
711 (*iter)->SetPlaybackRate(playback_rate);
712 }
717 } 713 }
718 714
719 void PipelineImpl::VolumeChangedTask(float volume) { 715 void PipelineImpl::VolumeChangedTask(float volume) {
720 DCHECK_EQ(MessageLoop::current(), message_loop_); 716 DCHECK_EQ(MessageLoop::current(), message_loop_);
721 717
722 if (audio_renderer_) { 718 if (audio_renderer_) {
723 audio_renderer_->SetVolume(volume); 719 audio_renderer_->SetVolume(volume);
724 } 720 }
725 } 721 }
726 722
(...skipping 15 matching lines...) Expand all
742 DCHECK(!seek_pending_); 738 DCHECK(!seek_pending_);
743 seek_pending_ = true; 739 seek_pending_ = true;
744 740
745 // We'll need to pause every filter before seeking. The state transition 741 // We'll need to pause every filter before seeking. The state transition
746 // is as follows: 742 // is as follows:
747 // kStarted/kEnded 743 // kStarted/kEnded
748 // kPausing (for each filter) 744 // kPausing (for each filter)
749 // kSeeking (for each filter) 745 // kSeeking (for each filter)
750 // kStarting (for each filter) 746 // kStarting (for each filter)
751 // kStarted 747 // kStarted
752 set_state(kPausing); 748 state_ = kPausing;
753 seek_timestamp_ = time; 749 seek_timestamp_ = time;
754 seek_callback_.reset(seek_callback); 750 seek_callback_.reset(seek_callback);
751 remaining_transitions_ = filters_.size();
755 752
756 // Kick off seeking! 753 // Kick off seeking!
757 { 754 {
758 AutoLock auto_lock(lock_); 755 AutoLock auto_lock(lock_);
759 // If we are waiting for a clock update, the clock hasn't been played yet. 756 // If we are waiting for a clock update, the clock hasn't been played yet.
760 if (!waiting_for_clock_update_) 757 if (!waiting_for_clock_update_)
761 clock_->Pause(); 758 clock_->Pause();
762 } 759 }
763 pipeline_filter_->Pause( 760 filters_.front()->Pause(
764 NewCallback(this, &PipelineImpl::OnFilterStateTransition)); 761 NewCallback(this, &PipelineImpl::OnFilterStateTransition));
765 } 762 }
766 763
767 void PipelineImpl::NotifyEndedTask() { 764 void PipelineImpl::NotifyEndedTask() {
768 DCHECK_EQ(MessageLoop::current(), message_loop_); 765 DCHECK_EQ(MessageLoop::current(), message_loop_);
769 766
770 // We can only end if we were actually playing. 767 // We can only end if we were actually playing.
771 if (state_ != kStarted) { 768 if (state_ != kStarted) {
772 return; 769 return;
773 } 770 }
(...skipping 12 matching lines...) Expand all
786 waiting_for_clock_update_ = false; 783 waiting_for_clock_update_ = false;
787 clock_->Play(); 784 clock_->Play();
788 } 785 }
789 } 786 }
790 787
791 if (video_renderer_ && !video_renderer_->HasEnded()) { 788 if (video_renderer_ && !video_renderer_->HasEnded()) {
792 return; 789 return;
793 } 790 }
794 791
795 // Transition to ended, executing the callback if present. 792 // Transition to ended, executing the callback if present.
796 set_state(kEnded); 793 state_ = kEnded;
797 if (ended_callback_.get()) { 794 if (ended_callback_.get()) {
798 ended_callback_->Run(); 795 ended_callback_->Run();
799 } 796 }
800 } 797 }
801 798
802 void PipelineImpl::NotifyNetworkEventTask() { 799 void PipelineImpl::NotifyNetworkEventTask() {
803 DCHECK_EQ(MessageLoop::current(), message_loop_); 800 DCHECK_EQ(MessageLoop::current(), message_loop_);
804 if (network_callback_.get()) { 801 if (network_callback_.get()) {
805 network_callback_->Run(); 802 network_callback_->Run();
806 } 803 }
807 } 804 }
808 805
809 void PipelineImpl::DisableAudioRendererTask() { 806 void PipelineImpl::DisableAudioRendererTask() {
810 DCHECK_EQ(MessageLoop::current(), message_loop_); 807 DCHECK_EQ(MessageLoop::current(), message_loop_);
811 808
812 // |rendered_mime_types_| is read through public methods so we need to lock 809 // |rendered_mime_types_| is read through public methods so we need to lock
813 // this variable. 810 // this variable.
814 AutoLock auto_lock(lock_); 811 AutoLock auto_lock(lock_);
815 rendered_mime_types_.erase(mime_type::kMajorTypeAudio); 812 rendered_mime_types_.erase(mime_type::kMajorTypeAudio);
816 813
817 audio_disabled_ = true; 814 audio_disabled_ = true;
818 815
819 // Notify all filters of disabled audio renderer. 816 // Notify all filters of disabled audio renderer.
820 pipeline_filter_->OnAudioRendererDisabled(); 817 for (FilterVector::iterator iter = filters_.begin();
818 iter != filters_.end();
819 ++iter) {
820 (*iter)->OnAudioRendererDisabled();
821 }
821 } 822 }
822 823
823 void PipelineImpl::FilterStateTransitionTask() { 824 void PipelineImpl::FilterStateTransitionTask() {
824 DCHECK_EQ(MessageLoop::current(), message_loop_); 825 DCHECK_EQ(MessageLoop::current(), message_loop_);
825 826
826 // No reason transitioning if we've errored or have stopped. 827 // No reason transitioning if we've errored or have stopped.
827 if (IsPipelineStopped()) { 828 if (IsPipelineStopped()) {
828 return; 829 return;
829 } 830 }
830 831
831 if (!TransientState(state_)) { 832 if (!TransientState(state_)) {
832 NOTREACHED() << "Invalid current state: " << state_; 833 NOTREACHED() << "Invalid current state: " << state_;
833 SetError(PIPELINE_ERROR_ABORT); 834 SetError(PIPELINE_ERROR_ABORT);
834 return; 835 return;
835 } 836 }
836 837
837 // Decrement the number of remaining transitions, making sure to transition 838 // Decrement the number of remaining transitions, making sure to transition
838 // to the next state if needed. 839 // to the next state if needed.
839 set_state(FindNextState(state_)); 840 DCHECK(remaining_transitions_ <= filters_.size());
840 if (state_ == kSeeking) { 841 DCHECK(remaining_transitions_ > 0u);
841 AutoLock auto_lock(lock_); 842 if (--remaining_transitions_ == 0) {
842 clock_->SetTime(seek_timestamp_); 843 state_ = FindNextState(state_);
844 if (state_ == kSeeking) {
845 AutoLock auto_lock(lock_);
846 clock_->SetTime(seek_timestamp_);
847 }
848
849 if (TransientState(state_)) {
850 remaining_transitions_ = filters_.size();
851 }
843 } 852 }
844 853
845 // Carry out the action for the current state. 854 // Carry out the action for the current state.
846 if (TransientState(state_)) { 855 if (TransientState(state_)) {
856 Filter* filter = filters_[filters_.size() - remaining_transitions_];
847 if (state_ == kPausing) { 857 if (state_ == kPausing) {
848 pipeline_filter_->Pause( 858 filter->Pause(NewCallback(this, &PipelineImpl::OnFilterStateTransition));
849 NewCallback(this, &PipelineImpl::OnFilterStateTransition));
850 } else if (state_ == kFlushing) { 859 } else if (state_ == kFlushing) {
851 pipeline_filter_->Flush( 860 // We had to use parallel flushing all filters.
852 NewCallback(this, &PipelineImpl::OnFilterStateTransition)); 861 if (remaining_transitions_ == filters_.size()) {
862 for (size_t i = 0; i < filters_.size(); i++) {
863 filters_[i]->Flush(
864 NewCallback(this, &PipelineImpl::OnFilterStateTransition));
865 }
866 }
853 } else if (state_ == kSeeking) { 867 } else if (state_ == kSeeking) {
854 pipeline_filter_->Seek(seek_timestamp_, 868 filter->Seek(seek_timestamp_,
855 NewCallback(this, &PipelineImpl::OnFilterStateTransition)); 869 NewCallback(this, &PipelineImpl::OnFilterStateTransition));
856 } else if (state_ == kStarting) { 870 } else if (state_ == kStarting) {
857 pipeline_filter_->Play( 871 filter->Play(NewCallback(this, &PipelineImpl::OnFilterStateTransition));
858 NewCallback(this,&PipelineImpl::OnFilterStateTransition));
859 } else if (state_ == kStopping) { 872 } else if (state_ == kStopping) {
860 pipeline_filter_->Stop( 873 filter->Stop(NewCallback(this, &PipelineImpl::OnFilterStateTransition));
861 NewCallback(this, &PipelineImpl::OnFilterStateTransition));
862 } else { 874 } else {
863 NOTREACHED() << "Unexpected state: " << state_; 875 NOTREACHED();
864 } 876 }
865 } else if (state_ == kStarted) { 877 } else if (state_ == kStarted) {
866 FinishInitialization(); 878 FinishInitialization();
867 879
868 // Finally, reset our seeking timestamp back to zero. 880 // Finally, reset our seeking timestamp back to zero.
869 seek_timestamp_ = base::TimeDelta(); 881 seek_timestamp_ = base::TimeDelta();
870 seek_pending_ = false; 882 seek_pending_ = false;
871 883
872 AutoLock auto_lock(lock_); 884 AutoLock auto_lock(lock_);
873 // We use audio stream to update the clock. So if there is such a stream, 885 // We use audio stream to update the clock. So if there is such a stream,
874 // we pause the clock until we receive a valid timestamp. 886 // we pause the clock until we receive a valid timestamp.
875 waiting_for_clock_update_ = 887 waiting_for_clock_update_ =
876 rendered_mime_types_.find(mime_type::kMajorTypeAudio) != 888 rendered_mime_types_.find(mime_type::kMajorTypeAudio) !=
877 rendered_mime_types_.end(); 889 rendered_mime_types_.end();
878 if (!waiting_for_clock_update_) 890 if (!waiting_for_clock_update_)
879 clock_->Play(); 891 clock_->Play();
880 892
881 if (IsPipelineStopPending()) { 893 if (IsPipelineStopPending()) {
882 // We had a pending stop request need to be honored right now. 894 // We had a pending stop request need to be honored right now.
883 TearDownPipeline(); 895 TearDownPipeline();
884 } 896 }
885 } else if (IsPipelineStopped()) { 897 } else if (IsPipelineStopped()) {
886 FinishDestroyingFiltersTask(); 898 FinishDestroyingFiltersTask();
887 } else { 899 } else {
888 NOTREACHED() << "Unexpected state: " << state_; 900 NOTREACHED();
889 } 901 }
890 } 902 }
891 903
892 void PipelineImpl::FinishDestroyingFiltersTask() { 904 void PipelineImpl::FinishDestroyingFiltersTask() {
893 DCHECK_EQ(MessageLoop::current(), message_loop_); 905 DCHECK_EQ(MessageLoop::current(), message_loop_);
894 DCHECK(IsPipelineStopped()); 906 DCHECK(IsPipelineStopped());
895 907
908 // Stop every running filter thread.
909 //
910 // TODO(scherkus): can we watchdog this section to detect wedged threads?
911 for (FilterThreadVector::iterator iter = filter_threads_.begin();
912 iter != filter_threads_.end();
913 ++iter) {
914 (*iter)->Stop();
915 }
916
896 // Clear renderer references. 917 // Clear renderer references.
897 audio_renderer_ = NULL; 918 audio_renderer_ = NULL;
898 video_renderer_ = NULL; 919 video_renderer_ = NULL;
899 920
900 pipeline_filter_ = NULL; 921 // Reset the pipeline, which will decrement a reference to this object.
922 // We will get destroyed as soon as the remaining tasks finish executing.
923 // To be safe, we'll set our pipeline reference to NULL.
924 filters_.clear();
925 STLDeleteElements(&filter_threads_);
901 926
902 stop_pending_ = false; 927 stop_pending_ = false;
903 tearing_down_ = false; 928 tearing_down_ = false;
904 929
905 if (PIPELINE_OK == GetError()) { 930 if (PIPELINE_OK == GetError()) {
906 // Destroying filters due to Stop(). 931 // Destroying filters due to Stop().
907 ResetState(); 932 ResetState();
908 933
909 // Notify the client that stopping has finished. 934 // Notify the client that stopping has finished.
910 if (stop_callback_.get()) { 935 if (stop_callback_.get()) {
911 stop_callback_->Run(); 936 stop_callback_->Run();
912 stop_callback_.reset(); 937 stop_callback_.reset();
913 } 938 }
914 } else { 939 } else {
915 // Destroying filters due to SetError(). 940 // Destroying filters due to SetError().
916 set_state(kError); 941 state_ = kError;
917 // If our owner has requested to be notified of an error. 942 // If our owner has requested to be notified of an error.
918 if (error_callback_.get()) { 943 if (error_callback_.get()) {
919 error_callback_->Run(); 944 error_callback_->Run();
920 } 945 }
921 } 946 }
922 } 947 }
923 948
924 bool PipelineImpl::PrepareFilter(scoped_refptr<Filter> filter) { 949 bool PipelineImpl::PrepareFilter(scoped_refptr<Filter> filter) {
925 bool ret = pipeline_init_state_->composite_->AddFilter(filter.get()); 950 DCHECK_EQ(MessageLoop::current(), message_loop_);
951 DCHECK(IsPipelineOk());
926 952
927 if (!ret) { 953 // Create a dedicated thread for this filter if applicable.
928 SetError(PIPELINE_ERROR_INITIALIZATION_FAILED); 954 if (filter->requires_message_loop()) {
955 scoped_ptr<base::Thread> thread(
956 new base::Thread(filter->message_loop_name()));
957 if (!thread.get() || !thread->Start()) {
958 NOTREACHED() << "Could not start filter thread";
959 SetError(PIPELINE_ERROR_INITIALIZATION_FAILED);
960 return false;
961 }
962
963 filter->set_message_loop(thread->message_loop());
964 filter_threads_.push_back(thread.release());
929 } 965 }
930 return ret; 966
967 // Register ourselves as the filter's host.
968 DCHECK(IsPipelineOk());
969 filter->set_host(this);
970 filters_.push_back(make_scoped_refptr(filter.get()));
971 return true;
931 } 972 }
932 973
933 void PipelineImpl::InitializeDataSource() { 974 void PipelineImpl::InitializeDataSource() {
934 DCHECK_EQ(MessageLoop::current(), message_loop_); 975 DCHECK_EQ(MessageLoop::current(), message_loop_);
935 DCHECK(IsPipelineOk()); 976 DCHECK(IsPipelineOk());
936 977
937 scoped_refptr<DataSource> data_source; 978 scoped_refptr<DataSource> data_source;
938 while (true) { 979 while (true) {
939 filter_collection_->SelectDataSource(&data_source); 980 filter_collection_->SelectDataSource(&data_source);
940 if (!data_source || data_source->IsUrlSupported(url_)) 981 if (!data_source || data_source->IsUrlSupported(url_))
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
1097 } 1138 }
1098 1139
1099 void PipelineImpl::TearDownPipeline() { 1140 void PipelineImpl::TearDownPipeline() {
1100 DCHECK_EQ(MessageLoop::current(), message_loop_); 1141 DCHECK_EQ(MessageLoop::current(), message_loop_);
1101 DCHECK_NE(kStopped, state_); 1142 DCHECK_NE(kStopped, state_);
1102 1143
1103 // Mark that we already start tearing down operation. 1144 // Mark that we already start tearing down operation.
1104 tearing_down_ = true; 1145 tearing_down_ = true;
1105 1146
1106 if (IsPipelineInitializing()) { 1147 if (IsPipelineInitializing()) {
1107 // Make it look like initialization was successful. 1148 // Notify the client that starting did not complete, if necessary.
1108 pipeline_filter_ = pipeline_init_state_->composite_; 1149 FinishInitialization();
1109 pipeline_init_state_.reset(); 1150 }
1110 1151
1111 set_state(kStopping); 1152 remaining_transitions_ = filters_.size();
1112 pipeline_filter_->Stop(NewCallback( 1153 if (remaining_transitions_ > 0) {
1113 this, &PipelineImpl::OnFilterStateTransition)); 1154 if (IsPipelineInitializing()) {
1114 1155 state_ = kStopping;
1115 FinishInitialization(); 1156 filters_.front()->Stop(NewCallback(
1116 } else if (pipeline_filter_.get()) { 1157 this, &PipelineImpl::OnFilterStateTransition));
1117 set_state(kPausing); 1158 } else {
1118 pipeline_filter_->Pause(NewCallback( 1159 state_ = kPausing;
1119 this, &PipelineImpl::OnFilterStateTransition)); 1160 filters_.front()->Pause(NewCallback(
1161 this, &PipelineImpl::OnFilterStateTransition));
1162 }
1120 } else { 1163 } else {
1121 set_state(kStopped); 1164 state_ = kStopped;
1122 message_loop_->PostTask(FROM_HERE, 1165 message_loop_->PostTask(FROM_HERE,
1123 NewRunnableMethod(this, &PipelineImpl::FinishDestroyingFiltersTask)); 1166 NewRunnableMethod(this, &PipelineImpl::FinishDestroyingFiltersTask));
1124 } 1167 }
1125 } 1168 }
1126 1169
1127 } // namespace media 1170 } // namespace media
OLDNEW
« no previous file with comments | « media/base/pipeline_impl.h ('k') | media/media.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698