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

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

Issue 10823261: Remove Pipeline::IsInitialized() and replace stop_pending_ with checks for stop_cb_. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src
Patch Set: fix .h Created 8 years, 4 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
OLDNEW
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
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), 75 error_caused_teardown_(false),
77 playback_rate_change_pending_(false), 76 playback_rate_change_pending_(false),
78 did_loading_progress_(false), 77 did_loading_progress_(false),
79 total_bytes_(0), 78 total_bytes_(0),
80 natural_size_(0, 0), 79 natural_size_(0, 0),
81 volume_(1.0f), 80 volume_(1.0f),
82 playback_rate_(0.0f), 81 playback_rate_(0.0f),
83 pending_playback_rate_(0.0f), 82 pending_playback_rate_(0.0f),
84 clock_(new Clock(&base::Time::Now)), 83 clock_(new Clock(&base::Time::Now)),
85 waiting_for_clock_update_(false), 84 waiting_for_clock_update_(false),
86 status_(PIPELINE_OK), 85 status_(PIPELINE_OK),
87 has_audio_(false), 86 has_audio_(false),
88 has_video_(false), 87 has_video_(false),
89 state_(kCreated), 88 state_(kCreated),
90 seek_timestamp_(kNoTimestamp()), 89 seek_timestamp_(kNoTimestamp()),
91 audio_ended_(false), 90 audio_ended_(false),
92 video_ended_(false), 91 video_ended_(false),
93 audio_disabled_(false), 92 audio_disabled_(false),
94 creation_time_(base::Time::Now()) { 93 creation_time_(base::Time::Now()) {
95 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); 94 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated));
96 media_log_->AddEvent( 95 media_log_->AddEvent(
97 media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED)); 96 media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED));
98 } 97 }
99 98
100 Pipeline::~Pipeline() { 99 Pipeline::~Pipeline() {
101 base::AutoLock auto_lock(lock_); 100 base::AutoLock auto_lock(lock_);
102 DCHECK(!running_) << "Stop() must complete before destroying object"; 101 DCHECK(!running_) << "Stop() must complete before destroying object";
103 DCHECK(!stop_pending_); 102 DCHECK(stop_cb_.is_null());
104 DCHECK(!seek_pending_); 103 DCHECK(!seek_pending_);
105 104
106 media_log_->AddEvent( 105 media_log_->AddEvent(
107 media_log_->CreateEvent(MediaLogEvent::PIPELINE_DESTROYED)); 106 media_log_->CreateEvent(MediaLogEvent::PIPELINE_DESTROYED));
108 } 107 }
109 108
110 void Pipeline::Start(scoped_ptr<FilterCollection> collection, 109 void Pipeline::Start(scoped_ptr<FilterCollection> collection,
111 const PipelineStatusCB& ended_cb, 110 const PipelineStatusCB& ended_cb,
112 const PipelineStatusCB& error_cb, 111 const PipelineStatusCB& error_cb,
113 const PipelineStatusCB& start_cb) { 112 const PipelineStatusCB& start_cb) {
(...skipping 21 matching lines...) Expand all
135 134
136 message_loop_->PostTask(FROM_HERE, base::Bind( 135 message_loop_->PostTask(FROM_HERE, base::Bind(
137 &Pipeline::SeekTask, this, time, seek_cb)); 136 &Pipeline::SeekTask, this, time, seek_cb));
138 } 137 }
139 138
140 bool Pipeline::IsRunning() const { 139 bool Pipeline::IsRunning() const {
141 base::AutoLock auto_lock(lock_); 140 base::AutoLock auto_lock(lock_);
142 return running_; 141 return running_;
143 } 142 }
144 143
145 bool Pipeline::IsInitialized() const {
146 // TODO(scherkus): perhaps replace this with a bool that is set/get under the
147 // lock, because this is breaching the contract that |state_| is only accessed
148 // on |message_loop_|.
149 base::AutoLock auto_lock(lock_);
150 switch (state_) {
151 case kPausing:
152 case kFlushing:
153 case kSeeking:
154 case kStarting:
155 case kStarted:
156 return true;
157 default:
158 return false;
159 }
160 }
161
162 bool Pipeline::HasAudio() const { 144 bool Pipeline::HasAudio() const {
163 base::AutoLock auto_lock(lock_); 145 base::AutoLock auto_lock(lock_);
164 return has_audio_; 146 return has_audio_;
165 } 147 }
166 148
167 bool Pipeline::HasVideo() const { 149 bool Pipeline::HasVideo() const {
168 base::AutoLock auto_lock(lock_); 150 base::AutoLock auto_lock(lock_);
169 return has_video_; 151 return has_video_;
170 } 152 }
171 153
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
249 bool ret = did_loading_progress_; 231 bool ret = did_loading_progress_;
250 did_loading_progress_ = false; 232 did_loading_progress_ = false;
251 return ret; 233 return ret;
252 } 234 }
253 235
254 PipelineStatistics Pipeline::GetStatistics() const { 236 PipelineStatistics Pipeline::GetStatistics() const {
255 base::AutoLock auto_lock(lock_); 237 base::AutoLock auto_lock(lock_);
256 return statistics_; 238 return statistics_;
257 } 239 }
258 240
241 bool Pipeline::IsInitializedForTesting() {
242 DCHECK(message_loop_->BelongsToCurrentThread())
243 << "Tests should run on the same thread as Pipeline";
244 switch (state_) {
245 case kPausing:
246 case kFlushing:
247 case kSeeking:
248 case kStarting:
249 case kStarted:
250 return true;
251 default:
252 return false;
253 }
254 }
255
259 void Pipeline::SetClockForTesting(Clock* clock) { 256 void Pipeline::SetClockForTesting(Clock* clock) {
260 clock_.reset(clock); 257 clock_.reset(clock);
261 } 258 }
262 259
263 void Pipeline::SetErrorForTesting(PipelineStatus status) { 260 void Pipeline::SetErrorForTesting(PipelineStatus status) {
264 SetError(status); 261 SetError(status);
265 } 262 }
266 263
267 void Pipeline::SetState(State next_state) { 264 void Pipeline::SetState(State next_state) {
268 if (state_ != kStarted && next_state == kStarted && 265 if (state_ != kStarted && next_state == kStarted &&
(...skipping 14 matching lines...) Expand all
283 bool Pipeline::IsPipelineStopped() { 280 bool Pipeline::IsPipelineStopped() {
284 DCHECK(message_loop_->BelongsToCurrentThread()); 281 DCHECK(message_loop_->BelongsToCurrentThread());
285 return state_ == kStopped || state_ == kError; 282 return state_ == kStopped || state_ == kError;
286 } 283 }
287 284
288 bool Pipeline::IsPipelineTearingDown() { 285 bool Pipeline::IsPipelineTearingDown() {
289 DCHECK(message_loop_->BelongsToCurrentThread()); 286 DCHECK(message_loop_->BelongsToCurrentThread());
290 return tearing_down_; 287 return tearing_down_;
291 } 288 }
292 289
293 bool Pipeline::IsPipelineStopPending() {
294 DCHECK(message_loop_->BelongsToCurrentThread());
295 return stop_pending_;
296 }
297
298 bool Pipeline::IsPipelineSeeking() { 290 bool Pipeline::IsPipelineSeeking() {
299 DCHECK(message_loop_->BelongsToCurrentThread()); 291 DCHECK(message_loop_->BelongsToCurrentThread());
300 if (!seek_pending_) 292 if (!seek_pending_)
301 return false; 293 return false;
302 DCHECK(kSeeking == state_ || kPausing == state_ || 294 DCHECK(kSeeking == state_ || kPausing == state_ ||
303 kFlushing == state_ || kStarting == state_) 295 kFlushing == state_ || kStarting == state_)
304 << "Current state : " << state_; 296 << "Current state : " << state_;
305 return true; 297 return true;
306 } 298 }
307 299
(...skipping 27 matching lines...) Expand all
335 327
336 // static 328 // static
337 Pipeline::State Pipeline::FindNextState(State current) { 329 Pipeline::State Pipeline::FindNextState(State current) {
338 // TODO(scherkus): refactor InitializeTask() to make use of this function. 330 // TODO(scherkus): refactor InitializeTask() to make use of this function.
339 if (current == kPausing) { 331 if (current == kPausing) {
340 return kFlushing; 332 return kFlushing;
341 } else if (current == kFlushing) { 333 } else if (current == kFlushing) {
342 // We will always honor Seek() before Stop(). This is based on the 334 // We will always honor Seek() before Stop(). This is based on the
343 // assumption that we never accept Seek() after Stop(). 335 // assumption that we never accept Seek() after Stop().
344 DCHECK(IsPipelineSeeking() || 336 DCHECK(IsPipelineSeeking() ||
345 IsPipelineStopPending() || 337 !stop_cb_.is_null() ||
346 IsPipelineTearingDown()); 338 IsPipelineTearingDown());
347 return IsPipelineSeeking() ? kSeeking : kStopping; 339 return IsPipelineSeeking() ? kSeeking : kStopping;
348 } else if (current == kSeeking) { 340 } else if (current == kSeeking) {
349 return kStarting; 341 return kStarting;
350 } else if (current == kStarting) { 342 } else if (current == kStarting) {
351 return kStarted; 343 return kStarted;
352 } else if (current == kStopping) { 344 } else if (current == kStopping) {
353 return error_caused_teardown_ ? kError : kStopped; 345 return error_caused_teardown_ ? kError : kStopped;
354 } else { 346 } else {
355 return current; 347 return current;
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
625 if (state_ == kInitVideoDecoder && 617 if (state_ == kInitVideoDecoder &&
626 last_stage_status == DECODER_ERROR_NOT_SUPPORTED) { 618 last_stage_status == DECODER_ERROR_NOT_SUPPORTED) {
627 state_ = kInitAudioRenderer; 619 state_ = kInitAudioRenderer;
628 } else { 620 } else {
629 SetError(last_stage_status); 621 SetError(last_stage_status);
630 return; 622 return;
631 } 623 }
632 } 624 }
633 625
634 // If we have received the stop or error signal, return immediately. 626 // If we have received the stop or error signal, return immediately.
635 if (IsPipelineStopPending() || IsPipelineStopped() || !IsPipelineOk()) 627 if (!stop_cb_.is_null() || IsPipelineStopped() || !IsPipelineOk())
636 return; 628 return;
637 629
638 DCHECK(state_ == kInitDemuxer || 630 DCHECK(state_ == kInitDemuxer ||
639 state_ == kInitAudioDecoder || 631 state_ == kInitAudioDecoder ||
640 state_ == kInitAudioRenderer || 632 state_ == kInitAudioRenderer ||
641 state_ == kInitVideoDecoder || 633 state_ == kInitVideoDecoder ||
642 state_ == kInitVideoRenderer); 634 state_ == kInitVideoRenderer);
643 635
644 // Demuxer created, create audio decoder. 636 // Demuxer created, create audio decoder.
645 if (state_ == kInitDemuxer) { 637 if (state_ == kInitDemuxer) {
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 698
707 // This method is called as a result of the client calling Pipeline::Stop() or 699 // This method is called as a result of the client calling Pipeline::Stop() or
708 // as the result of an error condition. 700 // as the result of an error condition.
709 // We stop the filters in the reverse order. 701 // We stop the filters in the reverse order.
710 // 702 //
711 // TODO(scherkus): beware! this can get posted multiple times since we post 703 // TODO(scherkus): beware! this can get posted multiple times since we post
712 // Stop() tasks even if we've already stopped. Perhaps this should no-op for 704 // Stop() tasks even if we've already stopped. Perhaps this should no-op for
713 // additional calls, however most of this logic will be changing. 705 // additional calls, however most of this logic will be changing.
714 void Pipeline::StopTask(const base::Closure& stop_cb) { 706 void Pipeline::StopTask(const base::Closure& stop_cb) {
715 DCHECK(message_loop_->BelongsToCurrentThread()); 707 DCHECK(message_loop_->BelongsToCurrentThread());
716 DCHECK(!IsPipelineStopPending()); 708 DCHECK(stop_cb_.is_null());
717 DCHECK_NE(state_, kStopped); 709 DCHECK_NE(state_, kStopped);
718 710
719 if (video_decoder_) { 711 if (video_decoder_) {
720 video_decoder_->PrepareForShutdownHack(); 712 video_decoder_->PrepareForShutdownHack();
721 video_decoder_ = NULL; 713 video_decoder_ = NULL;
722 } 714 }
723 715
724 if (IsPipelineTearingDown() && error_caused_teardown_) { 716 if (IsPipelineTearingDown() && error_caused_teardown_) {
725 // If we are stopping due to SetError(), stop normally instead of 717 // If we are stopping due to SetError(), stop normally instead of
726 // going to error state and calling |error_cb_|. This converts 718 // going to error state and calling |error_cb_|. This converts
727 // the teardown in progress from an error teardown into one that acts 719 // the teardown in progress from an error teardown into one that acts
728 // like the error never occurred. 720 // like the error never occurred.
729 base::AutoLock auto_lock(lock_); 721 base::AutoLock auto_lock(lock_);
730 status_ = PIPELINE_OK; 722 status_ = PIPELINE_OK;
731 error_caused_teardown_ = false; 723 error_caused_teardown_ = false;
732 } 724 }
733 725
734 stop_cb_ = stop_cb; 726 stop_cb_ = stop_cb;
735 727
736 stop_pending_ = true;
737 if (!IsPipelineSeeking() && !IsPipelineTearingDown()) { 728 if (!IsPipelineSeeking() && !IsPipelineTearingDown()) {
738 // We will tear down pipeline immediately when there is no seek operation 729 // We will tear down pipeline immediately when there is no seek operation
739 // pending and no teardown in progress. This should include the case where 730 // pending and no teardown in progress. This should include the case where
740 // we are partially initialized. 731 // we are partially initialized.
741 TearDownPipeline(); 732 TearDownPipeline();
742 } 733 }
743 } 734 }
744 735
745 void Pipeline::ErrorChangedTask(PipelineStatus error) { 736 void Pipeline::ErrorChangedTask(PipelineStatus error) {
746 DCHECK(message_loop_->BelongsToCurrentThread()); 737 DCHECK(message_loop_->BelongsToCurrentThread());
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
799 DCHECK(message_loop_->BelongsToCurrentThread()); 790 DCHECK(message_loop_->BelongsToCurrentThread());
800 if (!running_ || tearing_down_) 791 if (!running_ || tearing_down_)
801 return; 792 return;
802 793
803 if (audio_renderer_) 794 if (audio_renderer_)
804 audio_renderer_->SetVolume(volume); 795 audio_renderer_->SetVolume(volume);
805 } 796 }
806 797
807 void Pipeline::SeekTask(TimeDelta time, const PipelineStatusCB& seek_cb) { 798 void Pipeline::SeekTask(TimeDelta time, const PipelineStatusCB& seek_cb) {
808 DCHECK(message_loop_->BelongsToCurrentThread()); 799 DCHECK(message_loop_->BelongsToCurrentThread());
809 DCHECK(!IsPipelineStopPending()); 800 DCHECK(stop_cb_.is_null());
810 801
811 // Suppress seeking if we're not fully started. 802 // Suppress seeking if we're not fully started.
812 if (state_ != kStarted) { 803 if (state_ != kStarted) {
813 // TODO(scherkus): should we run the callback? I'm tempted to say the API 804 // TODO(scherkus): should we run the callback? I'm tempted to say the API
814 // will only execute the first Seek() request. 805 // will only execute the first Seek() request.
815 DVLOG(1) << "Media pipeline has not started, ignoring seek to " 806 DVLOG(1) << "Media pipeline has not started, ignoring seek to "
816 << time.InMicroseconds() << " (current state: " << state_ << ")"; 807 << time.InMicroseconds() << " (current state: " << state_ << ")";
817 return; 808 return;
818 } 809 }
819 810
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
969 960
970 base::AutoLock auto_lock(lock_); 961 base::AutoLock auto_lock(lock_);
971 // We use audio stream to update the clock. So if there is such a stream, 962 // We use audio stream to update the clock. So if there is such a stream,
972 // we pause the clock until we receive a valid timestamp. 963 // we pause the clock until we receive a valid timestamp.
973 waiting_for_clock_update_ = true; 964 waiting_for_clock_update_ = true;
974 if (!has_audio_) { 965 if (!has_audio_) {
975 clock_->SetMaxTime(clock_->Duration()); 966 clock_->SetMaxTime(clock_->Duration());
976 StartClockIfWaitingForTimeUpdate_Locked(); 967 StartClockIfWaitingForTimeUpdate_Locked();
977 } 968 }
978 969
979 if (IsPipelineStopPending()) { 970 // Check if we have a pending stop request that needs to be honored.
980 // We had a pending stop request need to be honored right now. 971 if (!stop_cb_.is_null()) {
981 TearDownPipeline(); 972 TearDownPipeline();
982 } 973 }
983 } else { 974 } else {
984 NOTREACHED() << "Unexpected state: " << state_; 975 NOTREACHED() << "Unexpected state: " << state_;
985 } 976 }
986 } 977 }
987 978
988 void Pipeline::TeardownStateTransitionTask() { 979 void Pipeline::TeardownStateTransitionTask() {
989 DCHECK(IsPipelineTearingDown()); 980 DCHECK(IsPipelineTearingDown());
990 DCHECK(pending_callbacks_.get()) 981 DCHECK(pending_callbacks_.get())
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1027 DCHECK(message_loop_->BelongsToCurrentThread()); 1018 DCHECK(message_loop_->BelongsToCurrentThread());
1028 DCHECK(IsPipelineStopped()); 1019 DCHECK(IsPipelineStopped());
1029 1020
1030 audio_renderer_ = NULL; 1021 audio_renderer_ = NULL;
1031 video_renderer_ = NULL; 1022 video_renderer_ = NULL;
1032 demuxer_ = NULL; 1023 demuxer_ = NULL;
1033 1024
1034 if (error_caused_teardown_ && !IsPipelineOk() && !error_cb_.is_null()) 1025 if (error_caused_teardown_ && !IsPipelineOk() && !error_cb_.is_null())
1035 error_cb_.Run(status_); 1026 error_cb_.Run(status_);
1036 1027
1037 if (stop_pending_) { 1028 if (!stop_cb_.is_null()) {
1038 stop_pending_ = false;
1039 { 1029 {
1040 base::AutoLock l(lock_); 1030 base::AutoLock l(lock_);
1041 running_ = false; 1031 running_ = false;
1042 } 1032 }
1043 1033
1044 // Notify the client that stopping has finished. 1034 // Notify the client that stopping has finished.
1045 base::ResetAndReturn(&stop_cb_).Run(); 1035 base::ResetAndReturn(&stop_cb_).Run();
1046 } 1036 }
1047 1037
1048 tearing_down_ = false; 1038 tearing_down_ = false;
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
1187 base::Bind(&Pipeline::SetError, this), 1177 base::Bind(&Pipeline::SetError, this),
1188 base::Bind(&Pipeline::GetMediaTime, this), 1178 base::Bind(&Pipeline::GetMediaTime, this),
1189 base::Bind(&Pipeline::GetMediaDuration, this)); 1179 base::Bind(&Pipeline::GetMediaDuration, this));
1190 return true; 1180 return true;
1191 } 1181 }
1192 1182
1193 void Pipeline::TearDownPipeline() { 1183 void Pipeline::TearDownPipeline() {
1194 DCHECK(message_loop_->BelongsToCurrentThread()); 1184 DCHECK(message_loop_->BelongsToCurrentThread());
1195 DCHECK_NE(kStopped, state_); 1185 DCHECK_NE(kStopped, state_);
1196 1186
1197 DCHECK(!tearing_down_ || // Teardown on Stop(). 1187 // We're either...
1198 (tearing_down_ && error_caused_teardown_) || // Teardown on error. 1188 // 1) ...tearing down due to Stop() (it doesn't set tearing_down_)
1199 (tearing_down_ && stop_pending_)); // Stop during teardown by error. 1189 // 2) ...tearing down due to an error (it does set tearing_down_)
1190 // 3) ...tearing down due to an error and Stop() was called during that time
1191 DCHECK(!tearing_down_ ||
1192 (tearing_down_ && error_caused_teardown_) ||
1193 (tearing_down_ && !stop_cb_.is_null()));
1200 1194
1201 // Mark that we already start tearing down operation. 1195 // Mark that we already start tearing down operation.
1202 tearing_down_ = true; 1196 tearing_down_ = true;
1203 1197
1204 // Cancel any pending operation so we can proceed with teardown. 1198 // Cancel any pending operation so we can proceed with teardown.
1205 pending_callbacks_.reset(); 1199 pending_callbacks_.reset();
1206 1200
1207 switch (state_) { 1201 switch (state_) {
1208 case kCreated: 1202 case kCreated:
1209 case kError: 1203 case kError:
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
1299 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { 1293 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() {
1300 lock_.AssertAcquired(); 1294 lock_.AssertAcquired();
1301 if (!waiting_for_clock_update_) 1295 if (!waiting_for_clock_update_)
1302 return; 1296 return;
1303 1297
1304 waiting_for_clock_update_ = false; 1298 waiting_for_clock_update_ = false;
1305 clock_->Play(); 1299 clock_->Play();
1306 } 1300 }
1307 1301
1308 } // namespace media 1302 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698