| 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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 clock_(&base::Time::Now), |
| 77 waiting_for_clock_update_(false), |
| 77 state_(kCreated), | 78 state_(kCreated), |
| 78 remaining_transitions_(0) { | 79 remaining_transitions_(0) { |
| 79 ResetState(); | 80 ResetState(); |
| 80 } | 81 } |
| 81 | 82 |
| 82 PipelineImpl::~PipelineImpl() { | 83 PipelineImpl::~PipelineImpl() { |
| 83 AutoLock auto_lock(lock_); | 84 AutoLock auto_lock(lock_); |
| 84 DCHECK(!running_) << "Stop() must complete before destroying object"; | 85 DCHECK(!running_) << "Stop() must complete before destroying object"; |
| 85 } | 86 } |
| 86 | 87 |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 duration_ = kZero; | 286 duration_ = kZero; |
| 286 buffered_time_ = kZero; | 287 buffered_time_ = kZero; |
| 287 buffered_bytes_ = 0; | 288 buffered_bytes_ = 0; |
| 288 streaming_ = false; | 289 streaming_ = false; |
| 289 total_bytes_ = 0; | 290 total_bytes_ = 0; |
| 290 video_width_ = 0; | 291 video_width_ = 0; |
| 291 video_height_ = 0; | 292 video_height_ = 0; |
| 292 volume_ = 1.0f; | 293 volume_ = 1.0f; |
| 293 playback_rate_ = 0.0f; | 294 playback_rate_ = 0.0f; |
| 294 error_ = PIPELINE_OK; | 295 error_ = PIPELINE_OK; |
| 296 waiting_for_clock_update_ = false; |
| 295 clock_.SetTime(kZero); | 297 clock_.SetTime(kZero); |
| 296 rendered_mime_types_.clear(); | 298 rendered_mime_types_.clear(); |
| 297 } | 299 } |
| 298 | 300 |
| 299 bool PipelineImpl::IsPipelineOk() { | 301 bool PipelineImpl::IsPipelineOk() { |
| 300 return PIPELINE_OK == GetError(); | 302 return PIPELINE_OK == GetError(); |
| 301 } | 303 } |
| 302 | 304 |
| 303 bool PipelineImpl::IsPipelineInitializing() { | 305 bool PipelineImpl::IsPipelineInitializing() { |
| 304 DCHECK_EQ(MessageLoop::current(), message_loop_); | 306 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 } | 341 } |
| 340 | 342 |
| 341 base::TimeDelta PipelineImpl::GetTime() const { | 343 base::TimeDelta PipelineImpl::GetTime() const { |
| 342 DCHECK(IsRunning()); | 344 DCHECK(IsRunning()); |
| 343 return GetCurrentTime(); | 345 return GetCurrentTime(); |
| 344 } | 346 } |
| 345 | 347 |
| 346 void PipelineImpl::SetTime(base::TimeDelta time) { | 348 void PipelineImpl::SetTime(base::TimeDelta time) { |
| 347 DCHECK(IsRunning()); | 349 DCHECK(IsRunning()); |
| 348 AutoLock auto_lock(lock_); | 350 AutoLock auto_lock(lock_); |
| 351 |
| 352 // If we were waiting for a valid timestamp and such timestamp arrives, we |
| 353 // need to clear the flag for waiting and start the clock. |
| 354 if (waiting_for_clock_update_) { |
| 355 if (time < clock_.Elapsed()) |
| 356 return; |
| 357 waiting_for_clock_update_ = false; |
| 358 clock_.SetTime(time); |
| 359 clock_.Play(); |
| 360 return; |
| 361 } |
| 349 clock_.SetTime(time); | 362 clock_.SetTime(time); |
| 350 } | 363 } |
| 351 | 364 |
| 352 void PipelineImpl::SetDuration(base::TimeDelta duration) { | 365 void PipelineImpl::SetDuration(base::TimeDelta duration) { |
| 353 DCHECK(IsRunning()); | 366 DCHECK(IsRunning()); |
| 354 AutoLock auto_lock(lock_); | 367 AutoLock auto_lock(lock_); |
| 355 duration_ = duration; | 368 duration_ = duration; |
| 356 } | 369 } |
| 357 | 370 |
| 358 void PipelineImpl::SetBufferedTime(base::TimeDelta buffered_time) { | 371 void PipelineImpl::SetBufferedTime(base::TimeDelta buffered_time) { |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 600 | 613 |
| 601 // If our owner has requested to be notified of an error, execute | 614 // If our owner has requested to be notified of an error, execute |
| 602 // |error_callback_| unless we have a "good" error. | 615 // |error_callback_| unless we have a "good" error. |
| 603 if (error_callback_.get() && error != PIPELINE_STOPPING) { | 616 if (error_callback_.get() && error != PIPELINE_STOPPING) { |
| 604 error_callback_->Run(); | 617 error_callback_->Run(); |
| 605 } | 618 } |
| 606 } | 619 } |
| 607 | 620 |
| 608 void PipelineImpl::PlaybackRateChangedTask(float playback_rate) { | 621 void PipelineImpl::PlaybackRateChangedTask(float playback_rate) { |
| 609 DCHECK_EQ(MessageLoop::current(), message_loop_); | 622 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 610 clock_.SetPlaybackRate(playback_rate); | 623 { |
| 624 AutoLock auto_lock(lock_); |
| 625 clock_.SetPlaybackRate(playback_rate); |
| 626 } |
| 611 for (FilterVector::iterator iter = filters_.begin(); | 627 for (FilterVector::iterator iter = filters_.begin(); |
| 612 iter != filters_.end(); | 628 iter != filters_.end(); |
| 613 ++iter) { | 629 ++iter) { |
| 614 (*iter)->SetPlaybackRate(playback_rate); | 630 (*iter)->SetPlaybackRate(playback_rate); |
| 615 } | 631 } |
| 616 } | 632 } |
| 617 | 633 |
| 618 void PipelineImpl::VolumeChangedTask(float volume) { | 634 void PipelineImpl::VolumeChangedTask(float volume) { |
| 619 DCHECK_EQ(MessageLoop::current(), message_loop_); | 635 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 620 | 636 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 645 // kPausing (for each filter) | 661 // kPausing (for each filter) |
| 646 // kSeeking (for each filter) | 662 // kSeeking (for each filter) |
| 647 // kStarting (for each filter) | 663 // kStarting (for each filter) |
| 648 // kStarted | 664 // kStarted |
| 649 state_ = kPausing; | 665 state_ = kPausing; |
| 650 seek_timestamp_ = time; | 666 seek_timestamp_ = time; |
| 651 seek_callback_.reset(seek_callback); | 667 seek_callback_.reset(seek_callback); |
| 652 remaining_transitions_ = filters_.size(); | 668 remaining_transitions_ = filters_.size(); |
| 653 | 669 |
| 654 // Kick off seeking! | 670 // Kick off seeking! |
| 655 clock_.Pause(); | 671 { |
| 672 AutoLock auto_lock(lock_); |
| 673 // If we are waiting for a clock update, the clock hasn't been played yet. |
| 674 if (!waiting_for_clock_update_) |
| 675 clock_.Pause(); |
| 676 } |
| 656 filters_.front()->Pause( | 677 filters_.front()->Pause( |
| 657 NewCallback(this, &PipelineImpl::OnFilterStateTransition)); | 678 NewCallback(this, &PipelineImpl::OnFilterStateTransition)); |
| 658 } | 679 } |
| 659 | 680 |
| 660 void PipelineImpl::NotifyEndedTask() { | 681 void PipelineImpl::NotifyEndedTask() { |
| 661 DCHECK_EQ(MessageLoop::current(), message_loop_); | 682 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 662 | 683 |
| 663 // We can only end if we were actually playing. | 684 // We can only end if we were actually playing. |
| 664 if (state_ != kStarted) { | 685 if (state_ != kStarted) { |
| 665 return; | 686 return; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 681 // Transition to ended, executing the callback if present. | 702 // Transition to ended, executing the callback if present. |
| 682 state_ = kEnded; | 703 state_ = kEnded; |
| 683 if (ended_callback_.get()) { | 704 if (ended_callback_.get()) { |
| 684 ended_callback_->Run(); | 705 ended_callback_->Run(); |
| 685 } | 706 } |
| 686 } | 707 } |
| 687 | 708 |
| 688 void PipelineImpl::BroadcastMessageTask(FilterMessage message) { | 709 void PipelineImpl::BroadcastMessageTask(FilterMessage message) { |
| 689 DCHECK_EQ(MessageLoop::current(), message_loop_); | 710 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 690 | 711 |
| 691 // TODO(kylep): This is a horribly ugly hack, but we have no better way to log | 712 // TODO(kylep): This is a horribly ugly hack, but we have no better way to |
| 692 // that audio is not and will not be working. | 713 // log that audio is not and will not be working. |
| 693 if (message == media::kMsgDisableAudio) | 714 if (message == media::kMsgDisableAudio) { |
| 715 // |rendered_mime_types_| is read through public methods so we need to lock |
| 716 // this variable. |
| 717 AutoLock auto_lock(lock_); |
| 694 rendered_mime_types_.erase(mime_type::kMajorTypeAudio); | 718 rendered_mime_types_.erase(mime_type::kMajorTypeAudio); |
| 719 } |
| 695 | 720 |
| 696 // Broadcast the message to all filters. | 721 // Broadcast the message to all filters. |
| 697 for (FilterVector::iterator iter = filters_.begin(); | 722 for (FilterVector::iterator iter = filters_.begin(); |
| 698 iter != filters_.end(); | 723 iter != filters_.end(); |
| 699 ++iter) { | 724 ++iter) { |
| 700 (*iter)->OnReceivedMessage(message); | 725 (*iter)->OnReceivedMessage(message); |
| 701 } | 726 } |
| 702 } | 727 } |
| 703 | 728 |
| 704 void PipelineImpl::FilterStateTransitionTask() { | 729 void PipelineImpl::FilterStateTransitionTask() { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 715 return; | 740 return; |
| 716 } | 741 } |
| 717 | 742 |
| 718 // Decrement the number of remaining transitions, making sure to transition | 743 // Decrement the number of remaining transitions, making sure to transition |
| 719 // to the next state if needed. | 744 // to the next state if needed. |
| 720 CHECK(remaining_transitions_ <= filters_.size()); | 745 CHECK(remaining_transitions_ <= filters_.size()); |
| 721 CHECK(remaining_transitions_ > 0u); | 746 CHECK(remaining_transitions_ > 0u); |
| 722 if (--remaining_transitions_ == 0) { | 747 if (--remaining_transitions_ == 0) { |
| 723 state_ = FindNextState(state_); | 748 state_ = FindNextState(state_); |
| 724 if (state_ == kSeeking) { | 749 if (state_ == kSeeking) { |
| 750 AutoLock auto_lock(lock_); |
| 725 clock_.SetTime(seek_timestamp_); | 751 clock_.SetTime(seek_timestamp_); |
| 726 } else if (state_ == kStarting) { | |
| 727 clock_.Play(); | |
| 728 } | 752 } |
| 729 | 753 |
| 730 if (StateTransitionsToStarted(state_)) { | 754 if (StateTransitionsToStarted(state_)) { |
| 731 remaining_transitions_ = filters_.size(); | 755 remaining_transitions_ = filters_.size(); |
| 732 } | 756 } |
| 733 } | 757 } |
| 734 | 758 |
| 735 // Carry out the action for the current state. | 759 // Carry out the action for the current state. |
| 736 if (StateTransitionsToStarted(state_)) { | 760 if (StateTransitionsToStarted(state_)) { |
| 737 MediaFilter* filter = filters_[filters_.size() - remaining_transitions_]; | 761 MediaFilter* filter = filters_[filters_.size() - remaining_transitions_]; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 748 } else if (state_ == kStarted) { | 772 } else if (state_ == kStarted) { |
| 749 // Execute the seek callback, if present. Note that this might be the | 773 // Execute the seek callback, if present. Note that this might be the |
| 750 // initial callback passed into Start(). | 774 // initial callback passed into Start(). |
| 751 if (seek_callback_.get()) { | 775 if (seek_callback_.get()) { |
| 752 seek_callback_->Run(); | 776 seek_callback_->Run(); |
| 753 seek_callback_.reset(); | 777 seek_callback_.reset(); |
| 754 } | 778 } |
| 755 | 779 |
| 756 // Finally, reset our seeking timestamp back to zero. | 780 // Finally, reset our seeking timestamp back to zero. |
| 757 seek_timestamp_ = base::TimeDelta(); | 781 seek_timestamp_ = base::TimeDelta(); |
| 782 |
| 783 AutoLock auto_lock(lock_); |
| 784 // We use audio stream to update the clock. So if there is such a stream, |
| 785 // we pause the clock until we receive a valid timestamp. |
| 786 waiting_for_clock_update_ = |
| 787 rendered_mime_types_.find(mime_type::kMajorTypeAudio) != |
| 788 rendered_mime_types_.end(); |
| 789 if (!waiting_for_clock_update_) |
| 790 clock_.Play(); |
| 758 } else { | 791 } else { |
| 759 NOTREACHED(); | 792 NOTREACHED(); |
| 760 } | 793 } |
| 761 } | 794 } |
| 762 | 795 |
| 763 template <class Filter, class Source> | 796 template <class Filter, class Source> |
| 764 void PipelineImpl::CreateFilter(FilterFactory* filter_factory, | 797 void PipelineImpl::CreateFilter(FilterFactory* filter_factory, |
| 765 Source source, | 798 Source source, |
| 766 const MediaFormat& media_format) { | 799 const MediaFormat& media_format) { |
| 767 DCHECK_EQ(MessageLoop::current(), message_loop_); | 800 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 916 | 949 |
| 917 // Reset the pipeline, which will decrement a reference to this object. | 950 // Reset the pipeline, which will decrement a reference to this object. |
| 918 // We will get destroyed as soon as the remaining tasks finish executing. | 951 // We will get destroyed as soon as the remaining tasks finish executing. |
| 919 // To be safe, we'll set our pipeline reference to NULL. | 952 // To be safe, we'll set our pipeline reference to NULL. |
| 920 filters_.clear(); | 953 filters_.clear(); |
| 921 filter_types_.clear(); | 954 filter_types_.clear(); |
| 922 STLDeleteElements(&filter_threads_); | 955 STLDeleteElements(&filter_threads_); |
| 923 } | 956 } |
| 924 | 957 |
| 925 } // namespace media | 958 } // namespace media |
| OLD | NEW |