| 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 |