OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "media/base/pipeline_impl.h" | 8 #include "media/base/pipeline_impl.h" |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 } | 48 } |
49 | 49 |
50 media::PipelineStatus PipelineStatusNotification::status() { | 50 media::PipelineStatus PipelineStatusNotification::status() { |
51 base::AutoLock auto_lock(lock_); | 51 base::AutoLock auto_lock(lock_); |
52 DCHECK(notified_); | 52 DCHECK(notified_); |
53 return status_; | 53 return status_; |
54 } | 54 } |
55 | 55 |
56 class PipelineImpl::PipelineInitState { | 56 class PipelineImpl::PipelineInitState { |
57 public: | 57 public: |
58 scoped_refptr<Demuxer> demuxer_; | |
59 scoped_refptr<AudioDecoder> audio_decoder_; | 58 scoped_refptr<AudioDecoder> audio_decoder_; |
60 scoped_refptr<VideoDecoder> video_decoder_; | 59 scoped_refptr<VideoDecoder> video_decoder_; |
61 scoped_refptr<CompositeFilter> composite_; | 60 scoped_refptr<CompositeFilter> composite_; |
62 }; | 61 }; |
63 | 62 |
64 PipelineImpl::PipelineImpl(MessageLoop* message_loop) | 63 PipelineImpl::PipelineImpl(MessageLoop* message_loop) |
65 : message_loop_(message_loop), | 64 : message_loop_(message_loop), |
66 clock_(new Clock(&base::Time::Now)), | 65 clock_(new Clock(&base::Time::Now)), |
67 waiting_for_clock_update_(false), | 66 waiting_for_clock_update_(false), |
68 state_(kCreated), | 67 state_(kCreated), |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 | 211 |
213 base::AutoLock auto_lock(lock_); | 212 base::AutoLock auto_lock(lock_); |
214 volume_ = volume; | 213 volume_ = volume; |
215 if (running_) { | 214 if (running_) { |
216 message_loop_->PostTask(FROM_HERE, | 215 message_loop_->PostTask(FROM_HERE, |
217 NewRunnableMethod(this, &PipelineImpl::VolumeChangedTask, | 216 NewRunnableMethod(this, &PipelineImpl::VolumeChangedTask, |
218 volume)); | 217 volume)); |
219 } | 218 } |
220 } | 219 } |
221 | 220 |
| 221 Preload PipelineImpl::GetPreload() const { |
| 222 base::AutoLock auto_lock(lock_); |
| 223 return preload_; |
| 224 } |
| 225 |
| 226 void PipelineImpl::SetPreload(Preload preload) { |
| 227 base::AutoLock auto_lock(lock_); |
| 228 preload_ = preload; |
| 229 if (running_) { |
| 230 message_loop_->PostTask(FROM_HERE, |
| 231 NewRunnableMethod(this, &PipelineImpl::PreloadChangedTask, |
| 232 preload)); |
| 233 } |
| 234 } |
| 235 |
222 base::TimeDelta PipelineImpl::GetCurrentTime() const { | 236 base::TimeDelta PipelineImpl::GetCurrentTime() const { |
223 // TODO(scherkus): perhaps replace checking state_ == kEnded with a bool that | 237 // TODO(scherkus): perhaps replace checking state_ == kEnded with a bool that |
224 // is set/get under the lock, because this is breaching the contract that | 238 // is set/get under the lock, because this is breaching the contract that |
225 // |state_| is only accessed on |message_loop_|. | 239 // |state_| is only accessed on |message_loop_|. |
226 base::AutoLock auto_lock(lock_); | 240 base::AutoLock auto_lock(lock_); |
227 return GetCurrentTime_Locked(); | 241 return GetCurrentTime_Locked(); |
228 } | 242 } |
229 | 243 |
230 base::TimeDelta PipelineImpl::GetCurrentTime_Locked() const { | 244 base::TimeDelta PipelineImpl::GetCurrentTime_Locked() const { |
231 base::TimeDelta elapsed = clock_->Elapsed(); | 245 base::TimeDelta elapsed = clock_->Elapsed(); |
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
623 state_ == kInitAudioDecoder || | 637 state_ == kInitAudioDecoder || |
624 state_ == kInitAudioRenderer || | 638 state_ == kInitAudioRenderer || |
625 state_ == kInitVideoDecoder || | 639 state_ == kInitVideoDecoder || |
626 state_ == kInitVideoRenderer); | 640 state_ == kInitVideoRenderer); |
627 | 641 |
628 | 642 |
629 // Demuxer created, create audio decoder. | 643 // Demuxer created, create audio decoder. |
630 if (state_ == kInitDemuxer) { | 644 if (state_ == kInitDemuxer) { |
631 set_state(kInitAudioDecoder); | 645 set_state(kInitAudioDecoder); |
632 // If this method returns false, then there's no audio stream. | 646 // If this method returns false, then there's no audio stream. |
633 if (InitializeAudioDecoder(pipeline_init_state_->demuxer_)) | 647 if (InitializeAudioDecoder(demuxer_)) |
634 return; | 648 return; |
635 } | 649 } |
636 | 650 |
637 // Assuming audio decoder was created, create audio renderer. | 651 // Assuming audio decoder was created, create audio renderer. |
638 if (state_ == kInitAudioDecoder) { | 652 if (state_ == kInitAudioDecoder) { |
639 set_state(kInitAudioRenderer); | 653 set_state(kInitAudioRenderer); |
640 // Returns false if there's no audio stream. | 654 // Returns false if there's no audio stream. |
641 if (InitializeAudioRenderer(pipeline_init_state_->audio_decoder_)) { | 655 if (InitializeAudioRenderer(pipeline_init_state_->audio_decoder_)) { |
642 base::AutoLock auto_lock(lock_); | 656 base::AutoLock auto_lock(lock_); |
643 has_audio_ = true; | 657 has_audio_ = true; |
644 return; | 658 return; |
645 } | 659 } |
646 } | 660 } |
647 | 661 |
648 // Assuming audio renderer was created, create video decoder. | 662 // Assuming audio renderer was created, create video decoder. |
649 if (state_ == kInitAudioRenderer) { | 663 if (state_ == kInitAudioRenderer) { |
650 // Then perform the stage of initialization, i.e. initialize video decoder. | 664 // Then perform the stage of initialization, i.e. initialize video decoder. |
651 set_state(kInitVideoDecoder); | 665 set_state(kInitVideoDecoder); |
652 if (InitializeVideoDecoder(pipeline_init_state_->demuxer_)) | 666 if (InitializeVideoDecoder(demuxer_)) |
653 return; | 667 return; |
654 } | 668 } |
655 | 669 |
656 // Assuming video decoder was created, create video renderer. | 670 // Assuming video decoder was created, create video renderer. |
657 if (state_ == kInitVideoDecoder) { | 671 if (state_ == kInitVideoDecoder) { |
658 set_state(kInitVideoRenderer); | 672 set_state(kInitVideoRenderer); |
659 if (InitializeVideoRenderer(pipeline_init_state_->video_decoder_)) { | 673 if (InitializeVideoRenderer(pipeline_init_state_->video_decoder_)) { |
660 base::AutoLock auto_lock(lock_); | 674 base::AutoLock auto_lock(lock_); |
661 has_video_ = true; | 675 has_video_ = true; |
662 return; | 676 return; |
(...skipping 15 matching lines...) Expand all Loading... |
678 pipeline_init_state_.reset(); | 692 pipeline_init_state_.reset(); |
679 | 693 |
680 if (audio_disabled_) { | 694 if (audio_disabled_) { |
681 // Audio was disabled at some point during initialization. Notify | 695 // Audio was disabled at some point during initialization. Notify |
682 // the pipeline filter now that it has been initialized. | 696 // the pipeline filter now that it has been initialized. |
683 pipeline_filter_->OnAudioRendererDisabled(); | 697 pipeline_filter_->OnAudioRendererDisabled(); |
684 } | 698 } |
685 | 699 |
686 // Initialization was successful, we are now considered paused, so it's safe | 700 // Initialization was successful, we are now considered paused, so it's safe |
687 // to set the initial playback rate and volume. | 701 // to set the initial playback rate and volume. |
| 702 PreloadChangedTask(GetPreload()); |
688 PlaybackRateChangedTask(GetPlaybackRate()); | 703 PlaybackRateChangedTask(GetPlaybackRate()); |
689 VolumeChangedTask(GetVolume()); | 704 VolumeChangedTask(GetVolume()); |
690 | 705 |
691 // Fire the seek request to get the filters to preroll. | 706 // Fire the seek request to get the filters to preroll. |
692 seek_pending_ = true; | 707 seek_pending_ = true; |
693 set_state(kSeeking); | 708 set_state(kSeeking); |
694 seek_timestamp_ = base::TimeDelta(); | 709 seek_timestamp_ = base::TimeDelta(); |
695 pipeline_filter_->Seek(seek_timestamp_, | 710 pipeline_filter_->Seek(seek_timestamp_, |
696 NewCallback(this, &PipelineImpl::OnFilterStateTransition)); | 711 NewCallback(this, &PipelineImpl::OnFilterStateTransition)); |
697 } | 712 } |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
778 } | 793 } |
779 | 794 |
780 void PipelineImpl::VolumeChangedTask(float volume) { | 795 void PipelineImpl::VolumeChangedTask(float volume) { |
781 DCHECK_EQ(MessageLoop::current(), message_loop_); | 796 DCHECK_EQ(MessageLoop::current(), message_loop_); |
782 | 797 |
783 if (audio_renderer_) { | 798 if (audio_renderer_) { |
784 audio_renderer_->SetVolume(volume); | 799 audio_renderer_->SetVolume(volume); |
785 } | 800 } |
786 } | 801 } |
787 | 802 |
| 803 void PipelineImpl::PreloadChangedTask(Preload preload) { |
| 804 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 805 if (demuxer_) |
| 806 demuxer_->SetPreload(preload); |
| 807 } |
| 808 |
788 void PipelineImpl::SeekTask(base::TimeDelta time, | 809 void PipelineImpl::SeekTask(base::TimeDelta time, |
789 PipelineStatusCallback* seek_callback) { | 810 PipelineStatusCallback* seek_callback) { |
790 DCHECK_EQ(MessageLoop::current(), message_loop_); | 811 DCHECK_EQ(MessageLoop::current(), message_loop_); |
791 DCHECK(!IsPipelineStopPending()); | 812 DCHECK(!IsPipelineStopPending()); |
792 | 813 |
793 // Suppress seeking if we're not fully started. | 814 // Suppress seeking if we're not fully started. |
794 if (state_ != kStarted && state_ != kEnded) { | 815 if (state_ != kStarted && state_ != kEnded) { |
795 // TODO(scherkus): should we run the callback? I'm tempted to say the API | 816 // TODO(scherkus): should we run the callback? I'm tempted to say the API |
796 // will only execute the first Seek() request. | 817 // will only execute the first Seek() request. |
797 VLOG(1) << "Media pipeline has not started, ignoring seek to " | 818 VLOG(1) << "Media pipeline has not started, ignoring seek to " |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
987 break; | 1008 break; |
988 // default: intentionally left out to force new states to cause compiler | 1009 // default: intentionally left out to force new states to cause compiler |
989 // errors. | 1010 // errors. |
990 }; | 1011 }; |
991 } | 1012 } |
992 | 1013 |
993 void PipelineImpl::FinishDestroyingFiltersTask() { | 1014 void PipelineImpl::FinishDestroyingFiltersTask() { |
994 DCHECK_EQ(MessageLoop::current(), message_loop_); | 1015 DCHECK_EQ(MessageLoop::current(), message_loop_); |
995 DCHECK(IsPipelineStopped()); | 1016 DCHECK(IsPipelineStopped()); |
996 | 1017 |
997 // Clear renderer references. | 1018 // Clear filter references. |
998 audio_renderer_ = NULL; | 1019 audio_renderer_ = NULL; |
999 video_renderer_ = NULL; | 1020 video_renderer_ = NULL; |
| 1021 demuxer_ = NULL; |
1000 | 1022 |
1001 pipeline_filter_ = NULL; | 1023 pipeline_filter_ = NULL; |
1002 | 1024 |
1003 if (error_caused_teardown_ && !IsPipelineOk() && error_callback_.get()) | 1025 if (error_caused_teardown_ && !IsPipelineOk() && error_callback_.get()) |
1004 error_callback_->Run(status_); | 1026 error_callback_->Run(status_); |
1005 | 1027 |
1006 if (stop_pending_) { | 1028 if (stop_pending_) { |
1007 stop_pending_ = false; | 1029 stop_pending_ = false; |
1008 ResetState(); | 1030 ResetState(); |
1009 scoped_ptr<PipelineStatusCallback> stop_callback(stop_callback_.release()); | 1031 scoped_ptr<PipelineStatusCallback> stop_callback(stop_callback_.release()); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1050 } | 1072 } |
1051 | 1073 |
1052 if (!demuxer) { | 1074 if (!demuxer) { |
1053 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 1075 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); |
1054 return; | 1076 return; |
1055 } | 1077 } |
1056 | 1078 |
1057 if (!PrepareFilter(demuxer)) | 1079 if (!PrepareFilter(demuxer)) |
1058 return; | 1080 return; |
1059 | 1081 |
1060 pipeline_init_state_->demuxer_ = demuxer; | 1082 demuxer_ = demuxer; |
1061 OnFilterInitialize(); | 1083 OnFilterInitialize(); |
1062 } | 1084 } |
1063 | 1085 |
1064 bool PipelineImpl::InitializeAudioDecoder( | 1086 bool PipelineImpl::InitializeAudioDecoder( |
1065 const scoped_refptr<Demuxer>& demuxer) { | 1087 const scoped_refptr<Demuxer>& demuxer) { |
1066 DCHECK_EQ(MessageLoop::current(), message_loop_); | 1088 DCHECK_EQ(MessageLoop::current(), message_loop_); |
1067 DCHECK(IsPipelineOk()); | 1089 DCHECK(IsPipelineOk()); |
1068 | 1090 |
1069 scoped_refptr<DemuxerStream> stream = | 1091 scoped_refptr<DemuxerStream> stream = |
1070 demuxer->GetStream(DemuxerStream::AUDIO); | 1092 demuxer->GetStream(DemuxerStream::AUDIO); |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1233 case kStopping: | 1255 case kStopping: |
1234 case kStopped: | 1256 case kStopped: |
1235 NOTREACHED() << "Unexpected state for teardown: " << state_; | 1257 NOTREACHED() << "Unexpected state for teardown: " << state_; |
1236 break; | 1258 break; |
1237 // default: intentionally left out to force new states to cause compiler | 1259 // default: intentionally left out to force new states to cause compiler |
1238 // errors. | 1260 // errors. |
1239 }; | 1261 }; |
1240 } | 1262 } |
1241 | 1263 |
1242 } // namespace media | 1264 } // namespace media |
OLD | NEW |