 Chromium Code Reviews
 Chromium Code Reviews Issue 6686061:
  PipelineError is dead.  Long live PipelineStatus!  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src
    
  
    Issue 6686061:
  PipelineError is dead.  Long live PipelineStatus!  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src| OLD | NEW | 
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/callback.h" | 8 #include "base/callback.h" | 
| 9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" | 
| 10 #include "base/stl_util-inl.h" | 10 #include "base/stl_util-inl.h" | 
| 11 #include "base/synchronization/condition_variable.h" | 11 #include "base/synchronization/condition_variable.h" | 
| 12 #include "media/base/clock.h" | 12 #include "media/base/clock.h" | 
| 13 #include "media/base/filter_collection.h" | 13 #include "media/base/filter_collection.h" | 
| 14 #include "media/base/media_format.h" | 14 #include "media/base/media_format.h" | 
| 15 #include "media/base/pipeline_impl.h" | 15 #include "media/base/pipeline_impl.h" | 
| 16 | 16 | 
| 17 namespace media { | 17 namespace media { | 
| 18 | 18 | 
| 19 PipelineStatusNotification::PipelineStatusNotification() | |
| 20 : cv_(&lock_), status_(PIPELINE_OK), notified_(false) { | |
| 21 callback_.reset(::NewCallback(this, &PipelineStatusNotification::Notify)); | |
| 
acolwell GONE FROM CHROMIUM
2011/03/15 03:56:28
Is :: necessary here?
 
Ami GONE FROM CHROMIUM
2011/03/15 17:37:18
Not anymore (it used to be, back when I had PSN::C
 | |
| 22 } | |
| 23 | |
| 24 PipelineStatusNotification::~PipelineStatusNotification() { | |
| 25 DCHECK(notified_); | |
| 26 } | |
| 27 | |
| 28 media::PipelineStatusCallback* PipelineStatusNotification::Callback() { | |
| 29 return callback_.release(); | |
| 30 } | |
| 31 | |
| 32 void PipelineStatusNotification::Notify(media::PipelineStatus status) { | |
| 33 base::AutoLock auto_lock(lock_); | |
| 34 DCHECK(!notified_); | |
| 35 notified_ = true; | |
| 36 status_ = status; | |
| 37 cv_.Signal(); | |
| 38 } | |
| 39 | |
| 40 void PipelineStatusNotification::Wait() { | |
| 41 base::AutoLock auto_lock(lock_); | |
| 42 while (!notified_) | |
| 43 cv_.Wait(); | |
| 44 } | |
| 45 | |
| 46 media::PipelineStatus PipelineStatusNotification::status() { | |
| 47 base::AutoLock auto_lock(lock_); | |
| 48 DCHECK(notified_); | |
| 49 return status_; | |
| 50 } | |
| 51 | |
| 19 class PipelineImpl::PipelineInitState { | 52 class PipelineImpl::PipelineInitState { | 
| 20 public: | 53 public: | 
| 21 scoped_refptr<Demuxer> demuxer_; | 54 scoped_refptr<Demuxer> demuxer_; | 
| 22 scoped_refptr<AudioDecoder> audio_decoder_; | 55 scoped_refptr<AudioDecoder> audio_decoder_; | 
| 23 scoped_refptr<VideoDecoder> video_decoder_; | 56 scoped_refptr<VideoDecoder> video_decoder_; | 
| 24 scoped_refptr<CompositeFilter> composite_; | 57 scoped_refptr<CompositeFilter> composite_; | 
| 25 }; | 58 }; | 
| 26 | 59 | 
| 27 PipelineImpl::PipelineImpl(MessageLoop* message_loop) | 60 PipelineImpl::PipelineImpl(MessageLoop* message_loop) | 
| 28 : message_loop_(message_loop), | 61 : message_loop_(message_loop), | 
| 29 clock_(new Clock(&base::Time::Now)), | 62 clock_(new Clock(&base::Time::Now)), | 
| 30 waiting_for_clock_update_(false), | 63 waiting_for_clock_update_(false), | 
| 31 state_(kCreated), | 64 state_(kCreated), | 
| 32 current_bytes_(0) { | 65 current_bytes_(0) { | 
| 33 ResetState(); | 66 ResetState(); | 
| 34 } | 67 } | 
| 35 | 68 | 
| 36 PipelineImpl::~PipelineImpl() { | 69 PipelineImpl::~PipelineImpl() { | 
| 37 base::AutoLock auto_lock(lock_); | 70 base::AutoLock auto_lock(lock_); | 
| 38 DCHECK(!running_) << "Stop() must complete before destroying object"; | 71 DCHECK(!running_) << "Stop() must complete before destroying object"; | 
| 39 DCHECK(!stop_pending_); | 72 DCHECK(!stop_pending_); | 
| 40 DCHECK(!seek_pending_); | 73 DCHECK(!seek_pending_); | 
| 41 } | 74 } | 
| 42 | 75 | 
| 43 void PipelineImpl::Init(PipelineCallback* ended_callback, | 76 void PipelineImpl::Init(PipelineStatusCallback* ended_callback, | 
| 44 PipelineCallback* error_callback, | 77 PipelineStatusCallback* error_callback, | 
| 45 PipelineCallback* network_callback) { | 78 PipelineStatusCallback* network_callback) { | 
| 46 DCHECK(!IsRunning()) | 79 DCHECK(!IsRunning()) | 
| 47 << "Init() should be called before the pipeline has started"; | 80 << "Init() should be called before the pipeline has started"; | 
| 48 ended_callback_.reset(ended_callback); | 81 ended_callback_.reset(ended_callback); | 
| 49 error_callback_.reset(error_callback); | 82 error_callback_.reset(error_callback); | 
| 50 network_callback_.reset(network_callback); | 83 network_callback_.reset(network_callback); | 
| 51 } | 84 } | 
| 52 | 85 | 
| 53 // Creates the PipelineInternal and calls it's start method. | 86 // Creates the PipelineInternal and calls it's start method. | 
| 54 bool PipelineImpl::Start(FilterCollection* collection, | 87 bool PipelineImpl::Start(FilterCollection* collection, | 
| 55 const std::string& url, | 88 const std::string& url, | 
| 56 PipelineCallback* start_callback) { | 89 PipelineStatusCallback* start_callback) { | 
| 57 base::AutoLock auto_lock(lock_); | 90 base::AutoLock auto_lock(lock_); | 
| 58 scoped_ptr<PipelineCallback> callback(start_callback); | 91 scoped_ptr<PipelineStatusCallback> callback(start_callback); | 
| 59 scoped_ptr<FilterCollection> filter_collection(collection); | 92 scoped_ptr<FilterCollection> filter_collection(collection); | 
| 60 | 93 | 
| 61 if (running_) { | 94 if (running_) { | 
| 62 VLOG(1) << "Media pipeline is already running"; | 95 VLOG(1) << "Media pipeline is already running"; | 
| 63 return false; | 96 return false; | 
| 64 } | 97 } | 
| 65 | 98 | 
| 66 if (collection->IsEmpty()) { | 99 if (collection->IsEmpty()) { | 
| 67 return false; | 100 return false; | 
| 68 } | 101 } | 
| 69 | 102 | 
| 70 // Kick off initialization! | 103 // Kick off initialization! | 
| 71 running_ = true; | 104 running_ = true; | 
| 72 message_loop_->PostTask( | 105 message_loop_->PostTask( | 
| 73 FROM_HERE, | 106 FROM_HERE, | 
| 74 NewRunnableMethod(this, | 107 NewRunnableMethod(this, | 
| 75 &PipelineImpl::StartTask, | 108 &PipelineImpl::StartTask, | 
| 76 filter_collection.release(), | 109 filter_collection.release(), | 
| 77 url, | 110 url, | 
| 78 callback.release())); | 111 callback.release())); | 
| 79 return true; | 112 return true; | 
| 80 } | 113 } | 
| 81 | 114 | 
| 82 void PipelineImpl::Stop(PipelineCallback* stop_callback) { | 115 void PipelineImpl::Stop(PipelineStatusCallback* stop_callback) { | 
| 83 base::AutoLock auto_lock(lock_); | 116 base::AutoLock auto_lock(lock_); | 
| 84 scoped_ptr<PipelineCallback> callback(stop_callback); | 117 scoped_ptr<PipelineStatusCallback> callback(stop_callback); | 
| 85 if (!running_) { | 118 if (!running_) { | 
| 86 VLOG(1) << "Media pipeline has already stopped"; | 119 VLOG(1) << "Media pipeline has already stopped"; | 
| 87 return; | 120 return; | 
| 88 } | 121 } | 
| 89 | 122 | 
| 90 // Stop the pipeline, which will set |running_| to false on behalf. | 123 // Stop the pipeline, which will set |running_| to false on behalf. | 
| 91 message_loop_->PostTask(FROM_HERE, | 124 message_loop_->PostTask(FROM_HERE, | 
| 92 NewRunnableMethod(this, &PipelineImpl::StopTask, callback.release())); | 125 NewRunnableMethod(this, &PipelineImpl::StopTask, callback.release())); | 
| 93 } | 126 } | 
| 94 | 127 | 
| 95 void PipelineImpl::Seek(base::TimeDelta time, | 128 void PipelineImpl::Seek(base::TimeDelta time, | 
| 96 PipelineCallback* seek_callback) { | 129 PipelineStatusCallback* seek_callback) { | 
| 97 base::AutoLock auto_lock(lock_); | 130 base::AutoLock auto_lock(lock_); | 
| 98 scoped_ptr<PipelineCallback> callback(seek_callback); | 131 scoped_ptr<PipelineStatusCallback> callback(seek_callback); | 
| 99 if (!running_) { | 132 if (!running_) { | 
| 100 VLOG(1) << "Media pipeline must be running"; | 133 VLOG(1) << "Media pipeline must be running"; | 
| 101 return; | 134 return; | 
| 102 } | 135 } | 
| 103 | 136 | 
| 104 message_loop_->PostTask(FROM_HERE, | 137 message_loop_->PostTask(FROM_HERE, | 
| 105 NewRunnableMethod(this, &PipelineImpl::SeekTask, time, | 138 NewRunnableMethod(this, &PipelineImpl::SeekTask, time, | 
| 106 callback.release())); | 139 callback.release())); | 
| 107 } | 140 } | 
| 108 | 141 | 
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 264 bool PipelineImpl::IsStreaming() const { | 297 bool PipelineImpl::IsStreaming() const { | 
| 265 base::AutoLock auto_lock(lock_); | 298 base::AutoLock auto_lock(lock_); | 
| 266 return streaming_; | 299 return streaming_; | 
| 267 } | 300 } | 
| 268 | 301 | 
| 269 bool PipelineImpl::IsLoaded() const { | 302 bool PipelineImpl::IsLoaded() const { | 
| 270 base::AutoLock auto_lock(lock_); | 303 base::AutoLock auto_lock(lock_); | 
| 271 return loaded_; | 304 return loaded_; | 
| 272 } | 305 } | 
| 273 | 306 | 
| 274 PipelineError PipelineImpl::GetError() const { | |
| 275 base::AutoLock auto_lock(lock_); | |
| 276 return error_; | |
| 277 } | |
| 278 | |
| 279 PipelineStatistics PipelineImpl::GetStatistics() const { | 307 PipelineStatistics PipelineImpl::GetStatistics() const { | 
| 280 base::AutoLock auto_lock(lock_); | 308 base::AutoLock auto_lock(lock_); | 
| 281 return statistics_; | 309 return statistics_; | 
| 282 } | 310 } | 
| 283 | 311 | 
| 284 void PipelineImpl::SetClockForTesting(Clock* clock) { | 312 void PipelineImpl::SetClockForTesting(Clock* clock) { | 
| 285 clock_.reset(clock); | 313 clock_.reset(clock); | 
| 286 } | 314 } | 
| 287 | 315 | 
| 288 void PipelineImpl::SetCurrentReadPosition(int64 offset) { | 316 void PipelineImpl::SetCurrentReadPosition(int64 offset) { | 
| (...skipping 26 matching lines...) Expand all Loading... | |
| 315 duration_ = kZero; | 343 duration_ = kZero; | 
| 316 buffered_time_ = kZero; | 344 buffered_time_ = kZero; | 
| 317 buffered_bytes_ = 0; | 345 buffered_bytes_ = 0; | 
| 318 streaming_ = false; | 346 streaming_ = false; | 
| 319 loaded_ = false; | 347 loaded_ = false; | 
| 320 total_bytes_ = 0; | 348 total_bytes_ = 0; | 
| 321 video_width_ = 0; | 349 video_width_ = 0; | 
| 322 video_height_ = 0; | 350 video_height_ = 0; | 
| 323 volume_ = 1.0f; | 351 volume_ = 1.0f; | 
| 324 playback_rate_ = 0.0f; | 352 playback_rate_ = 0.0f; | 
| 325 error_ = PIPELINE_OK; | 353 status_ = PIPELINE_OK; | 
| 326 has_audio_ = false; | 354 has_audio_ = false; | 
| 327 has_video_ = false; | 355 has_video_ = false; | 
| 328 waiting_for_clock_update_ = false; | 356 waiting_for_clock_update_ = false; | 
| 329 audio_disabled_ = false; | 357 audio_disabled_ = false; | 
| 330 clock_->SetTime(kZero); | 358 clock_->SetTime(kZero); | 
| 331 } | 359 } | 
| 332 | 360 | 
| 333 void PipelineImpl::set_state(State next_state) { | 361 void PipelineImpl::set_state(State next_state) { | 
| 334 state_ = next_state; | 362 state_ = next_state; | 
| 335 } | 363 } | 
| 336 | 364 | 
| 337 bool PipelineImpl::IsPipelineOk() { | 365 bool PipelineImpl::IsPipelineOk() { | 
| 338 return PIPELINE_OK == GetError(); | 366 base::AutoLock auto_lock(lock_); | 
| 367 return status_ == PIPELINE_OK; | |
| 339 } | 368 } | 
| 340 | 369 | 
| 341 bool PipelineImpl::IsPipelineStopped() { | 370 bool PipelineImpl::IsPipelineStopped() { | 
| 342 DCHECK_EQ(MessageLoop::current(), message_loop_); | 371 DCHECK_EQ(MessageLoop::current(), message_loop_); | 
| 343 return state_ == kStopped || state_ == kError; | 372 return state_ == kStopped || state_ == kError; | 
| 344 } | 373 } | 
| 345 | 374 | 
| 346 bool PipelineImpl::IsPipelineTearingDown() { | 375 bool PipelineImpl::IsPipelineTearingDown() { | 
| 347 DCHECK_EQ(MessageLoop::current(), message_loop_); | 376 DCHECK_EQ(MessageLoop::current(), message_loop_); | 
| 348 return tearing_down_; | 377 return tearing_down_; | 
| (...skipping 12 matching lines...) Expand all Loading... | |
| 361 kFlushing == state_ || kStarting == state_) | 390 kFlushing == state_ || kStarting == state_) | 
| 362 << "Current state : " << state_; | 391 << "Current state : " << state_; | 
| 363 return true; | 392 return true; | 
| 364 } | 393 } | 
| 365 | 394 | 
| 366 void PipelineImpl::FinishInitialization() { | 395 void PipelineImpl::FinishInitialization() { | 
| 367 DCHECK_EQ(MessageLoop::current(), message_loop_); | 396 DCHECK_EQ(MessageLoop::current(), message_loop_); | 
| 368 // Execute the seek callback, if present. Note that this might be the | 397 // Execute the seek callback, if present. Note that this might be the | 
| 369 // initial callback passed into Start(). | 398 // initial callback passed into Start(). | 
| 370 if (seek_callback_.get()) { | 399 if (seek_callback_.get()) { | 
| 371 seek_callback_->Run(); | 400 seek_callback_->Run(status_); | 
| 372 seek_callback_.reset(); | 401 seek_callback_.reset(); | 
| 373 } | 402 } | 
| 374 } | 403 } | 
| 375 | 404 | 
| 376 // static | 405 // static | 
| 377 bool PipelineImpl::TransientState(State state) { | 406 bool PipelineImpl::TransientState(State state) { | 
| 378 return state == kPausing || | 407 return state == kPausing || | 
| 379 state == kFlushing || | 408 state == kFlushing || | 
| 380 state == kSeeking || | 409 state == kSeeking || | 
| 381 state == kStarting || | 410 state == kStarting || | 
| (...skipping 16 matching lines...) Expand all Loading... | |
| 398 return kStarting; | 427 return kStarting; | 
| 399 } else if (current == kStarting) { | 428 } else if (current == kStarting) { | 
| 400 return kStarted; | 429 return kStarted; | 
| 401 } else if (current == kStopping) { | 430 } else if (current == kStopping) { | 
| 402 return error_caused_teardown_ ? kError : kStopped; | 431 return error_caused_teardown_ ? kError : kStopped; | 
| 403 } else { | 432 } else { | 
| 404 return current; | 433 return current; | 
| 405 } | 434 } | 
| 406 } | 435 } | 
| 407 | 436 | 
| 408 void PipelineImpl::SetError(PipelineError error) { | 437 void PipelineImpl::SetError(PipelineStatus error) { | 
| 409 DCHECK(IsRunning()); | 438 DCHECK(IsRunning()); | 
| 410 DCHECK(error != PIPELINE_OK) << "PIPELINE_OK isn't an error!"; | 439 DCHECK(error != PIPELINE_OK) << "PIPELINE_OK isn't an error!"; | 
| 411 VLOG(1) << "Media pipeline error: " << error; | 440 VLOG(1) << "Media pipeline error: " << error; | 
| 412 | 441 | 
| 413 message_loop_->PostTask(FROM_HERE, | 442 message_loop_->PostTask(FROM_HERE, | 
| 414 NewRunnableMethod(this, &PipelineImpl::ErrorChangedTask, error)); | 443 NewRunnableMethod(this, &PipelineImpl::ErrorChangedTask, error)); | 
| 415 } | 444 } | 
| 416 | 445 | 
| 417 base::TimeDelta PipelineImpl::GetTime() const { | 446 base::TimeDelta PipelineImpl::GetTime() const { | 
| 418 DCHECK(IsRunning()); | 447 DCHECK(IsRunning()); | 
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 534 void PipelineImpl::OnUpdateStatistics(const PipelineStatistics& stats) { | 563 void PipelineImpl::OnUpdateStatistics(const PipelineStatistics& stats) { | 
| 535 base::AutoLock auto_lock(lock_); | 564 base::AutoLock auto_lock(lock_); | 
| 536 statistics_.audio_bytes_decoded += stats.audio_bytes_decoded; | 565 statistics_.audio_bytes_decoded += stats.audio_bytes_decoded; | 
| 537 statistics_.video_bytes_decoded += stats.video_bytes_decoded; | 566 statistics_.video_bytes_decoded += stats.video_bytes_decoded; | 
| 538 statistics_.video_frames_decoded += stats.video_frames_decoded; | 567 statistics_.video_frames_decoded += stats.video_frames_decoded; | 
| 539 statistics_.video_frames_dropped += stats.video_frames_dropped; | 568 statistics_.video_frames_dropped += stats.video_frames_dropped; | 
| 540 } | 569 } | 
| 541 | 570 | 
| 542 void PipelineImpl::StartTask(FilterCollection* filter_collection, | 571 void PipelineImpl::StartTask(FilterCollection* filter_collection, | 
| 543 const std::string& url, | 572 const std::string& url, | 
| 544 PipelineCallback* start_callback) { | 573 PipelineStatusCallback* start_callback) { | 
| 545 DCHECK_EQ(MessageLoop::current(), message_loop_); | 574 DCHECK_EQ(MessageLoop::current(), message_loop_); | 
| 546 DCHECK_EQ(kCreated, state_); | 575 DCHECK_EQ(kCreated, state_); | 
| 547 filter_collection_.reset(filter_collection); | 576 filter_collection_.reset(filter_collection); | 
| 548 url_ = url; | 577 url_ = url; | 
| 549 seek_callback_.reset(start_callback); | 578 seek_callback_.reset(start_callback); | 
| 550 | 579 | 
| 551 // Kick off initialization. | 580 // Kick off initialization. | 
| 552 set_state(kInitDemuxer); | 581 set_state(kInitDemuxer); | 
| 553 pipeline_init_state_.reset(new PipelineInitState()); | 582 pipeline_init_state_.reset(new PipelineInitState()); | 
| 554 pipeline_init_state_->composite_ = new CompositeFilter(message_loop_); | 583 pipeline_init_state_->composite_ = new CompositeFilter(message_loop_); | 
| (...skipping 16 matching lines...) Expand all Loading... | |
| 571 // FilterHost's InitializationComplete() method, the pipeline will update its | 600 // FilterHost's InitializationComplete() method, the pipeline will update its | 
| 572 // state to kStarted and |init_callback_|, will be executed. | 601 // state to kStarted and |init_callback_|, will be executed. | 
| 573 // | 602 // | 
| 574 // TODO(hclam): InitializeTask() is now starting the pipeline asynchronously. It | 603 // TODO(hclam): InitializeTask() is now starting the pipeline asynchronously. It | 
| 575 // works like a big state change table. If we no longer need to start filters | 604 // works like a big state change table. If we no longer need to start filters | 
| 576 // in order, we need to get rid of all the state change. | 605 // in order, we need to get rid of all the state change. | 
| 577 void PipelineImpl::InitializeTask() { | 606 void PipelineImpl::InitializeTask() { | 
| 578 DCHECK_EQ(MessageLoop::current(), message_loop_); | 607 DCHECK_EQ(MessageLoop::current(), message_loop_); | 
| 579 | 608 | 
| 580 // If we have received the stop or error signal, return immediately. | 609 // If we have received the stop or error signal, return immediately. | 
| 581 if (IsPipelineStopPending() || | 610 if (IsPipelineStopPending() || IsPipelineStopped() || !IsPipelineOk()) | 
| 582 IsPipelineStopped() || | |
| 583 PIPELINE_OK != GetError()) { | |
| 584 return; | 611 return; | 
| 585 } | |
| 586 | 612 | 
| 587 DCHECK(state_ == kInitDemuxer || | 613 DCHECK(state_ == kInitDemuxer || | 
| 588 state_ == kInitAudioDecoder || | 614 state_ == kInitAudioDecoder || | 
| 589 state_ == kInitAudioRenderer || | 615 state_ == kInitAudioRenderer || | 
| 590 state_ == kInitVideoDecoder || | 616 state_ == kInitVideoDecoder || | 
| 591 state_ == kInitVideoRenderer); | 617 state_ == kInitVideoRenderer); | 
| 592 | 618 | 
| 593 | 619 | 
| 594 // Demuxer created, create audio decoder. | 620 // Demuxer created, create audio decoder. | 
| 595 if (state_ == kInitDemuxer) { | 621 if (state_ == kInitDemuxer) { | 
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 662 } | 688 } | 
| 663 } | 689 } | 
| 664 | 690 | 
| 665 // This method is called as a result of the client calling Pipeline::Stop() or | 691 // This method is called as a result of the client calling Pipeline::Stop() or | 
| 666 // as the result of an error condition. | 692 // as the result of an error condition. | 
| 667 // We stop the filters in the reverse order. | 693 // We stop the filters in the reverse order. | 
| 668 // | 694 // | 
| 669 // TODO(scherkus): beware! this can get posted multiple times since we post | 695 // TODO(scherkus): beware! this can get posted multiple times since we post | 
| 670 // Stop() tasks even if we've already stopped. Perhaps this should no-op for | 696 // Stop() tasks even if we've already stopped. Perhaps this should no-op for | 
| 671 // additional calls, however most of this logic will be changing. | 697 // additional calls, however most of this logic will be changing. | 
| 672 void PipelineImpl::StopTask(PipelineCallback* stop_callback) { | 698 void PipelineImpl::StopTask(PipelineStatusCallback* stop_callback) { | 
| 673 DCHECK_EQ(MessageLoop::current(), message_loop_); | 699 DCHECK_EQ(MessageLoop::current(), message_loop_); | 
| 674 DCHECK(!IsPipelineStopPending()); | 700 DCHECK(!IsPipelineStopPending()); | 
| 675 DCHECK_NE(state_, kStopped); | 701 DCHECK_NE(state_, kStopped); | 
| 676 | 702 | 
| 677 if (state_ == kStopped) { | 703 if (state_ == kStopped) { | 
| 678 // Already stopped so just run callback. | 704 // Already stopped so just run callback. | 
| 679 stop_callback->Run(); | 705 stop_callback->Run(status_); | 
| 680 delete stop_callback; | 706 delete stop_callback; | 
| 681 return; | 707 return; | 
| 682 } | 708 } | 
| 683 | 709 | 
| 684 if (IsPipelineTearingDown() && error_caused_teardown_) { | 710 if (IsPipelineTearingDown() && error_caused_teardown_) { | 
| 685 // If we are stopping due to SetError(), stop normally instead of | 711 // If we are stopping due to SetError(), stop normally instead of | 
| 686 // going to error state and calling |error_callback_|. This converts | 712 // going to error state and calling |error_callback_|. This converts | 
| 687 // the teardown in progress from an error teardown into one that acts | 713 // the teardown in progress from an error teardown into one that acts | 
| 688 // like the error never occurred. | 714 // like the error never occurred. | 
| 689 base::AutoLock auto_lock(lock_); | 715 base::AutoLock auto_lock(lock_); | 
| 690 error_ = PIPELINE_OK; | 716 status_ = PIPELINE_OK; | 
| 691 error_caused_teardown_ = false; | 717 error_caused_teardown_ = false; | 
| 692 } | 718 } | 
| 693 | 719 | 
| 694 stop_callback_.reset(stop_callback); | 720 stop_callback_.reset(stop_callback); | 
| 695 | 721 | 
| 696 stop_pending_ = true; | 722 stop_pending_ = true; | 
| 697 if (!IsPipelineSeeking() && !IsPipelineTearingDown()) { | 723 if (!IsPipelineSeeking() && !IsPipelineTearingDown()) { | 
| 698 // We will tear down pipeline immediately when there is no seek operation | 724 // We will tear down pipeline immediately when there is no seek operation | 
| 699 // pending and no teardown in progress. This should include the case where | 725 // pending and no teardown in progress. This should include the case where | 
| 700 // we are partially initialized. | 726 // we are partially initialized. | 
| 701 TearDownPipeline(); | 727 TearDownPipeline(); | 
| 702 } | 728 } | 
| 703 } | 729 } | 
| 704 | 730 | 
| 705 void PipelineImpl::ErrorChangedTask(PipelineError error) { | 731 void PipelineImpl::ErrorChangedTask(PipelineStatus error) { | 
| 706 DCHECK_EQ(MessageLoop::current(), message_loop_); | 732 DCHECK_EQ(MessageLoop::current(), message_loop_); | 
| 707 DCHECK_NE(PIPELINE_OK, error) << "PIPELINE_OK isn't an error!"; | 733 DCHECK_NE(PIPELINE_OK, error) << "PIPELINE_OK isn't an error!"; | 
| 708 | 734 | 
| 709 // Suppress executing additional error logic. Note that if we are currently | 735 // Suppress executing additional error logic. Note that if we are currently | 
| 710 // performing a normal stop, then we return immediately and continue the | 736 // performing a normal stop, then we return immediately and continue the | 
| 711 // normal stop. | 737 // normal stop. | 
| 712 if (IsPipelineStopped() || IsPipelineTearingDown()) { | 738 if (IsPipelineStopped() || IsPipelineTearingDown()) { | 
| 713 return; | 739 return; | 
| 714 } | 740 } | 
| 715 | 741 | 
| 716 base::AutoLock auto_lock(lock_); | 742 base::AutoLock auto_lock(lock_); | 
| 717 error_ = error; | 743 status_ = error; | 
| 718 | 744 | 
| 719 error_caused_teardown_ = true; | 745 error_caused_teardown_ = true; | 
| 720 | 746 | 
| 721 // Posting TearDownPipeline() to message loop so that we can make sure | 747 // Posting TearDownPipeline() to message loop so that we can make sure | 
| 722 // it runs after any pending callbacks that are already queued. | 748 // it runs after any pending callbacks that are already queued. | 
| 723 // |tearing_down_| is set early here to make sure that pending callbacks | 749 // |tearing_down_| is set early here to make sure that pending callbacks | 
| 724 // don't modify the state before TeadDownPipeline() can run. | 750 // don't modify the state before TeadDownPipeline() can run. | 
| 725 tearing_down_ = true; | 751 tearing_down_ = true; | 
| 726 message_loop_->PostTask(FROM_HERE, | 752 message_loop_->PostTask(FROM_HERE, | 
| 727 NewRunnableMethod(this, &PipelineImpl::TearDownPipeline)); | 753 NewRunnableMethod(this, &PipelineImpl::TearDownPipeline)); | 
| (...skipping 16 matching lines...) Expand all Loading... | |
| 744 | 770 | 
| 745 void PipelineImpl::VolumeChangedTask(float volume) { | 771 void PipelineImpl::VolumeChangedTask(float volume) { | 
| 746 DCHECK_EQ(MessageLoop::current(), message_loop_); | 772 DCHECK_EQ(MessageLoop::current(), message_loop_); | 
| 747 | 773 | 
| 748 if (audio_renderer_) { | 774 if (audio_renderer_) { | 
| 749 audio_renderer_->SetVolume(volume); | 775 audio_renderer_->SetVolume(volume); | 
| 750 } | 776 } | 
| 751 } | 777 } | 
| 752 | 778 | 
| 753 void PipelineImpl::SeekTask(base::TimeDelta time, | 779 void PipelineImpl::SeekTask(base::TimeDelta time, | 
| 754 PipelineCallback* seek_callback) { | 780 PipelineStatusCallback* seek_callback) { | 
| 755 DCHECK_EQ(MessageLoop::current(), message_loop_); | 781 DCHECK_EQ(MessageLoop::current(), message_loop_); | 
| 756 DCHECK(!IsPipelineStopPending()); | 782 DCHECK(!IsPipelineStopPending()); | 
| 757 | 783 | 
| 758 // Suppress seeking if we're not fully started. | 784 // Suppress seeking if we're not fully started. | 
| 759 if (state_ != kStarted && state_ != kEnded) { | 785 if (state_ != kStarted && state_ != kEnded) { | 
| 760 // TODO(scherkus): should we run the callback? I'm tempted to say the API | 786 // TODO(scherkus): should we run the callback? I'm tempted to say the API | 
| 761 // will only execute the first Seek() request. | 787 // will only execute the first Seek() request. | 
| 762 VLOG(1) << "Media pipeline has not started, ignoring seek to " | 788 VLOG(1) << "Media pipeline has not started, ignoring seek to " | 
| 763 << time.InMicroseconds(); | 789 << time.InMicroseconds(); | 
| 764 delete seek_callback; | 790 delete seek_callback; | 
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 814 } | 840 } | 
| 815 } | 841 } | 
| 816 | 842 | 
| 817 if (video_renderer_ && !video_renderer_->HasEnded()) { | 843 if (video_renderer_ && !video_renderer_->HasEnded()) { | 
| 818 return; | 844 return; | 
| 819 } | 845 } | 
| 820 | 846 | 
| 821 // Transition to ended, executing the callback if present. | 847 // Transition to ended, executing the callback if present. | 
| 822 set_state(kEnded); | 848 set_state(kEnded); | 
| 823 if (ended_callback_.get()) { | 849 if (ended_callback_.get()) { | 
| 824 ended_callback_->Run(); | 850 ended_callback_->Run(status_); | 
| 825 } | 851 } | 
| 826 } | 852 } | 
| 827 | 853 | 
| 828 void PipelineImpl::NotifyNetworkEventTask() { | 854 void PipelineImpl::NotifyNetworkEventTask() { | 
| 829 DCHECK_EQ(MessageLoop::current(), message_loop_); | 855 DCHECK_EQ(MessageLoop::current(), message_loop_); | 
| 830 if (network_callback_.get()) { | 856 if (network_callback_.get()) { | 
| 831 network_callback_->Run(); | 857 network_callback_->Run(status_); | 
| 832 } | 858 } | 
| 833 } | 859 } | 
| 834 | 860 | 
| 835 void PipelineImpl::DisableAudioRendererTask() { | 861 void PipelineImpl::DisableAudioRendererTask() { | 
| 836 DCHECK_EQ(MessageLoop::current(), message_loop_); | 862 DCHECK_EQ(MessageLoop::current(), message_loop_); | 
| 837 | 863 | 
| 838 base::AutoLock auto_lock(lock_); | 864 base::AutoLock auto_lock(lock_); | 
| 839 has_audio_ = false; | 865 has_audio_ = false; | 
| 840 audio_disabled_ = true; | 866 audio_disabled_ = true; | 
| 841 | 867 | 
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 958 void PipelineImpl::FinishDestroyingFiltersTask() { | 984 void PipelineImpl::FinishDestroyingFiltersTask() { | 
| 959 DCHECK_EQ(MessageLoop::current(), message_loop_); | 985 DCHECK_EQ(MessageLoop::current(), message_loop_); | 
| 960 DCHECK(IsPipelineStopped()); | 986 DCHECK(IsPipelineStopped()); | 
| 961 | 987 | 
| 962 // Clear renderer references. | 988 // Clear renderer references. | 
| 963 audio_renderer_ = NULL; | 989 audio_renderer_ = NULL; | 
| 964 video_renderer_ = NULL; | 990 video_renderer_ = NULL; | 
| 965 | 991 | 
| 966 pipeline_filter_ = NULL; | 992 pipeline_filter_ = NULL; | 
| 967 | 993 | 
| 968 if (error_caused_teardown_ && GetError() != PIPELINE_OK && | 994 if (error_caused_teardown_ && !IsPipelineOk() && error_callback_.get()) | 
| 969 error_callback_.get()) { | 995 error_callback_->Run(status_); | 
| 970 error_callback_->Run(); | |
| 971 } | |
| 972 | 996 | 
| 973 if (stop_pending_) { | 997 if (stop_pending_) { | 
| 974 stop_pending_ = false; | 998 stop_pending_ = false; | 
| 975 ResetState(); | 999 ResetState(); | 
| 976 scoped_ptr<PipelineCallback> stop_callback(stop_callback_.release()); | 1000 scoped_ptr<PipelineStatusCallback> stop_callback(stop_callback_.release()); | 
| 977 // Notify the client that stopping has finished. | 1001 // Notify the client that stopping has finished. | 
| 978 if (stop_callback.get()) { | 1002 if (stop_callback.get()) { | 
| 979 stop_callback->Run(); | 1003 stop_callback->Run(status_); | 
| 980 } | 1004 } | 
| 981 } | 1005 } | 
| 982 | 1006 | 
| 983 tearing_down_ = false; | 1007 tearing_down_ = false; | 
| 984 error_caused_teardown_ = false; | 1008 error_caused_teardown_ = false; | 
| 985 } | 1009 } | 
| 986 | 1010 | 
| 987 bool PipelineImpl::PrepareFilter(scoped_refptr<Filter> filter) { | 1011 bool PipelineImpl::PrepareFilter(scoped_refptr<Filter> filter) { | 
| 988 bool ret = pipeline_init_state_->composite_->AddFilter(filter.get()); | 1012 bool ret = pipeline_init_state_->composite_->AddFilter(filter.get()); | 
| 989 | 1013 | 
| 990 if (!ret) { | 1014 if (!ret) { | 
| 991 SetError(PIPELINE_ERROR_INITIALIZATION_FAILED); | 1015 SetError(PIPELINE_ERROR_INITIALIZATION_FAILED); | 
| 992 } | 1016 } | 
| 993 return ret; | 1017 return ret; | 
| 994 } | 1018 } | 
| 995 | 1019 | 
| 996 void PipelineImpl::InitializeDemuxer() { | 1020 void PipelineImpl::InitializeDemuxer() { | 
| 997 DCHECK_EQ(MessageLoop::current(), message_loop_); | 1021 DCHECK_EQ(MessageLoop::current(), message_loop_); | 
| 998 DCHECK(IsPipelineOk()); | 1022 DCHECK(IsPipelineOk()); | 
| 999 | 1023 | 
| 1000 filter_collection_->GetDemuxerFactory()->Build(url_, | 1024 filter_collection_->GetDemuxerFactory()->Build(url_, | 
| 1001 NewCallback(this, &PipelineImpl::OnDemuxerBuilt)); | 1025 NewCallback(this, &PipelineImpl::OnDemuxerBuilt)); | 
| 1002 } | 1026 } | 
| 1003 | 1027 | 
| 1004 void PipelineImpl::OnDemuxerBuilt(PipelineError error, | 1028 void PipelineImpl::OnDemuxerBuilt(PipelineStatus status, Demuxer* demuxer) { | 
| 1005 Demuxer* demuxer) { | |
| 1006 if (MessageLoop::current() != message_loop_) { | 1029 if (MessageLoop::current() != message_loop_) { | 
| 1007 message_loop_->PostTask(FROM_HERE, | 1030 message_loop_->PostTask(FROM_HERE, | 
| 1008 NewRunnableMethod(this, | 1031 NewRunnableMethod(this, | 
| 1009 &PipelineImpl::OnDemuxerBuilt, | 1032 &PipelineImpl::OnDemuxerBuilt, | 
| 1010 error, | 1033 status, | 
| 1011 make_scoped_refptr(demuxer))); | 1034 make_scoped_refptr(demuxer))); | 
| 1012 return; | 1035 return; | 
| 1013 } | 1036 } | 
| 1014 | 1037 | 
| 1015 if (error != PIPELINE_OK) { | 1038 if (status != PIPELINE_OK) { | 
| 1016 SetError(error); | 1039 SetError(status); | 
| 1017 return; | 1040 return; | 
| 1018 } | 1041 } | 
| 1019 | 1042 | 
| 1020 if (!demuxer) { | 1043 if (!demuxer) { | 
| 1021 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 1044 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 
| 1022 return; | 1045 return; | 
| 1023 } | 1046 } | 
| 1024 | 1047 | 
| 1025 if (!PrepareFilter(demuxer)) | 1048 if (!PrepareFilter(demuxer)) | 
| 1026 return; | 1049 return; | 
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1213 case kStopping: | 1236 case kStopping: | 
| 1214 case kStopped: | 1237 case kStopped: | 
| 1215 NOTREACHED() << "Unexpected state for teardown: " << state_; | 1238 NOTREACHED() << "Unexpected state for teardown: " << state_; | 
| 1216 break; | 1239 break; | 
| 1217 // default: intentionally left out to force new states to cause compiler | 1240 // default: intentionally left out to force new states to cause compiler | 
| 1218 // errors. | 1241 // errors. | 
| 1219 }; | 1242 }; | 
| 1220 } | 1243 } | 
| 1221 | 1244 | 
| 1222 } // namespace media | 1245 } // namespace media | 
| OLD | NEW |