| 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 17 matching lines...) Expand all Loading... |
| 232 *height_out = video_height_; | 233 *height_out = video_height_; |
| 233 } | 234 } |
| 234 | 235 |
| 235 PipelineError PipelineImpl::GetError() const { | 236 PipelineError PipelineImpl::GetError() const { |
| 236 AutoLock auto_lock(lock_); | 237 AutoLock auto_lock(lock_); |
| 237 return error_; | 238 return error_; |
| 238 } | 239 } |
| 239 | 240 |
| 240 void PipelineImpl::ResetState() { | 241 void PipelineImpl::ResetState() { |
| 241 AutoLock auto_lock(lock_); | 242 AutoLock auto_lock(lock_); |
| 243 const base::TimeDelta kZero; |
| 242 running_ = false; | 244 running_ = false; |
| 243 duration_ = base::TimeDelta(); | 245 duration_ = kZero; |
| 244 buffered_time_ = base::TimeDelta(); | 246 buffered_time_ = kZero; |
| 245 buffered_bytes_ = 0; | 247 buffered_bytes_ = 0; |
| 246 total_bytes_ = 0; | 248 total_bytes_ = 0; |
| 247 video_width_ = 0; | 249 video_width_ = 0; |
| 248 video_height_ = 0; | 250 video_height_ = 0; |
| 249 volume_ = 1.0f; | 251 volume_ = 1.0f; |
| 250 playback_rate_ = 0.0f; | 252 playback_rate_ = 0.0f; |
| 251 error_ = PIPELINE_OK; | 253 error_ = PIPELINE_OK; |
| 252 time_ = base::TimeDelta(); | 254 clock_.SetTime(kZero); |
| 253 rendered_mime_types_.clear(); | 255 rendered_mime_types_.clear(); |
| 254 } | 256 } |
| 255 | 257 |
| 256 bool PipelineImpl::IsPipelineOk() { | 258 bool PipelineImpl::IsPipelineOk() { |
| 257 return PIPELINE_OK == GetError(); | 259 return PIPELINE_OK == GetError(); |
| 258 } | 260 } |
| 259 | 261 |
| 260 bool PipelineImpl::IsPipelineInitializing() { | 262 bool PipelineImpl::IsPipelineInitializing() { |
| 261 DCHECK_EQ(MessageLoop::current(), message_loop_); | 263 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 262 return state_ == kInitDataSource || | 264 return state_ == kInitDataSource || |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 } | 298 } |
| 297 | 299 |
| 298 base::TimeDelta PipelineImpl::GetTime() const { | 300 base::TimeDelta PipelineImpl::GetTime() const { |
| 299 DCHECK(IsRunning()); | 301 DCHECK(IsRunning()); |
| 300 return GetCurrentTime(); | 302 return GetCurrentTime(); |
| 301 } | 303 } |
| 302 | 304 |
| 303 void PipelineImpl::SetTime(base::TimeDelta time) { | 305 void PipelineImpl::SetTime(base::TimeDelta time) { |
| 304 DCHECK(IsRunning()); | 306 DCHECK(IsRunning()); |
| 305 AutoLock auto_lock(lock_); | 307 AutoLock auto_lock(lock_); |
| 306 time_ = time; | 308 clock_.SetTime(time); |
| 307 } | 309 } |
| 308 | 310 |
| 309 void PipelineImpl::SetDuration(base::TimeDelta duration) { | 311 void PipelineImpl::SetDuration(base::TimeDelta duration) { |
| 310 DCHECK(IsRunning()); | 312 DCHECK(IsRunning()); |
| 311 AutoLock auto_lock(lock_); | 313 AutoLock auto_lock(lock_); |
| 312 duration_ = duration; | 314 duration_ = duration; |
| 313 } | 315 } |
| 314 | 316 |
| 315 void PipelineImpl::SetBufferedTime(base::TimeDelta buffered_time) { | 317 void PipelineImpl::SetBufferedTime(base::TimeDelta buffered_time) { |
| 316 DCHECK(IsRunning()); | 318 DCHECK(IsRunning()); |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 530 | 532 |
| 531 // We no longer need to examine our previous state, set it to stopped. | 533 // We no longer need to examine our previous state, set it to stopped. |
| 532 state_ = kError; | 534 state_ = kError; |
| 533 | 535 |
| 534 // Destroy every filter and reset the pipeline as well. | 536 // Destroy every filter and reset the pipeline as well. |
| 535 DestroyFilters(); | 537 DestroyFilters(); |
| 536 } | 538 } |
| 537 | 539 |
| 538 void PipelineImpl::PlaybackRateChangedTask(float playback_rate) { | 540 void PipelineImpl::PlaybackRateChangedTask(float playback_rate) { |
| 539 DCHECK_EQ(MessageLoop::current(), message_loop_); | 541 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 542 clock_.SetPlaybackRate(playback_rate); |
| 540 for (FilterVector::iterator iter = filters_.begin(); | 543 for (FilterVector::iterator iter = filters_.begin(); |
| 541 iter != filters_.end(); | 544 iter != filters_.end(); |
| 542 ++iter) { | 545 ++iter) { |
| 543 (*iter)->SetPlaybackRate(playback_rate); | 546 (*iter)->SetPlaybackRate(playback_rate); |
| 544 } | 547 } |
| 545 } | 548 } |
| 546 | 549 |
| 547 void PipelineImpl::VolumeChangedTask(float volume) { | 550 void PipelineImpl::VolumeChangedTask(float volume) { |
| 548 DCHECK_EQ(MessageLoop::current(), message_loop_); | 551 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 549 | 552 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 574 // kPausing (for each filter) | 577 // kPausing (for each filter) |
| 575 // kSeeking (for each filter) | 578 // kSeeking (for each filter) |
| 576 // kStarting (for each filter) | 579 // kStarting (for each filter) |
| 577 // kStarted | 580 // kStarted |
| 578 state_ = kPausing; | 581 state_ = kPausing; |
| 579 seek_timestamp_ = time; | 582 seek_timestamp_ = time; |
| 580 seek_callback_.reset(seek_callback); | 583 seek_callback_.reset(seek_callback); |
| 581 remaining_transitions_ = filters_.size(); | 584 remaining_transitions_ = filters_.size(); |
| 582 | 585 |
| 583 // Kick off seeking! | 586 // Kick off seeking! |
| 587 clock_.Pause(); |
| 584 filters_.front()->Pause( | 588 filters_.front()->Pause( |
| 585 NewCallback(this, &PipelineImpl::OnFilterStateTransition)); | 589 NewCallback(this, &PipelineImpl::OnFilterStateTransition)); |
| 586 } | 590 } |
| 587 | 591 |
| 588 void PipelineImpl::FilterStateTransitionTask() { | 592 void PipelineImpl::FilterStateTransitionTask() { |
| 589 DCHECK_EQ(MessageLoop::current(), message_loop_); | 593 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 590 | 594 |
| 591 if (!StateTransitionsToStarted(state_)) { | 595 if (!StateTransitionsToStarted(state_)) { |
| 592 NOTREACHED() << "Invalid current state: " << state_; | 596 NOTREACHED() << "Invalid current state: " << state_; |
| 593 SetError(PIPELINE_ERROR_ABORT); | 597 SetError(PIPELINE_ERROR_ABORT); |
| 594 return; | 598 return; |
| 595 } | 599 } |
| 596 | 600 |
| 597 // Decrement the number of remaining transitions, making sure to transition | 601 // Decrement the number of remaining transitions, making sure to transition |
| 598 // to the next state if needed. | 602 // to the next state if needed. |
| 599 CHECK(remaining_transitions_ <= filters_.size()); | 603 CHECK(remaining_transitions_ <= filters_.size()); |
| 600 CHECK(remaining_transitions_ > 0u); | 604 CHECK(remaining_transitions_ > 0u); |
| 601 if (--remaining_transitions_ == 0) { | 605 if (--remaining_transitions_ == 0) { |
| 602 state_ = FindNextState(state_); | 606 state_ = FindNextState(state_); |
| 607 if (state_ == kSeeking) { |
| 608 clock_.SetTime(seek_timestamp_); |
| 609 } else if (state_ == kStarting) { |
| 610 clock_.Play(); |
| 611 } |
| 612 |
| 603 if (StateTransitionsToStarted(state_)) { | 613 if (StateTransitionsToStarted(state_)) { |
| 604 remaining_transitions_ = filters_.size(); | 614 remaining_transitions_ = filters_.size(); |
| 605 } | 615 } |
| 606 } | 616 } |
| 607 | 617 |
| 608 // Carry out the action for the current state. | 618 // Carry out the action for the current state. |
| 609 if (StateTransitionsToStarted(state_)) { | 619 if (StateTransitionsToStarted(state_)) { |
| 610 MediaFilter* filter = filters_[filters_.size() - remaining_transitions_]; | 620 MediaFilter* filter = filters_[filters_.size() - remaining_transitions_]; |
| 611 if (state_ == kPausing) { | 621 if (state_ == kPausing) { |
| 612 filter->Pause(NewCallback(this, &PipelineImpl::OnFilterStateTransition)); | 622 filter->Pause(NewCallback(this, &PipelineImpl::OnFilterStateTransition)); |
| 613 } else if (state_ == kSeeking) { | 623 } else if (state_ == kSeeking) { |
| 614 filter->Seek(seek_timestamp_, | 624 filter->Seek(seek_timestamp_, |
| 615 NewCallback(this, &PipelineImpl::OnFilterStateTransition)); | 625 NewCallback(this, &PipelineImpl::OnFilterStateTransition)); |
| 616 } else if (state_ == kStarting) { | 626 } else if (state_ == kStarting) { |
| 617 filter->Play(NewCallback(this, &PipelineImpl::OnFilterStateTransition)); | 627 filter->Play(NewCallback(this, &PipelineImpl::OnFilterStateTransition)); |
| 618 } else { | 628 } else { |
| 619 NOTREACHED(); | 629 NOTREACHED(); |
| 620 } | 630 } |
| 621 } else if (state_ == kStarted) { | 631 } else if (state_ == kStarted) { |
| 622 // We've completed the seek, update the time. | |
| 623 SetTime(seek_timestamp_); | |
| 624 | |
| 625 // Execute the seek callback, if present. Note that this might be the | 632 // Execute the seek callback, if present. Note that this might be the |
| 626 // initial callback passed into Start(). | 633 // initial callback passed into Start(). |
| 627 if (seek_callback_.get()) { | 634 if (seek_callback_.get()) { |
| 628 seek_callback_->Run(); | 635 seek_callback_->Run(); |
| 629 seek_callback_.reset(); | 636 seek_callback_.reset(); |
| 630 } | 637 } |
| 631 | 638 |
| 632 // Finally, reset our seeking timestamp back to zero. | 639 // Finally, reset our seeking timestamp back to zero. |
| 633 seek_timestamp_ = base::TimeDelta(); | 640 seek_timestamp_ = base::TimeDelta(); |
| 634 } else { | 641 } else { |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 792 | 799 |
| 793 // Reset the pipeline, which will decrement a reference to this object. | 800 // Reset the pipeline, which will decrement a reference to this object. |
| 794 // We will get destroyed as soon as the remaining tasks finish executing. | 801 // We will get destroyed as soon as the remaining tasks finish executing. |
| 795 // To be safe, we'll set our pipeline reference to NULL. | 802 // To be safe, we'll set our pipeline reference to NULL. |
| 796 filters_.clear(); | 803 filters_.clear(); |
| 797 filter_types_.clear(); | 804 filter_types_.clear(); |
| 798 STLDeleteElements(&filter_threads_); | 805 STLDeleteElements(&filter_threads_); |
| 799 } | 806 } |
| 800 | 807 |
| 801 } // namespace media | 808 } // namespace media |
| OLD | NEW |