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 |