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

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

Issue 173072: Suppress slider thumb jumping around during seeking... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 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
« no previous file with comments | « media/base/pipeline_impl.h ('k') | media/filters/ffmpeg_audio_decoder.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « media/base/pipeline_impl.h ('k') | media/filters/ffmpeg_audio_decoder.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698