| 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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 struct Pipeline::PipelineInitState { | 64 struct Pipeline::PipelineInitState { |
| 65 scoped_refptr<AudioDecoder> audio_decoder; | 65 scoped_refptr<AudioDecoder> audio_decoder; |
| 66 scoped_refptr<VideoDecoder> video_decoder; | 66 scoped_refptr<VideoDecoder> video_decoder; |
| 67 }; | 67 }; |
| 68 | 68 |
| 69 Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log) | 69 Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log) |
| 70 : message_loop_(message_loop->message_loop_proxy()), | 70 : message_loop_(message_loop->message_loop_proxy()), |
| 71 media_log_(media_log), | 71 media_log_(media_log), |
| 72 running_(false), | 72 running_(false), |
| 73 seek_pending_(false), | 73 seek_pending_(false), |
| 74 stop_pending_(false), | |
| 75 tearing_down_(false), | 74 tearing_down_(false), |
| 76 error_caused_teardown_(false), | |
| 77 playback_rate_change_pending_(false), | 75 playback_rate_change_pending_(false), |
| 78 did_loading_progress_(false), | 76 did_loading_progress_(false), |
| 79 total_bytes_(0), | 77 total_bytes_(0), |
| 80 natural_size_(0, 0), | 78 natural_size_(0, 0), |
| 81 volume_(1.0f), | 79 volume_(1.0f), |
| 82 playback_rate_(0.0f), | 80 playback_rate_(0.0f), |
| 83 pending_playback_rate_(0.0f), | 81 pending_playback_rate_(0.0f), |
| 84 clock_(new Clock(&base::Time::Now)), | 82 clock_(new Clock(&base::Time::Now)), |
| 85 waiting_for_clock_update_(false), | 83 waiting_for_clock_update_(false), |
| 86 status_(PIPELINE_OK), | 84 status_(PIPELINE_OK), |
| 87 has_audio_(false), | 85 has_audio_(false), |
| 88 has_video_(false), | 86 has_video_(false), |
| 89 state_(kCreated), | 87 state_(kCreated), |
| 90 seek_timestamp_(kNoTimestamp()), | 88 seek_timestamp_(kNoTimestamp()), |
| 91 audio_disabled_(false), | 89 audio_disabled_(false), |
| 92 creation_time_(base::Time::Now()) { | 90 creation_time_(base::Time::Now()) { |
| 93 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); | 91 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); |
| 94 media_log_->AddEvent( | 92 media_log_->AddEvent( |
| 95 media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED)); | 93 media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED)); |
| 96 } | 94 } |
| 97 | 95 |
| 98 Pipeline::~Pipeline() { | 96 Pipeline::~Pipeline() { |
| 99 base::AutoLock auto_lock(lock_); | 97 base::AutoLock auto_lock(lock_); |
| 100 DCHECK(!running_) << "Stop() must complete before destroying object"; | 98 DCHECK(!running_) << "Stop() must complete before destroying object"; |
| 101 DCHECK(!stop_pending_); | 99 DCHECK(stop_cb_.is_null()); |
| 102 DCHECK(!seek_pending_); | 100 DCHECK(!seek_pending_); |
| 103 | 101 |
| 104 media_log_->AddEvent( | 102 media_log_->AddEvent( |
| 105 media_log_->CreateEvent(MediaLogEvent::PIPELINE_DESTROYED)); | 103 media_log_->CreateEvent(MediaLogEvent::PIPELINE_DESTROYED)); |
| 106 } | 104 } |
| 107 | 105 |
| 108 void Pipeline::Start(scoped_ptr<FilterCollection> collection, | 106 void Pipeline::Start(scoped_ptr<FilterCollection> collection, |
| 109 const PipelineStatusCB& ended_cb, | 107 const PipelineStatusCB& ended_cb, |
| 110 const PipelineStatusCB& error_cb, | 108 const PipelineStatusCB& error_cb, |
| 111 const PipelineStatusCB& start_cb) { | 109 const PipelineStatusCB& start_cb) { |
| 112 base::AutoLock auto_lock(lock_); | 110 base::AutoLock auto_lock(lock_); |
| 113 CHECK(!running_) << "Media pipeline is already running"; | 111 CHECK(!running_) << "Media pipeline is already running"; |
| 114 | 112 |
| 115 running_ = true; | 113 running_ = true; |
| 116 message_loop_->PostTask(FROM_HERE, base::Bind( | 114 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 117 &Pipeline::StartTask, this, base::Passed(&collection), | 115 &Pipeline::StartTask, this, base::Passed(&collection), |
| 118 ended_cb, error_cb, start_cb)); | 116 ended_cb, error_cb, start_cb)); |
| 119 } | 117 } |
| 120 | 118 |
| 121 void Pipeline::Stop(const base::Closure& stop_cb) { | 119 void Pipeline::Stop(const base::Closure& stop_cb) { |
| 122 base::AutoLock auto_lock(lock_); | |
| 123 CHECK(running_) << "Media pipeline isn't running"; | |
| 124 | |
| 125 // Stop the pipeline, which will set |running_| to false on our behalf. | |
| 126 message_loop_->PostTask(FROM_HERE, base::Bind( | 120 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 127 &Pipeline::StopTask, this, stop_cb)); | 121 &Pipeline::StopTask, this, stop_cb)); |
| 128 } | 122 } |
| 129 | 123 |
| 130 void Pipeline::Seek(TimeDelta time, const PipelineStatusCB& seek_cb) { | 124 void Pipeline::Seek(TimeDelta time, const PipelineStatusCB& seek_cb) { |
| 131 base::AutoLock auto_lock(lock_); | 125 base::AutoLock auto_lock(lock_); |
| 132 CHECK(running_) << "Media pipeline isn't running"; | 126 CHECK(running_) << "Media pipeline isn't running"; |
| 133 | 127 |
| 134 message_loop_->PostTask(FROM_HERE, base::Bind( | 128 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 135 &Pipeline::SeekTask, this, time, seek_cb)); | 129 &Pipeline::SeekTask, this, time, seek_cb)); |
| 136 } | 130 } |
| 137 | 131 |
| 138 bool Pipeline::IsRunning() const { | 132 bool Pipeline::IsRunning() const { |
| 139 base::AutoLock auto_lock(lock_); | 133 base::AutoLock auto_lock(lock_); |
| 140 return running_; | 134 return running_; |
| 141 } | 135 } |
| 142 | 136 |
| 143 bool Pipeline::IsInitialized() const { | |
| 144 // TODO(scherkus): perhaps replace this with a bool that is set/get under the | |
| 145 // lock, because this is breaching the contract that |state_| is only accessed | |
| 146 // on |message_loop_|. | |
| 147 base::AutoLock auto_lock(lock_); | |
| 148 switch (state_) { | |
| 149 case kPausing: | |
| 150 case kFlushing: | |
| 151 case kSeeking: | |
| 152 case kStarting: | |
| 153 case kStarted: | |
| 154 return true; | |
| 155 default: | |
| 156 return false; | |
| 157 } | |
| 158 } | |
| 159 | |
| 160 bool Pipeline::HasAudio() const { | 137 bool Pipeline::HasAudio() const { |
| 161 base::AutoLock auto_lock(lock_); | 138 base::AutoLock auto_lock(lock_); |
| 162 return has_audio_; | 139 return has_audio_; |
| 163 } | 140 } |
| 164 | 141 |
| 165 bool Pipeline::HasVideo() const { | 142 bool Pipeline::HasVideo() const { |
| 166 base::AutoLock auto_lock(lock_); | 143 base::AutoLock auto_lock(lock_); |
| 167 return has_video_; | 144 return has_video_; |
| 168 } | 145 } |
| 169 | 146 |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 269 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(next_state)); | 246 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(next_state)); |
| 270 } | 247 } |
| 271 | 248 |
| 272 bool Pipeline::IsPipelineOk() { | 249 bool Pipeline::IsPipelineOk() { |
| 273 base::AutoLock auto_lock(lock_); | 250 base::AutoLock auto_lock(lock_); |
| 274 return status_ == PIPELINE_OK; | 251 return status_ == PIPELINE_OK; |
| 275 } | 252 } |
| 276 | 253 |
| 277 bool Pipeline::IsPipelineStopped() { | 254 bool Pipeline::IsPipelineStopped() { |
| 278 DCHECK(message_loop_->BelongsToCurrentThread()); | 255 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 279 return state_ == kStopped || state_ == kError; | 256 return state_ == kStopped; |
| 280 } | 257 } |
| 281 | 258 |
| 282 bool Pipeline::IsPipelineTearingDown() { | 259 bool Pipeline::IsPipelineTearingDown() { |
| 283 DCHECK(message_loop_->BelongsToCurrentThread()); | 260 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 284 return tearing_down_; | 261 return tearing_down_; |
| 285 } | 262 } |
| 286 | 263 |
| 287 bool Pipeline::IsPipelineStopPending() { | 264 bool Pipeline::IsPipelineStopPending() { |
| 288 DCHECK(message_loop_->BelongsToCurrentThread()); | 265 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 289 return stop_pending_; | 266 return !stop_cb_.is_null(); |
| 290 } | 267 } |
| 291 | 268 |
| 292 bool Pipeline::IsPipelineSeeking() { | 269 bool Pipeline::IsPipelineSeeking() { |
| 293 DCHECK(message_loop_->BelongsToCurrentThread()); | 270 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 294 if (!seek_pending_) | 271 if (!seek_pending_) |
| 295 return false; | 272 return false; |
| 296 DCHECK(kSeeking == state_ || kPausing == state_ || | 273 DCHECK(kSeeking == state_ || kPausing == state_ || |
| 297 kFlushing == state_ || kStarting == state_) | 274 kFlushing == state_ || kStarting == state_) |
| 298 << "Current state : " << state_; | 275 << "Current state : " << state_; |
| 299 return true; | 276 return true; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 // assumption that we never accept Seek() after Stop(). | 313 // assumption that we never accept Seek() after Stop(). |
| 337 DCHECK(IsPipelineSeeking() || | 314 DCHECK(IsPipelineSeeking() || |
| 338 IsPipelineStopPending() || | 315 IsPipelineStopPending() || |
| 339 IsPipelineTearingDown()); | 316 IsPipelineTearingDown()); |
| 340 return IsPipelineSeeking() ? kSeeking : kStopping; | 317 return IsPipelineSeeking() ? kSeeking : kStopping; |
| 341 } else if (current == kSeeking) { | 318 } else if (current == kSeeking) { |
| 342 return kStarting; | 319 return kStarting; |
| 343 } else if (current == kStarting) { | 320 } else if (current == kStarting) { |
| 344 return kStarted; | 321 return kStarted; |
| 345 } else if (current == kStopping) { | 322 } else if (current == kStopping) { |
| 346 return error_caused_teardown_ ? kError : kStopped; | 323 return kStopped; |
| 347 } else { | 324 } else { |
| 348 return current; | 325 return current; |
| 349 } | 326 } |
| 350 } | 327 } |
| 351 | 328 |
| 352 void Pipeline::OnDemuxerError(PipelineStatus error) { | 329 void Pipeline::OnDemuxerError(PipelineStatus error) { |
| 353 SetError(error); | 330 SetError(error); |
| 354 } | 331 } |
| 355 | 332 |
| 356 void Pipeline::SetError(PipelineStatus error) { | 333 void Pipeline::SetError(PipelineStatus error) { |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 682 // Fire a seek request to get the renderers to preroll. We can skip a seek | 659 // Fire a seek request to get the renderers to preroll. We can skip a seek |
| 683 // here as the demuxer should be at the start of the stream. | 660 // here as the demuxer should be at the start of the stream. |
| 684 seek_pending_ = true; | 661 seek_pending_ = true; |
| 685 SetState(kSeeking); | 662 SetState(kSeeking); |
| 686 seek_timestamp_ = demuxer_->GetStartTime(); | 663 seek_timestamp_ = demuxer_->GetStartTime(); |
| 687 DoSeek(seek_timestamp_, true, | 664 DoSeek(seek_timestamp_, true, |
| 688 base::Bind(&Pipeline::OnFilterStateTransition, this)); | 665 base::Bind(&Pipeline::OnFilterStateTransition, this)); |
| 689 } | 666 } |
| 690 } | 667 } |
| 691 | 668 |
| 692 // This method is called as a result of the client calling Pipeline::Stop() or | |
| 693 // as the result of an error condition. | |
| 694 // We stop the filters in the reverse order. | |
| 695 // | |
| 696 // TODO(scherkus): beware! this can get posted multiple times since we post | |
| 697 // Stop() tasks even if we've already stopped. Perhaps this should no-op for | |
| 698 // additional calls, however most of this logic will be changing. | |
| 699 void Pipeline::StopTask(const base::Closure& stop_cb) { | 669 void Pipeline::StopTask(const base::Closure& stop_cb) { |
| 700 DCHECK(message_loop_->BelongsToCurrentThread()); | 670 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 701 DCHECK(!IsPipelineStopPending()); | 671 DCHECK(!IsPipelineStopPending()); |
| 702 DCHECK_NE(state_, kStopped); | 672 DCHECK(!stop_cb.is_null()); |
| 673 |
| 674 if (state_ == kStopped) { |
| 675 stop_cb.Run(); |
| 676 return; |
| 677 } |
| 703 | 678 |
| 704 if (video_decoder_) { | 679 if (video_decoder_) { |
| 705 video_decoder_->PrepareForShutdownHack(); | 680 video_decoder_->PrepareForShutdownHack(); |
| 706 video_decoder_ = NULL; | 681 video_decoder_ = NULL; |
| 707 } | 682 } |
| 708 | 683 |
| 709 if (IsPipelineTearingDown() && error_caused_teardown_) { | 684 if (IsPipelineTearingDown() && status_ != PIPELINE_OK) { |
| 710 // If we are stopping due to SetError(), stop normally instead of | 685 // If we are stopping due to SetError(), stop normally instead of |
| 711 // going to error state and calling |error_cb_|. This converts | 686 // going to error state and calling |error_cb_|. This converts |
| 712 // the teardown in progress from an error teardown into one that acts | 687 // the teardown in progress from an error teardown into one that acts |
| 713 // like the error never occurred. | 688 // like the error never occurred. |
| 714 base::AutoLock auto_lock(lock_); | 689 base::AutoLock auto_lock(lock_); |
| 715 status_ = PIPELINE_OK; | 690 status_ = PIPELINE_OK; |
| 716 error_caused_teardown_ = false; | |
| 717 } | 691 } |
| 718 | 692 |
| 719 stop_cb_ = stop_cb; | 693 stop_cb_ = stop_cb; |
| 720 | 694 |
| 721 stop_pending_ = true; | |
| 722 if (!IsPipelineSeeking() && !IsPipelineTearingDown()) { | 695 if (!IsPipelineSeeking() && !IsPipelineTearingDown()) { |
| 723 // We will tear down pipeline immediately when there is no seek operation | 696 // We will tear down pipeline immediately when there is no seek operation |
| 724 // pending and no teardown in progress. This should include the case where | 697 // pending and no teardown in progress. This should include the case where |
| 725 // we are partially initialized. | 698 // we are partially initialized. |
| 726 TearDownPipeline(); | 699 TearDownPipeline(); |
| 727 } | 700 } |
| 728 } | 701 } |
| 729 | 702 |
| 730 void Pipeline::ErrorChangedTask(PipelineStatus error) { | 703 void Pipeline::ErrorChangedTask(PipelineStatus error) { |
| 731 DCHECK(message_loop_->BelongsToCurrentThread()); | 704 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 732 DCHECK_NE(PIPELINE_OK, error) << "PIPELINE_OK isn't an error!"; | 705 DCHECK_NE(PIPELINE_OK, error) << "PIPELINE_OK isn't an error!"; |
| 733 | 706 |
| 734 // Suppress executing additional error logic. Note that if we are currently | 707 // Suppress executing additional error logic. Note that if we are currently |
| 735 // performing a normal stop, then we return immediately and continue the | 708 // performing a normal stop, then we return immediately and continue the |
| 736 // normal stop. | 709 // normal stop. |
| 737 if (IsPipelineStopped() || IsPipelineTearingDown()) { | 710 if (IsPipelineStopped() || IsPipelineTearingDown()) { |
| 738 return; | 711 return; |
| 739 } | 712 } |
| 740 | 713 |
| 741 base::AutoLock auto_lock(lock_); | 714 base::AutoLock auto_lock(lock_); |
| 742 status_ = error; | 715 status_ = error; |
| 743 | 716 |
| 744 error_caused_teardown_ = true; | |
| 745 | |
| 746 // Posting TearDownPipeline() to message loop so that we can make sure | 717 // Posting TearDownPipeline() to message loop so that we can make sure |
| 747 // it runs after any pending callbacks that are already queued. | 718 // it runs after any pending callbacks that are already queued. |
| 748 // |tearing_down_| is set early here to make sure that pending callbacks | 719 // |tearing_down_| is set early here to make sure that pending callbacks |
| 749 // don't modify the state before TeadDownPipeline() can run. | 720 // don't modify the state before TeadDownPipeline() can run. |
| 750 tearing_down_ = true; | 721 tearing_down_ = true; |
| 751 message_loop_->PostTask(FROM_HERE, base::Bind( | 722 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 752 &Pipeline::TearDownPipeline, this)); | 723 &Pipeline::TearDownPipeline, this)); |
| 753 } | 724 } |
| 754 | 725 |
| 755 void Pipeline::PlaybackRateChangedTask(float playback_rate) { | 726 void Pipeline::PlaybackRateChangedTask(float playback_rate) { |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 955 } | 926 } |
| 956 | 927 |
| 957 void Pipeline::TeardownStateTransitionTask() { | 928 void Pipeline::TeardownStateTransitionTask() { |
| 958 DCHECK(IsPipelineTearingDown()); | 929 DCHECK(IsPipelineTearingDown()); |
| 959 DCHECK(pending_callbacks_.get()) | 930 DCHECK(pending_callbacks_.get()) |
| 960 << "Teardown state transitions must be completed via pending_callbacks_"; | 931 << "Teardown state transitions must be completed via pending_callbacks_"; |
| 961 pending_callbacks_.reset(); | 932 pending_callbacks_.reset(); |
| 962 | 933 |
| 963 switch (state_) { | 934 switch (state_) { |
| 964 case kStopping: | 935 case kStopping: |
| 965 SetState(error_caused_teardown_ ? kError : kStopped); | 936 SetState(kStopped); |
| 966 FinishDestroyingFiltersTask(); | 937 FinishDestroyingFiltersTask(); |
| 967 break; | 938 break; |
| 968 case kPausing: | 939 case kPausing: |
| 969 SetState(kFlushing); | 940 SetState(kFlushing); |
| 970 DoFlush(base::Bind(&Pipeline::OnTeardownStateTransition, this)); | 941 DoFlush(base::Bind(&Pipeline::OnTeardownStateTransition, this)); |
| 971 break; | 942 break; |
| 972 case kFlushing: | 943 case kFlushing: |
| 973 SetState(kStopping); | 944 SetState(kStopping); |
| 974 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); | 945 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); |
| 975 break; | 946 break; |
| 976 | 947 |
| 977 case kCreated: | 948 case kCreated: |
| 978 case kError: | |
| 979 case kInitDemuxer: | 949 case kInitDemuxer: |
| 980 case kInitAudioDecoder: | 950 case kInitAudioDecoder: |
| 981 case kInitAudioRenderer: | 951 case kInitAudioRenderer: |
| 982 case kInitVideoDecoder: | 952 case kInitVideoDecoder: |
| 983 case kInitVideoRenderer: | 953 case kInitVideoRenderer: |
| 984 case kSeeking: | 954 case kSeeking: |
| 985 case kStarting: | 955 case kStarting: |
| 986 case kStopped: | 956 case kStopped: |
| 987 case kStarted: | 957 case kStarted: |
| 988 NOTREACHED() << "Unexpected state for teardown: " << state_; | 958 NOTREACHED() << "Unexpected state for teardown: " << state_; |
| 989 break; | 959 break; |
| 990 // default: intentionally left out to force new states to cause compiler | 960 // default: intentionally left out to force new states to cause compiler |
| 991 // errors. | 961 // errors. |
| 992 }; | 962 }; |
| 993 } | 963 } |
| 994 | 964 |
| 995 void Pipeline::FinishDestroyingFiltersTask() { | 965 void Pipeline::FinishDestroyingFiltersTask() { |
| 996 DCHECK(message_loop_->BelongsToCurrentThread()); | 966 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 997 DCHECK(IsPipelineStopped()); | 967 DCHECK(IsPipelineStopped()); |
| 998 | 968 |
| 999 audio_renderer_ = NULL; | 969 audio_renderer_ = NULL; |
| 1000 video_renderer_ = NULL; | 970 video_renderer_ = NULL; |
| 1001 demuxer_ = NULL; | 971 demuxer_ = NULL; |
| 972 { |
| 973 base::AutoLock l(lock_); |
| 974 running_ = false; |
| 975 } |
| 1002 | 976 |
| 1003 if (error_caused_teardown_ && !IsPipelineOk() && !error_cb_.is_null()) | 977 // We prioritize executing stop callbacks over error callbacks if they're |
| 978 // present. |
| 979 if (!stop_cb_.is_null()) { |
| 980 base::ResetAndReturn(&stop_cb_).Run(); |
| 981 } else if (!error_cb_.is_null() && status_ != PIPELINE_OK) { |
| 1004 error_cb_.Run(status_); | 982 error_cb_.Run(status_); |
| 1005 | |
| 1006 if (stop_pending_) { | |
| 1007 stop_pending_ = false; | |
| 1008 { | |
| 1009 base::AutoLock l(lock_); | |
| 1010 running_ = false; | |
| 1011 } | |
| 1012 | |
| 1013 // Notify the client that stopping has finished. | |
| 1014 base::ResetAndReturn(&stop_cb_).Run(); | |
| 1015 } | 983 } |
| 1016 | 984 |
| 1017 tearing_down_ = false; | 985 tearing_down_ = false; |
| 1018 error_caused_teardown_ = false; | |
| 1019 } | 986 } |
| 1020 | 987 |
| 1021 void Pipeline::InitializeDemuxer() { | 988 void Pipeline::InitializeDemuxer() { |
| 1022 DCHECK(message_loop_->BelongsToCurrentThread()); | 989 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 1023 DCHECK(IsPipelineOk()); | 990 DCHECK(IsPipelineOk()); |
| 1024 | 991 |
| 1025 demuxer_ = filter_collection_->GetDemuxer(); | 992 demuxer_ = filter_collection_->GetDemuxer(); |
| 1026 if (!demuxer_) { | 993 if (!demuxer_) { |
| 1027 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 994 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); |
| 1028 return; | 995 return; |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1156 base::Bind(&Pipeline::SetError, this), | 1123 base::Bind(&Pipeline::SetError, this), |
| 1157 base::Bind(&Pipeline::GetMediaTime, this), | 1124 base::Bind(&Pipeline::GetMediaTime, this), |
| 1158 base::Bind(&Pipeline::GetMediaDuration, this)); | 1125 base::Bind(&Pipeline::GetMediaDuration, this)); |
| 1159 return true; | 1126 return true; |
| 1160 } | 1127 } |
| 1161 | 1128 |
| 1162 void Pipeline::TearDownPipeline() { | 1129 void Pipeline::TearDownPipeline() { |
| 1163 DCHECK(message_loop_->BelongsToCurrentThread()); | 1130 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 1164 DCHECK_NE(kStopped, state_); | 1131 DCHECK_NE(kStopped, state_); |
| 1165 | 1132 |
| 1166 DCHECK(!tearing_down_ || // Teardown on Stop(). | 1133 // We're either... |
| 1167 (tearing_down_ && error_caused_teardown_) || // Teardown on error. | 1134 // 1) ...tearing down due to Stop() (it doesn't set tearing_down_) |
| 1168 (tearing_down_ && stop_pending_)); // Stop during teardown by error. | 1135 // 2) ...tearing down due to an error (it does set tearing_down_) |
| 1136 // 3) ...tearing down due to an error and Stop() was called |
| 1137 DCHECK(!tearing_down_ && !stop_cb_.is_null() || |
| 1138 (tearing_down_ && status_ != PIPELINE_OK) || |
| 1139 (tearing_down_ && !stop_cb_.is_null())); |
| 1169 | 1140 |
| 1170 // Mark that we already start tearing down operation. | 1141 // Mark that we already start tearing down operation. |
| 1171 tearing_down_ = true; | 1142 tearing_down_ = true; |
| 1172 | 1143 |
| 1173 // Cancel any pending operation so we can proceed with teardown. | 1144 // Cancel any pending operation so we can proceed with teardown. |
| 1174 pending_callbacks_.reset(); | 1145 pending_callbacks_.reset(); |
| 1175 | 1146 |
| 1176 switch (state_) { | 1147 switch (state_) { |
| 1177 case kCreated: | 1148 case kCreated: |
| 1178 case kError: | |
| 1179 SetState(kStopped); | 1149 SetState(kStopped); |
| 1180 // Need to put this in the message loop to make sure that it comes | 1150 // Need to put this in the message loop to make sure that it comes |
| 1181 // after any pending callback tasks that are already queued. | 1151 // after any pending callback tasks that are already queued. |
| 1182 message_loop_->PostTask(FROM_HERE, base::Bind( | 1152 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 1183 &Pipeline::FinishDestroyingFiltersTask, this)); | 1153 &Pipeline::FinishDestroyingFiltersTask, this)); |
| 1184 break; | 1154 break; |
| 1185 | 1155 |
| 1186 case kInitDemuxer: | 1156 case kInitDemuxer: |
| 1187 case kInitAudioDecoder: | 1157 case kInitAudioDecoder: |
| 1188 case kInitAudioRenderer: | 1158 case kInitAudioRenderer: |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1268 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { | 1238 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { |
| 1269 lock_.AssertAcquired(); | 1239 lock_.AssertAcquired(); |
| 1270 if (!waiting_for_clock_update_) | 1240 if (!waiting_for_clock_update_) |
| 1271 return; | 1241 return; |
| 1272 | 1242 |
| 1273 waiting_for_clock_update_ = false; | 1243 waiting_for_clock_update_ = false; |
| 1274 clock_->Play(); | 1244 clock_->Play(); |
| 1275 } | 1245 } |
| 1276 | 1246 |
| 1277 } // namespace media | 1247 } // namespace media |
| OLD | NEW |