| OLD | NEW |
| 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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 CHECK(*count >= 0); | 66 CHECK(*count >= 0); |
| 67 if (*count == 0) { | 67 if (*count == 0) { |
| 68 cond_var->Signal(); | 68 cond_var->Signal(); |
| 69 } | 69 } |
| 70 } | 70 } |
| 71 | 71 |
| 72 } // namespace | 72 } // namespace |
| 73 | 73 |
| 74 PipelineImpl::PipelineImpl(MessageLoop* message_loop) | 74 PipelineImpl::PipelineImpl(MessageLoop* message_loop) |
| 75 : message_loop_(message_loop), | 75 : message_loop_(message_loop), |
| 76 clock_(&base::Time::Now), |
| 76 state_(kCreated), | 77 state_(kCreated), |
| 77 remaining_transitions_(0) { | 78 remaining_transitions_(0) { |
| 78 ResetState(); | 79 ResetState(); |
| 79 } | 80 } |
| 80 | 81 |
| 81 PipelineImpl::~PipelineImpl() { | 82 PipelineImpl::~PipelineImpl() { |
| 82 AutoLock auto_lock(lock_); | 83 AutoLock auto_lock(lock_); |
| 83 DCHECK(!running_) << "Stop() must complete before destroying object"; | 84 DCHECK(!running_) << "Stop() must complete before destroying object"; |
| 84 } | 85 } |
| 85 | 86 |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 volume_ = volume; | 195 volume_ = volume; |
| 195 if (running_) { | 196 if (running_) { |
| 196 message_loop_->PostTask(FROM_HERE, | 197 message_loop_->PostTask(FROM_HERE, |
| 197 NewRunnableMethod(this, &PipelineImpl::VolumeChangedTask, | 198 NewRunnableMethod(this, &PipelineImpl::VolumeChangedTask, |
| 198 volume)); | 199 volume)); |
| 199 } | 200 } |
| 200 } | 201 } |
| 201 | 202 |
| 202 base::TimeDelta PipelineImpl::GetCurrentTime() const { | 203 base::TimeDelta PipelineImpl::GetCurrentTime() const { |
| 203 AutoLock auto_lock(lock_); | 204 AutoLock auto_lock(lock_); |
| 204 return time_; | 205 return clock_.Elapsed(); |
| 205 } | 206 } |
| 206 | 207 |
| 207 base::TimeDelta PipelineImpl::GetBufferedTime() const { | 208 base::TimeDelta PipelineImpl::GetBufferedTime() const { |
| 208 AutoLock auto_lock(lock_); | 209 AutoLock auto_lock(lock_); |
| 209 return buffered_time_; | 210 return buffered_time_; |
| 210 } | 211 } |
| 211 | 212 |
| 212 base::TimeDelta PipelineImpl::GetDuration() const { | 213 base::TimeDelta PipelineImpl::GetDuration() const { |
| 213 AutoLock auto_lock(lock_); | 214 AutoLock auto_lock(lock_); |
| 214 return duration_; | 215 return duration_; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 236 AutoLock auto_lock(lock_); | 237 AutoLock auto_lock(lock_); |
| 237 return error_; | 238 return error_; |
| 238 } | 239 } |
| 239 | 240 |
| 240 void PipelineImpl::SetPipelineErrorCallback(PipelineCallback* error_callback) { | 241 void PipelineImpl::SetPipelineErrorCallback(PipelineCallback* error_callback) { |
| 241 error_callback_.reset(error_callback); | 242 error_callback_.reset(error_callback); |
| 242 } | 243 } |
| 243 | 244 |
| 244 void PipelineImpl::ResetState() { | 245 void PipelineImpl::ResetState() { |
| 245 AutoLock auto_lock(lock_); | 246 AutoLock auto_lock(lock_); |
| 247 const base::TimeDelta kZero; |
| 246 running_ = false; | 248 running_ = false; |
| 247 duration_ = base::TimeDelta(); | 249 duration_ = kZero; |
| 248 buffered_time_ = base::TimeDelta(); | 250 buffered_time_ = kZero; |
| 249 buffered_bytes_ = 0; | 251 buffered_bytes_ = 0; |
| 250 total_bytes_ = 0; | 252 total_bytes_ = 0; |
| 251 video_width_ = 0; | 253 video_width_ = 0; |
| 252 video_height_ = 0; | 254 video_height_ = 0; |
| 253 volume_ = 1.0f; | 255 volume_ = 1.0f; |
| 254 playback_rate_ = 0.0f; | 256 playback_rate_ = 0.0f; |
| 255 error_ = PIPELINE_OK; | 257 error_ = PIPELINE_OK; |
| 256 time_ = base::TimeDelta(); | 258 clock_.SetTime(kZero); |
| 257 rendered_mime_types_.clear(); | 259 rendered_mime_types_.clear(); |
| 258 } | 260 } |
| 259 | 261 |
| 260 bool PipelineImpl::IsPipelineOk() { | 262 bool PipelineImpl::IsPipelineOk() { |
| 261 return PIPELINE_OK == GetError(); | 263 return PIPELINE_OK == GetError(); |
| 262 } | 264 } |
| 263 | 265 |
| 264 bool PipelineImpl::IsPipelineInitializing() { | 266 bool PipelineImpl::IsPipelineInitializing() { |
| 265 DCHECK_EQ(MessageLoop::current(), message_loop_); | 267 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 266 return state_ == kInitDataSource || | 268 return state_ == kInitDataSource || |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 300 } | 302 } |
| 301 | 303 |
| 302 base::TimeDelta PipelineImpl::GetTime() const { | 304 base::TimeDelta PipelineImpl::GetTime() const { |
| 303 DCHECK(IsRunning()); | 305 DCHECK(IsRunning()); |
| 304 return GetCurrentTime(); | 306 return GetCurrentTime(); |
| 305 } | 307 } |
| 306 | 308 |
| 307 void PipelineImpl::SetTime(base::TimeDelta time) { | 309 void PipelineImpl::SetTime(base::TimeDelta time) { |
| 308 DCHECK(IsRunning()); | 310 DCHECK(IsRunning()); |
| 309 AutoLock auto_lock(lock_); | 311 AutoLock auto_lock(lock_); |
| 310 time_ = time; | 312 clock_.SetTime(time); |
| 311 } | 313 } |
| 312 | 314 |
| 313 void PipelineImpl::SetDuration(base::TimeDelta duration) { | 315 void PipelineImpl::SetDuration(base::TimeDelta duration) { |
| 314 DCHECK(IsRunning()); | 316 DCHECK(IsRunning()); |
| 315 AutoLock auto_lock(lock_); | 317 AutoLock auto_lock(lock_); |
| 316 duration_ = duration; | 318 duration_ = duration; |
| 317 } | 319 } |
| 318 | 320 |
| 319 void PipelineImpl::SetBufferedTime(base::TimeDelta buffered_time) { | 321 void PipelineImpl::SetBufferedTime(base::TimeDelta buffered_time) { |
| 320 DCHECK(IsRunning()); | 322 DCHECK(IsRunning()); |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 540 | 542 |
| 541 // If our owner has requested to be notified of an error, execute | 543 // If our owner has requested to be notified of an error, execute |
| 542 // |error_callback_| unless we have a "good" error. | 544 // |error_callback_| unless we have a "good" error. |
| 543 if (error_callback_.get() && error != PIPELINE_STOPPING) { | 545 if (error_callback_.get() && error != PIPELINE_STOPPING) { |
| 544 error_callback_->Run(); | 546 error_callback_->Run(); |
| 545 } | 547 } |
| 546 } | 548 } |
| 547 | 549 |
| 548 void PipelineImpl::PlaybackRateChangedTask(float playback_rate) { | 550 void PipelineImpl::PlaybackRateChangedTask(float playback_rate) { |
| 549 DCHECK_EQ(MessageLoop::current(), message_loop_); | 551 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 552 clock_.SetPlaybackRate(playback_rate); |
| 550 for (FilterVector::iterator iter = filters_.begin(); | 553 for (FilterVector::iterator iter = filters_.begin(); |
| 551 iter != filters_.end(); | 554 iter != filters_.end(); |
| 552 ++iter) { | 555 ++iter) { |
| 553 (*iter)->SetPlaybackRate(playback_rate); | 556 (*iter)->SetPlaybackRate(playback_rate); |
| 554 } | 557 } |
| 555 } | 558 } |
| 556 | 559 |
| 557 void PipelineImpl::VolumeChangedTask(float volume) { | 560 void PipelineImpl::VolumeChangedTask(float volume) { |
| 558 DCHECK_EQ(MessageLoop::current(), message_loop_); | 561 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 559 | 562 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 584 // kPausing (for each filter) | 587 // kPausing (for each filter) |
| 585 // kSeeking (for each filter) | 588 // kSeeking (for each filter) |
| 586 // kStarting (for each filter) | 589 // kStarting (for each filter) |
| 587 // kStarted | 590 // kStarted |
| 588 state_ = kPausing; | 591 state_ = kPausing; |
| 589 seek_timestamp_ = time; | 592 seek_timestamp_ = time; |
| 590 seek_callback_.reset(seek_callback); | 593 seek_callback_.reset(seek_callback); |
| 591 remaining_transitions_ = filters_.size(); | 594 remaining_transitions_ = filters_.size(); |
| 592 | 595 |
| 593 // Kick off seeking! | 596 // Kick off seeking! |
| 597 clock_.Pause(); |
| 594 filters_.front()->Pause( | 598 filters_.front()->Pause( |
| 595 NewCallback(this, &PipelineImpl::OnFilterStateTransition)); | 599 NewCallback(this, &PipelineImpl::OnFilterStateTransition)); |
| 596 } | 600 } |
| 597 | 601 |
| 598 void PipelineImpl::FilterStateTransitionTask() { | 602 void PipelineImpl::FilterStateTransitionTask() { |
| 599 DCHECK_EQ(MessageLoop::current(), message_loop_); | 603 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 600 | 604 |
| 601 if (!StateTransitionsToStarted(state_)) { | 605 if (!StateTransitionsToStarted(state_)) { |
| 602 NOTREACHED() << "Invalid current state: " << state_; | 606 NOTREACHED() << "Invalid current state: " << state_; |
| 603 SetError(PIPELINE_ERROR_ABORT); | 607 SetError(PIPELINE_ERROR_ABORT); |
| 604 return; | 608 return; |
| 605 } | 609 } |
| 606 | 610 |
| 607 // Decrement the number of remaining transitions, making sure to transition | 611 // Decrement the number of remaining transitions, making sure to transition |
| 608 // to the next state if needed. | 612 // to the next state if needed. |
| 609 CHECK(remaining_transitions_ <= filters_.size()); | 613 CHECK(remaining_transitions_ <= filters_.size()); |
| 610 CHECK(remaining_transitions_ > 0u); | 614 CHECK(remaining_transitions_ > 0u); |
| 611 if (--remaining_transitions_ == 0) { | 615 if (--remaining_transitions_ == 0) { |
| 612 state_ = FindNextState(state_); | 616 state_ = FindNextState(state_); |
| 617 if (state_ == kSeeking) { |
| 618 clock_.SetTime(seek_timestamp_); |
| 619 } else if (state_ == kStarting) { |
| 620 clock_.Play(); |
| 621 } |
| 622 |
| 613 if (StateTransitionsToStarted(state_)) { | 623 if (StateTransitionsToStarted(state_)) { |
| 614 remaining_transitions_ = filters_.size(); | 624 remaining_transitions_ = filters_.size(); |
| 615 } | 625 } |
| 616 } | 626 } |
| 617 | 627 |
| 618 // Carry out the action for the current state. | 628 // Carry out the action for the current state. |
| 619 if (StateTransitionsToStarted(state_)) { | 629 if (StateTransitionsToStarted(state_)) { |
| 620 MediaFilter* filter = filters_[filters_.size() - remaining_transitions_]; | 630 MediaFilter* filter = filters_[filters_.size() - remaining_transitions_]; |
| 621 if (state_ == kPausing) { | 631 if (state_ == kPausing) { |
| 622 filter->Pause(NewCallback(this, &PipelineImpl::OnFilterStateTransition)); | 632 filter->Pause(NewCallback(this, &PipelineImpl::OnFilterStateTransition)); |
| 623 } else if (state_ == kSeeking) { | 633 } else if (state_ == kSeeking) { |
| 624 filter->Seek(seek_timestamp_, | 634 filter->Seek(seek_timestamp_, |
| 625 NewCallback(this, &PipelineImpl::OnFilterStateTransition)); | 635 NewCallback(this, &PipelineImpl::OnFilterStateTransition)); |
| 626 } else if (state_ == kStarting) { | 636 } else if (state_ == kStarting) { |
| 627 filter->Play(NewCallback(this, &PipelineImpl::OnFilterStateTransition)); | 637 filter->Play(NewCallback(this, &PipelineImpl::OnFilterStateTransition)); |
| 628 } else { | 638 } else { |
| 629 NOTREACHED(); | 639 NOTREACHED(); |
| 630 } | 640 } |
| 631 } else if (state_ == kStarted) { | 641 } else if (state_ == kStarted) { |
| 632 // We've completed the seek, update the time. | |
| 633 SetTime(seek_timestamp_); | |
| 634 | |
| 635 // Execute the seek callback, if present. Note that this might be the | 642 // Execute the seek callback, if present. Note that this might be the |
| 636 // initial callback passed into Start(). | 643 // initial callback passed into Start(). |
| 637 if (seek_callback_.get()) { | 644 if (seek_callback_.get()) { |
| 638 seek_callback_->Run(); | 645 seek_callback_->Run(); |
| 639 seek_callback_.reset(); | 646 seek_callback_.reset(); |
| 640 } | 647 } |
| 641 | 648 |
| 642 // Finally, reset our seeking timestamp back to zero. | 649 // Finally, reset our seeking timestamp back to zero. |
| 643 seek_timestamp_ = base::TimeDelta(); | 650 seek_timestamp_ = base::TimeDelta(); |
| 644 } else { | 651 } else { |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 802 | 809 |
| 803 // Reset the pipeline, which will decrement a reference to this object. | 810 // Reset the pipeline, which will decrement a reference to this object. |
| 804 // We will get destroyed as soon as the remaining tasks finish executing. | 811 // We will get destroyed as soon as the remaining tasks finish executing. |
| 805 // To be safe, we'll set our pipeline reference to NULL. | 812 // To be safe, we'll set our pipeline reference to NULL. |
| 806 filters_.clear(); | 813 filters_.clear(); |
| 807 filter_types_.clear(); | 814 filter_types_.clear(); |
| 808 STLDeleteElements(&filter_threads_); | 815 STLDeleteElements(&filter_threads_); |
| 809 } | 816 } |
| 810 | 817 |
| 811 } // namespace media | 818 } // namespace media |
| OLD | NEW |