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

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

Issue 165472: Merge 23255 - Implemented endofstream callback for media::PipelineImpl.... (Closed) Base URL: svn://chrome-svn/chrome/branches/195/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/base/pipeline_impl_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Modified: svn:mergeinfo
Merged /trunk/src/media/base/pipeline_impl.cc:r23255
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 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 bool PipelineImpl::IsInitialized() const { 142 bool PipelineImpl::IsInitialized() const {
143 // TODO(scherkus): perhaps replace this with a bool that is set/get under the 143 // TODO(scherkus): perhaps replace this with a bool that is set/get under the
144 // lock, because this is breaching the contract that |state_| is only accessed 144 // lock, because this is breaching the contract that |state_| is only accessed
145 // on |message_loop_|. 145 // on |message_loop_|.
146 AutoLock auto_lock(lock_); 146 AutoLock auto_lock(lock_);
147 switch (state_) { 147 switch (state_) {
148 case kPausing: 148 case kPausing:
149 case kSeeking: 149 case kSeeking:
150 case kStarting: 150 case kStarting:
151 case kStarted: 151 case kStarted:
152 case kEnded:
152 return true; 153 return true;
153 default: 154 default:
154 return false; 155 return false;
155 } 156 }
156 } 157 }
157 158
158 bool PipelineImpl::IsRendered(const std::string& major_mime_type) const { 159 bool PipelineImpl::IsRendered(const std::string& major_mime_type) const {
159 AutoLock auto_lock(lock_); 160 AutoLock auto_lock(lock_);
160 bool is_rendered = (rendered_mime_types_.find(major_mime_type) != 161 bool is_rendered = (rendered_mime_types_.find(major_mime_type) !=
161 rendered_mime_types_.end()); 162 rendered_mime_types_.end());
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 AutoLock auto_lock(lock_); 195 AutoLock auto_lock(lock_);
195 volume_ = volume; 196 volume_ = volume;
196 if (running_) { 197 if (running_) {
197 message_loop_->PostTask(FROM_HERE, 198 message_loop_->PostTask(FROM_HERE,
198 NewRunnableMethod(this, &PipelineImpl::VolumeChangedTask, 199 NewRunnableMethod(this, &PipelineImpl::VolumeChangedTask,
199 volume)); 200 volume));
200 } 201 }
201 } 202 }
202 203
203 base::TimeDelta PipelineImpl::GetCurrentTime() const { 204 base::TimeDelta PipelineImpl::GetCurrentTime() const {
205 // TODO(scherkus): perhaps replace checking state_ == kEnded with a bool that
206 // is set/get under the lock, because this is breaching the contract that
207 // |state_| is only accessed on |message_loop_|.
204 AutoLock auto_lock(lock_); 208 AutoLock auto_lock(lock_);
205 base::TimeDelta elapsed = clock_.Elapsed(); 209 base::TimeDelta elapsed = clock_.Elapsed();
206 if (elapsed > duration_) { 210 if (state_ == kEnded || elapsed > duration_) {
207 return duration_; 211 return duration_;
208 } 212 }
209 return elapsed; 213 return elapsed;
210 } 214 }
211 215
212 base::TimeDelta PipelineImpl::GetBufferedTime() const { 216 base::TimeDelta PipelineImpl::GetBufferedTime() const {
213 AutoLock auto_lock(lock_); 217 AutoLock auto_lock(lock_);
214 218
215 // If buffered time was set, we report that value directly. 219 // If buffered time was set, we report that value directly.
216 if (buffered_time_.ToInternalValue() > 0) 220 if (buffered_time_.ToInternalValue() > 0)
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 bool PipelineImpl::IsStreaming() const { 259 bool PipelineImpl::IsStreaming() const {
256 AutoLock auto_lock(lock_); 260 AutoLock auto_lock(lock_);
257 return streaming_; 261 return streaming_;
258 } 262 }
259 263
260 PipelineError PipelineImpl::GetError() const { 264 PipelineError PipelineImpl::GetError() const {
261 AutoLock auto_lock(lock_); 265 AutoLock auto_lock(lock_);
262 return error_; 266 return error_;
263 } 267 }
264 268
269 void PipelineImpl::SetPipelineEndedCallback(PipelineCallback* ended_callback) {
270 DCHECK(!IsRunning())
271 << "Permanent callbacks should be set before the pipeline has started";
272 ended_callback_.reset(ended_callback);
273 }
274
265 void PipelineImpl::SetPipelineErrorCallback(PipelineCallback* error_callback) { 275 void PipelineImpl::SetPipelineErrorCallback(PipelineCallback* error_callback) {
276 DCHECK(!IsRunning())
277 << "Permanent callbacks should be set before the pipeline has started";
266 error_callback_.reset(error_callback); 278 error_callback_.reset(error_callback);
267 } 279 }
268 280
269 void PipelineImpl::ResetState() { 281 void PipelineImpl::ResetState() {
270 AutoLock auto_lock(lock_); 282 AutoLock auto_lock(lock_);
271 const base::TimeDelta kZero; 283 const base::TimeDelta kZero;
272 running_ = false; 284 running_ = false;
273 duration_ = kZero; 285 duration_ = kZero;
274 buffered_time_ = kZero; 286 buffered_time_ = kZero;
275 buffered_bytes_ = 0; 287 buffered_bytes_ = 0;
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 video_width_ = width; 379 video_width_ = width;
368 video_height_ = height; 380 video_height_ = height;
369 } 381 }
370 382
371 void PipelineImpl::SetStreaming(bool streaming) { 383 void PipelineImpl::SetStreaming(bool streaming) {
372 DCHECK(IsRunning()); 384 DCHECK(IsRunning());
373 AutoLock auto_lock(lock_); 385 AutoLock auto_lock(lock_);
374 streaming_ = streaming; 386 streaming_ = streaming;
375 } 387 }
376 388
389 void PipelineImpl::NotifyEnded() {
390 DCHECK(IsRunning());
391 message_loop_->PostTask(FROM_HERE,
392 NewRunnableMethod(this, &PipelineImpl::NotifyEndedTask));
393 }
394
377 void PipelineImpl::BroadcastMessage(FilterMessage message) { 395 void PipelineImpl::BroadcastMessage(FilterMessage message) {
378 DCHECK(IsRunning()); 396 DCHECK(IsRunning());
379 397
380 // Broadcast the message on the message loop. 398 // Broadcast the message on the message loop.
381 message_loop_->PostTask(FROM_HERE, 399 message_loop_->PostTask(FROM_HERE,
382 NewRunnableMethod(this, &PipelineImpl::BroadcastMessageTask, 400 NewRunnableMethod(this, &PipelineImpl::BroadcastMessageTask,
383 message)); 401 message));
384 } 402 }
385 403
386 void PipelineImpl::InsertRenderedMimeType(const std::string& major_mime_type) { 404 void PipelineImpl::InsertRenderedMimeType(const std::string& major_mime_type) {
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 if (audio_renderer) { 623 if (audio_renderer) {
606 audio_renderer->SetVolume(volume); 624 audio_renderer->SetVolume(volume);
607 } 625 }
608 } 626 }
609 627
610 void PipelineImpl::SeekTask(base::TimeDelta time, 628 void PipelineImpl::SeekTask(base::TimeDelta time,
611 PipelineCallback* seek_callback) { 629 PipelineCallback* seek_callback) {
612 DCHECK_EQ(MessageLoop::current(), message_loop_); 630 DCHECK_EQ(MessageLoop::current(), message_loop_);
613 631
614 // Suppress seeking if we're not fully started. 632 // Suppress seeking if we're not fully started.
615 if (state_ != kStarted) { 633 if (state_ != kStarted && state_ != kEnded) {
616 // TODO(scherkus): should we run the callback? I'm tempted to say the API 634 // TODO(scherkus): should we run the callback? I'm tempted to say the API
617 // will only execute the first Seek() request. 635 // will only execute the first Seek() request.
618 LOG(INFO) << "Media pipeline is not in started state, ignoring seek to " 636 LOG(INFO) << "Media pipeline has not started, ignoring seek to "
619 << time.InMicroseconds(); 637 << time.InMicroseconds();
620 delete seek_callback; 638 delete seek_callback;
621 return; 639 return;
622 } 640 }
623 641
624 // We'll need to pause every filter before seeking. The state transition 642 // We'll need to pause every filter before seeking. The state transition
625 // is as follows: 643 // is as follows:
626 // kStarted 644 // kStarted/kEnded
627 // kPausing (for each filter) 645 // kPausing (for each filter)
628 // kSeeking (for each filter) 646 // kSeeking (for each filter)
629 // kStarting (for each filter) 647 // kStarting (for each filter)
630 // kStarted 648 // kStarted
631 state_ = kPausing; 649 state_ = kPausing;
632 seek_timestamp_ = time; 650 seek_timestamp_ = time;
633 seek_callback_.reset(seek_callback); 651 seek_callback_.reset(seek_callback);
634 remaining_transitions_ = filters_.size(); 652 remaining_transitions_ = filters_.size();
635 653
636 // Kick off seeking! 654 // Kick off seeking!
637 clock_.Pause(); 655 clock_.Pause();
638 filters_.front()->Pause( 656 filters_.front()->Pause(
639 NewCallback(this, &PipelineImpl::OnFilterStateTransition)); 657 NewCallback(this, &PipelineImpl::OnFilterStateTransition));
640 } 658 }
641 659
660 void PipelineImpl::NotifyEndedTask() {
661 DCHECK_EQ(MessageLoop::current(), message_loop_);
662
663 // We can only end if we were actually playing.
664 if (state_ != kStarted) {
665 return;
666 }
667
668 // Grab the renderers, if they exist.
669 scoped_refptr<AudioRenderer> audio_renderer;
670 scoped_refptr<VideoRenderer> video_renderer;
671 GetFilter(&audio_renderer);
672 GetFilter(&video_renderer);
673 DCHECK(audio_renderer || video_renderer);
674
675 // Make sure every extant renderer has ended.
676 if ((audio_renderer && !audio_renderer->HasEnded()) ||
677 (video_renderer && !video_renderer->HasEnded())) {
678 return;
679 }
680
681 // Transition to ended, executing the callback if present.
682 state_ = kEnded;
683 if (ended_callback_.get()) {
684 ended_callback_->Run();
685 }
686 }
687
642 void PipelineImpl::BroadcastMessageTask(FilterMessage message) { 688 void PipelineImpl::BroadcastMessageTask(FilterMessage message) {
643 DCHECK_EQ(MessageLoop::current(), message_loop_); 689 DCHECK_EQ(MessageLoop::current(), message_loop_);
644 690
645 // Broadcast the message to all filters. 691 // Broadcast the message to all filters.
646 for (FilterVector::iterator iter = filters_.begin(); 692 for (FilterVector::iterator iter = filters_.begin();
647 iter != filters_.end(); 693 iter != filters_.end();
648 ++iter) { 694 ++iter) {
649 (*iter)->OnReceivedMessage(message); 695 (*iter)->OnReceivedMessage(message);
650 } 696 }
651 } 697 }
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
865 911
866 // Reset the pipeline, which will decrement a reference to this object. 912 // Reset the pipeline, which will decrement a reference to this object.
867 // We will get destroyed as soon as the remaining tasks finish executing. 913 // We will get destroyed as soon as the remaining tasks finish executing.
868 // To be safe, we'll set our pipeline reference to NULL. 914 // To be safe, we'll set our pipeline reference to NULL.
869 filters_.clear(); 915 filters_.clear();
870 filter_types_.clear(); 916 filter_types_.clear();
871 STLDeleteElements(&filter_threads_); 917 STLDeleteElements(&filter_threads_);
872 } 918 }
873 919
874 } // namespace media 920 } // namespace media
OLDNEW
« no previous file with comments | « media/base/pipeline_impl.h ('k') | media/base/pipeline_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698