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

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

Issue 149500: More media::PipelineImpl cleanup, this time focusing on not taking down the render process. (Closed)
Patch Set: Cleanup Created 11 years, 5 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
OLDNEW
1 // Copyright (c) 2008-2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2008-2009 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/compiler_specific.h" 8 #include "base/compiler_specific.h"
9 #include "base/condition_variable.h" 9 #include "base/condition_variable.h"
10 #include "base/stl_util-inl.h" 10 #include "base/stl_util-inl.h"
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 71
72 PipelineImpl::~PipelineImpl() { 72 PipelineImpl::~PipelineImpl() {
73 DCHECK(!pipeline_internal_) 73 DCHECK(!pipeline_internal_)
74 << "Stop() must complete before destroying object"; 74 << "Stop() must complete before destroying object";
75 } 75 }
76 76
77 // Creates the PipelineInternal and calls it's start method. 77 // Creates the PipelineInternal and calls it's start method.
78 bool PipelineImpl::Start(FilterFactory* factory, 78 bool PipelineImpl::Start(FilterFactory* factory,
79 const std::string& url, 79 const std::string& url,
80 PipelineCallback* start_callback) { 80 PipelineCallback* start_callback) {
81 DCHECK(!pipeline_internal_); 81 DCHECK(!pipeline_internal_) << "PipelineInternal already exists";
82 DCHECK(factory); 82 scoped_ptr<PipelineCallback> callback(start_callback);
Alpha Left Google 2009/07/11 02:05:36 good catch on leak! :)
83 if (pipeline_internal_ || !factory) { 83 if (pipeline_internal_ || !factory) {
84 return false; 84 return false;
85 } 85 }
86 86
87 // Create and start the PipelineInternal. 87 // Create and start the PipelineInternal.
88 pipeline_internal_ = new PipelineInternal(this, message_loop_); 88 pipeline_internal_ = new PipelineInternal(this, message_loop_);
89 if (!pipeline_internal_) { 89 if (!pipeline_internal_) {
90 NOTREACHED() << "Could not create PipelineInternal"; 90 NOTREACHED() << "Could not create PipelineInternal";
91 return false; 91 return false;
92 } 92 }
93 pipeline_internal_->Start(factory, url, start_callback); 93 pipeline_internal_->Start(factory, url, callback.release());
94 return true; 94 return true;
95 } 95 }
96 96
97 // Stop the PipelineInternal who will NULL our reference to it and reset our 97 // Stop the PipelineInternal who will NULL our reference to it and reset our
98 // state to a newly created PipelineImpl object. 98 // state to a newly created PipelineImpl object.
99 void PipelineImpl::Stop(PipelineCallback* stop_callback) { 99 void PipelineImpl::Stop(PipelineCallback* stop_callback) {
100 scoped_ptr<PipelineCallback> callback(stop_callback);
100 if (pipeline_internal_) { 101 if (pipeline_internal_) {
101 pipeline_internal_->Stop(stop_callback); 102 pipeline_internal_->Stop(callback.release());
102 } 103 }
103 } 104 }
104 105
105 void PipelineImpl::Seek(base::TimeDelta time, 106 void PipelineImpl::Seek(base::TimeDelta time,
106 PipelineCallback* seek_callback) { 107 PipelineCallback* seek_callback) {
107 if (IsPipelineOk()) { 108 scoped_ptr<PipelineCallback> callback(seek_callback);
108 pipeline_internal_->Seek(time, seek_callback); 109 if (pipeline_internal_) {
109 } else { 110 pipeline_internal_->Seek(time, callback.release());
110 NOTREACHED();
111 } 111 }
112 } 112 }
113 113
114 bool PipelineImpl::IsRunning() const { 114 bool PipelineImpl::IsRunning() const {
115 AutoLock auto_lock(const_cast<Lock&>(lock_)); 115 AutoLock auto_lock(lock_);
116 return pipeline_internal_ != NULL; 116 return pipeline_internal_ != NULL;
117 } 117 }
118 118
119 bool PipelineImpl::IsInitialized() const { 119 bool PipelineImpl::IsInitialized() const {
120 AutoLock auto_lock(lock_); 120 AutoLock auto_lock(lock_);
121 return pipeline_internal_ && pipeline_internal_->IsInitialized(); 121 return pipeline_internal_ && pipeline_internal_->IsInitialized();
122 } 122 }
123 123
124 bool PipelineImpl::IsRendered(const std::string& major_mime_type) const { 124 bool PipelineImpl::IsRendered(const std::string& major_mime_type) const {
125 AutoLock auto_lock(lock_); 125 AutoLock auto_lock(lock_);
126 bool is_rendered = (rendered_mime_types_.find(major_mime_type) != 126 bool is_rendered = (rendered_mime_types_.find(major_mime_type) !=
127 rendered_mime_types_.end()); 127 rendered_mime_types_.end());
128 return is_rendered; 128 return is_rendered;
129 } 129 }
130 130
131 float PipelineImpl::GetPlaybackRate() const { 131 float PipelineImpl::GetPlaybackRate() const {
132 AutoLock auto_lock(lock_); 132 AutoLock auto_lock(lock_);
133 return playback_rate_; 133 return playback_rate_;
134 } 134 }
135 135
136 void PipelineImpl::SetPlaybackRate(float rate) { 136 void PipelineImpl::SetPlaybackRate(float playback_rate) {
137 if (IsPipelineOk() && rate >= 0.0f) { 137 if (playback_rate < 0.0f) {
138 pipeline_internal_->SetPlaybackRate(rate); 138 return;
139 } else { 139 }
140 // It's OK for a client to call SetPlaybackRate(0.0f) if we're stopped. 140
141 DCHECK(rate == 0.0f && playback_rate_ == 0.0f); 141 AutoLock auto_lock(lock_);
142 playback_rate_ = playback_rate;
143 if (pipeline_internal_) {
144 pipeline_internal_->PlaybackRateChanged(playback_rate);
142 } 145 }
143 } 146 }
144 147
145 float PipelineImpl::GetVolume() const { 148 float PipelineImpl::GetVolume() const {
146 AutoLock auto_lock(lock_); 149 AutoLock auto_lock(lock_);
147 return volume_; 150 return volume_;
148 } 151 }
149 152
150 void PipelineImpl::SetVolume(float volume) { 153 void PipelineImpl::SetVolume(float volume) {
151 if (IsPipelineOk() && volume >= 0.0f && volume <= 1.0f) { 154 if (volume < 0.0f || volume > 1.0f) {
152 pipeline_internal_->SetVolume(volume); 155 return;
153 } else { 156 }
154 NOTREACHED(); 157
158 AutoLock auto_lock(lock_);
159 volume_ = volume;
160 if (pipeline_internal_) {
161 pipeline_internal_->VolumeChanged(volume);
155 } 162 }
156 } 163 }
157 164
158 base::TimeDelta PipelineImpl::GetTime() const { 165 base::TimeDelta PipelineImpl::GetTime() const {
159 AutoLock auto_lock(lock_); 166 AutoLock auto_lock(lock_);
160 return time_; 167 return time_;
161 } 168 }
162 169
163 base::TimeDelta PipelineImpl::GetBufferedTime() const { 170 base::TimeDelta PipelineImpl::GetBufferedTime() const {
164 AutoLock auto_lock(lock_); 171 AutoLock auto_lock(lock_);
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 AutoLock auto_lock(lock_); 244 AutoLock auto_lock(lock_);
238 video_width_ = width; 245 video_width_ = width;
239 video_height_ = height; 246 video_height_ = height;
240 } 247 }
241 248
242 void PipelineImpl::SetTime(base::TimeDelta time) { 249 void PipelineImpl::SetTime(base::TimeDelta time) {
243 AutoLock auto_lock(lock_); 250 AutoLock auto_lock(lock_);
244 time_ = time; 251 time_ = time;
245 } 252 }
246 253
247 void PipelineImpl::InternalSetPlaybackRate(float rate) {
248 AutoLock auto_lock(lock_);
249 playback_rate_ = rate;
250 }
251
252 bool PipelineImpl::InternalSetError(PipelineError error) { 254 bool PipelineImpl::InternalSetError(PipelineError error) {
253 // Don't want callers to set an error of "OK". STOPPING is a special value 255 // Don't want callers to set an error of "OK". STOPPING is a special value
254 // that should only be used internally by the StopTask() method. 256 // that should only be used internally by the StopTask() method.
255 DCHECK(PIPELINE_OK != error && PIPELINE_STOPPING != error); 257 DCHECK(PIPELINE_OK != error && PIPELINE_STOPPING != error);
256 AutoLock auto_lock(lock_); 258 AutoLock auto_lock(lock_);
257 bool changed_error = false; 259 bool changed_error = false;
258 if (PIPELINE_OK == error_) { 260 if (PIPELINE_OK == error_) {
259 error_ = error; 261 error_ = error;
260 changed_error = true; 262 changed_error = true;
261 } 263 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 301
300 // Called on client's thread. 302 // Called on client's thread.
301 void PipelineInternal::Seek(base::TimeDelta time, 303 void PipelineInternal::Seek(base::TimeDelta time,
302 PipelineCallback* seek_callback) { 304 PipelineCallback* seek_callback) {
303 message_loop_->PostTask(FROM_HERE, 305 message_loop_->PostTask(FROM_HERE,
304 NewRunnableMethod(this, &PipelineInternal::SeekTask, time, 306 NewRunnableMethod(this, &PipelineInternal::SeekTask, time,
305 seek_callback)); 307 seek_callback));
306 } 308 }
307 309
308 // Called on client's thread. 310 // Called on client's thread.
309 void PipelineInternal::SetPlaybackRate(float rate) { 311 void PipelineInternal::PlaybackRateChanged(float playback_rate) {
310 message_loop_->PostTask(FROM_HERE, 312 message_loop_->PostTask(FROM_HERE,
311 NewRunnableMethod(this, &PipelineInternal::SetPlaybackRateTask, rate)); 313 NewRunnableMethod(this, &PipelineInternal::PlaybackRateChangedTask,
314 playback_rate));
312 } 315 }
313 316
314 // Called on client's thread. 317 // Called on client's thread.
315 void PipelineInternal::SetVolume(float volume) { 318 void PipelineInternal::VolumeChanged(float volume) {
316 message_loop_->PostTask(FROM_HERE, 319 message_loop_->PostTask(FROM_HERE,
317 NewRunnableMethod(this, &PipelineInternal::SetVolumeTask, volume)); 320 NewRunnableMethod(this, &PipelineInternal::VolumeChangedTask, volume));
318 } 321 }
319 322
320 // Called from any thread. 323 // Called from any thread.
321 void PipelineInternal::InitializationComplete(FilterHostImpl* host) { 324 void PipelineInternal::InitializationComplete(FilterHostImpl* host) {
322 if (IsPipelineOk()) { 325 if (IsPipelineOk()) {
323 // Continue the initialize task by proceeding to the next stage. 326 // Continue the initialize task by proceeding to the next stage.
324 message_loop_->PostTask(FROM_HERE, 327 message_loop_->PostTask(FROM_HERE,
325 NewRunnableMethod(this, &PipelineInternal::InitializeTask)); 328 NewRunnableMethod(this, &PipelineInternal::InitializeTask));
326 } 329 }
327 } 330 }
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
429 return; 432 return;
430 } 433 }
431 } 434 }
432 435
433 if (state_ == kInitVideoRenderer) { 436 if (state_ == kInitVideoRenderer) {
434 if (!IsPipelineOk() || pipeline_->rendered_mime_types_.empty()) { 437 if (!IsPipelineOk() || pipeline_->rendered_mime_types_.empty()) {
435 Error(PIPELINE_ERROR_COULD_NOT_RENDER); 438 Error(PIPELINE_ERROR_COULD_NOT_RENDER);
436 return; 439 return;
437 } 440 }
438 441
442 // Initialization was successful, set the volume and playback rate.
443 PlaybackRateChangedTask(pipeline_->GetPlaybackRate());
444 VolumeChangedTask(pipeline_->GetVolume());
445
439 state_ = kStarted; 446 state_ = kStarted;
440 filter_factory_ = NULL; 447 filter_factory_ = NULL;
441 if (start_callback_.get()) { 448 if (start_callback_.get()) {
442 start_callback_->Run(true); 449 start_callback_->Run(true);
443 start_callback_.reset(); 450 start_callback_.reset();
444 } 451 }
445 } 452 }
446 } 453 }
447 454
448 // This method is called as a result of the client calling Pipeline::Stop() or 455 // This method is called as a result of the client calling Pipeline::Stop() or
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 start_callback_.reset(); 506 start_callback_.reset();
500 filter_factory_ = NULL; 507 filter_factory_ = NULL;
501 508
502 // We no longer need to examine our previous state, set it to stopped. 509 // We no longer need to examine our previous state, set it to stopped.
503 state_ = kError; 510 state_ = kError;
504 511
505 // Destroy every filter and reset the pipeline as well. 512 // Destroy every filter and reset the pipeline as well.
506 DestroyFilters(); 513 DestroyFilters();
507 } 514 }
508 515
509 void PipelineInternal::SetPlaybackRateTask(float rate) { 516 void PipelineInternal::PlaybackRateChangedTask(float playback_rate) {
510 DCHECK_EQ(MessageLoop::current(), message_loop_); 517 DCHECK_EQ(MessageLoop::current(), message_loop_);
511 518
512 pipeline_->InternalSetPlaybackRate(rate);
513 for (FilterHostVector::iterator iter = filter_hosts_.begin(); 519 for (FilterHostVector::iterator iter = filter_hosts_.begin();
514 iter != filter_hosts_.end(); 520 iter != filter_hosts_.end();
515 ++iter) { 521 ++iter) {
516 (*iter)->media_filter()->SetPlaybackRate(rate); 522 (*iter)->media_filter()->SetPlaybackRate(playback_rate);
517 } 523 }
518 } 524 }
519 525
526 void PipelineInternal::VolumeChangedTask(float volume) {
527 DCHECK_EQ(MessageLoop::current(), message_loop_);
528
529 scoped_refptr<AudioRenderer> audio_renderer;
530 GetFilter(&audio_renderer);
531 if (audio_renderer) {
532 audio_renderer->SetVolume(volume);
533 }
534 }
535
520 void PipelineInternal::SeekTask(base::TimeDelta time, 536 void PipelineInternal::SeekTask(base::TimeDelta time,
521 PipelineCallback* seek_callback) { 537 PipelineCallback* seek_callback) {
522 DCHECK_EQ(MessageLoop::current(), message_loop_); 538 DCHECK_EQ(MessageLoop::current(), message_loop_);
523 seek_callback_.reset(seek_callback); 539 seek_callback_.reset(seek_callback);
524 540
541 // Supress seeking if we haven't fully started.
542 if (state_ != kStarted) {
543 return;
544 }
545
525 for (FilterHostVector::iterator iter = filter_hosts_.begin(); 546 for (FilterHostVector::iterator iter = filter_hosts_.begin();
526 iter != filter_hosts_.end(); 547 iter != filter_hosts_.end();
527 ++iter) { 548 ++iter) {
528 (*iter)->media_filter()->Seek(time); 549 (*iter)->media_filter()->Seek(time);
529 } 550 }
530 551
531 // TODO(hclam): we should set the time when the above seek operations were all 552 // TODO(hclam): we should set the time when the above seek operations were all
532 // successful and first frame/packet at the desired time is decoded. I'm 553 // successful and first frame/packet at the desired time is decoded. I'm
533 // setting the time here because once we do the callback the user can ask for 554 // setting the time here because once we do the callback the user can ask for
534 // current time immediately, which is the old time. In order to get rid this 555 // current time immediately, which is the old time. In order to get rid this
535 // little glitch, we either assume the seek was successful and time is updated 556 // little glitch, we either assume the seek was successful and time is updated
536 // immediately here or we set time and do callback when we have new 557 // immediately here or we set time and do callback when we have new
537 // frames/packets. 558 // frames/packets.
538 SetTime(time); 559 SetTime(time);
539 if (seek_callback_.get()) { 560 if (seek_callback_.get()) {
540 seek_callback_->Run(true); 561 seek_callback_->Run(true);
541 seek_callback_.reset(); 562 seek_callback_.reset();
542 } 563 }
543 } 564 }
544 565
545 void PipelineInternal::SetVolumeTask(float volume) {
546 DCHECK_EQ(MessageLoop::current(), message_loop_);
547
548 pipeline_->volume_ = volume;
549 scoped_refptr<AudioRenderer> audio_renderer;
550 GetFilter(&audio_renderer);
551 if (audio_renderer) {
552 audio_renderer->SetVolume(volume);
553 }
554 }
555
556 template <class Filter, class Source> 566 template <class Filter, class Source>
557 void PipelineInternal::CreateFilter(FilterFactory* filter_factory, 567 void PipelineInternal::CreateFilter(FilterFactory* filter_factory,
558 Source source, 568 Source source,
559 const MediaFormat& media_format) { 569 const MediaFormat& media_format) {
560 DCHECK_EQ(MessageLoop::current(), message_loop_); 570 DCHECK_EQ(MessageLoop::current(), message_loop_);
561 DCHECK(IsPipelineOk()); 571 DCHECK(IsPipelineOk());
562 572
563 // Create the filter. 573 // Create the filter.
564 scoped_refptr<Filter> filter = filter_factory->Create<Filter>(media_format); 574 scoped_refptr<Filter> filter = filter_factory->Create<Filter>(media_format);
565 if (!filter) { 575 if (!filter) {
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
707 } 717 }
708 718
709 // Reset the pipeline, which will decrement a reference to this object. 719 // Reset the pipeline, which will decrement a reference to this object.
710 // We will get destroyed as soon as the remaining tasks finish executing. 720 // We will get destroyed as soon as the remaining tasks finish executing.
711 // To be safe, we'll set our pipeline reference to NULL. 721 // To be safe, we'll set our pipeline reference to NULL.
712 STLDeleteElements(&filter_hosts_); 722 STLDeleteElements(&filter_hosts_);
713 STLDeleteElements(&filter_threads_); 723 STLDeleteElements(&filter_threads_);
714 } 724 }
715 725
716 } // namespace media 726 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698