OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 #include "media/base/pipeline.h" | 5 #include "media/base/pipeline.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback.h" | 10 #include "base/callback.h" |
11 #include "base/callback_helpers.h" | 11 #include "base/callback_helpers.h" |
12 #include "base/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
13 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
14 #include "base/message_loop.h" | 14 #include "base/message_loop.h" |
15 #include "base/stl_util.h" | 15 #include "base/stl_util.h" |
16 #include "base/string_util.h" | 16 #include "base/string_util.h" |
17 #include "base/synchronization/condition_variable.h" | 17 #include "base/synchronization/condition_variable.h" |
18 #include "media/base/audio_decoder.h" | 18 #include "media/base/audio_decoder.h" |
19 #include "media/base/audio_renderer.h" | 19 #include "media/base/audio_renderer.h" |
20 #include "media/base/callback_util.h" | 20 #include "media/base/callback_util.h" |
21 #include "media/base/clock.h" | 21 #include "media/base/clock.h" |
22 #include "media/base/composite_filter.h" | |
23 #include "media/base/filter_collection.h" | 22 #include "media/base/filter_collection.h" |
24 #include "media/base/media_log.h" | 23 #include "media/base/media_log.h" |
25 #include "media/base/video_decoder.h" | 24 #include "media/base/video_decoder.h" |
26 #include "media/base/video_renderer.h" | 25 #include "media/base/video_renderer.h" |
27 | 26 |
28 using base::TimeDelta; | 27 using base::TimeDelta; |
29 | 28 |
30 namespace media { | 29 namespace media { |
31 | 30 |
32 PipelineStatusNotification::PipelineStatusNotification() | 31 PipelineStatusNotification::PipelineStatusNotification() |
(...skipping 25 matching lines...) Expand all Loading... |
58 | 57 |
59 media::PipelineStatus PipelineStatusNotification::status() { | 58 media::PipelineStatus PipelineStatusNotification::status() { |
60 base::AutoLock auto_lock(lock_); | 59 base::AutoLock auto_lock(lock_); |
61 DCHECK(notified_); | 60 DCHECK(notified_); |
62 return status_; | 61 return status_; |
63 } | 62 } |
64 | 63 |
65 struct Pipeline::PipelineInitState { | 64 struct Pipeline::PipelineInitState { |
66 scoped_refptr<AudioDecoder> audio_decoder; | 65 scoped_refptr<AudioDecoder> audio_decoder; |
67 scoped_refptr<VideoDecoder> video_decoder; | 66 scoped_refptr<VideoDecoder> video_decoder; |
68 scoped_refptr<VideoRenderer> video_renderer; | |
69 scoped_refptr<CompositeFilter> composite; | |
70 }; | 67 }; |
71 | 68 |
72 Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log) | 69 Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log) |
73 : message_loop_(message_loop->message_loop_proxy()), | 70 : message_loop_(message_loop->message_loop_proxy()), |
74 media_log_(media_log), | 71 media_log_(media_log), |
75 clock_(new Clock(&base::Time::Now)), | 72 clock_(new Clock(&base::Time::Now)), |
76 waiting_for_clock_update_(false), | 73 waiting_for_clock_update_(false), |
77 state_(kCreated), | 74 state_(kCreated), |
78 creation_time_(base::Time::Now()) { | 75 creation_time_(base::Time::Now()) { |
79 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); | 76 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 return; | 179 return; |
183 | 180 |
184 base::AutoLock auto_lock(lock_); | 181 base::AutoLock auto_lock(lock_); |
185 volume_ = volume; | 182 volume_ = volume; |
186 if (running_ && !tearing_down_) { | 183 if (running_ && !tearing_down_) { |
187 message_loop_->PostTask(FROM_HERE, base::Bind( | 184 message_loop_->PostTask(FROM_HERE, base::Bind( |
188 &Pipeline::VolumeChangedTask, this, volume)); | 185 &Pipeline::VolumeChangedTask, this, volume)); |
189 } | 186 } |
190 } | 187 } |
191 | 188 |
192 TimeDelta Pipeline::GetCurrentTime() const { | 189 TimeDelta Pipeline::GetMediaTime() const { |
193 base::AutoLock auto_lock(lock_); | 190 base::AutoLock auto_lock(lock_); |
194 return GetCurrentTime_Locked(); | |
195 } | |
196 | |
197 TimeDelta Pipeline::GetCurrentTime_Locked() const { | |
198 lock_.AssertAcquired(); | |
199 return clock_->Elapsed(); | 191 return clock_->Elapsed(); |
200 } | 192 } |
201 | 193 |
202 Ranges<TimeDelta> Pipeline::GetBufferedTimeRanges() { | 194 Ranges<TimeDelta> Pipeline::GetBufferedTimeRanges() { |
203 base::AutoLock auto_lock(lock_); | 195 base::AutoLock auto_lock(lock_); |
204 Ranges<TimeDelta> time_ranges; | 196 Ranges<TimeDelta> time_ranges; |
205 for (size_t i = 0; i < buffered_time_ranges_.size(); ++i) { | 197 for (size_t i = 0; i < buffered_time_ranges_.size(); ++i) { |
206 time_ranges.Add(buffered_time_ranges_.start(i), | 198 time_ranges.Add(buffered_time_ranges_.start(i), |
207 buffered_time_ranges_.end(i)); | 199 buffered_time_ranges_.end(i)); |
208 } | 200 } |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
374 DCHECK(IsRunning()); | 366 DCHECK(IsRunning()); |
375 DCHECK_NE(PIPELINE_OK, error); | 367 DCHECK_NE(PIPELINE_OK, error); |
376 VLOG(1) << "Media pipeline error: " << error; | 368 VLOG(1) << "Media pipeline error: " << error; |
377 | 369 |
378 message_loop_->PostTask(FROM_HERE, base::Bind( | 370 message_loop_->PostTask(FROM_HERE, base::Bind( |
379 &Pipeline::ErrorChangedTask, this, error)); | 371 &Pipeline::ErrorChangedTask, this, error)); |
380 | 372 |
381 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error)); | 373 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error)); |
382 } | 374 } |
383 | 375 |
384 TimeDelta Pipeline::GetTime() const { | |
385 DCHECK(IsRunning()); | |
386 return GetCurrentTime(); | |
387 } | |
388 | |
389 TimeDelta Pipeline::GetDuration() const { | |
390 DCHECK(IsRunning()); | |
391 return GetMediaDuration(); | |
392 } | |
393 | |
394 void Pipeline::OnAudioDisabled() { | 376 void Pipeline::OnAudioDisabled() { |
395 DCHECK(IsRunning()); | 377 DCHECK(IsRunning()); |
396 message_loop_->PostTask(FROM_HERE, base::Bind( | 378 message_loop_->PostTask(FROM_HERE, base::Bind( |
397 &Pipeline::AudioDisabledTask, this)); | 379 &Pipeline::AudioDisabledTask, this)); |
398 media_log_->AddEvent( | 380 media_log_->AddEvent( |
399 media_log_->CreateEvent(MediaLogEvent::AUDIO_RENDERER_DISABLED)); | 381 media_log_->CreateEvent(MediaLogEvent::AUDIO_RENDERER_DISABLED)); |
400 } | 382 } |
401 | 383 |
402 void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) { | 384 void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) { |
403 DCHECK(time <= max_time); | 385 DCHECK(time <= max_time); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
469 return time_offset; | 451 return time_offset; |
470 } | 452 } |
471 | 453 |
472 void Pipeline::DoPause(const base::Closure& done_cb) { | 454 void Pipeline::DoPause(const base::Closure& done_cb) { |
473 DCHECK(message_loop_->BelongsToCurrentThread()); | 455 DCHECK(message_loop_->BelongsToCurrentThread()); |
474 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); | 456 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); |
475 | 457 |
476 if (audio_renderer_) | 458 if (audio_renderer_) |
477 closures->push(base::Bind(&AudioRenderer::Pause, audio_renderer_)); | 459 closures->push(base::Bind(&AudioRenderer::Pause, audio_renderer_)); |
478 | 460 |
479 if (pipeline_filter_) | 461 if (video_renderer_) |
480 closures->push(base::Bind(&Filter::Pause, pipeline_filter_)); | 462 closures->push(base::Bind(&VideoRenderer::Pause, video_renderer_)); |
481 | 463 |
482 RunInSeries(closures.Pass(), done_cb); | 464 RunInSeries(closures.Pass(), done_cb); |
483 } | 465 } |
484 | 466 |
485 void Pipeline::DoFlush(const base::Closure& done_cb) { | 467 void Pipeline::DoFlush(const base::Closure& done_cb) { |
486 DCHECK(message_loop_->BelongsToCurrentThread()); | 468 DCHECK(message_loop_->BelongsToCurrentThread()); |
487 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); | 469 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); |
488 | 470 |
489 if (audio_renderer_) | 471 if (audio_renderer_) |
490 closures->push(base::Bind(&AudioRenderer::Flush, audio_renderer_)); | 472 closures->push(base::Bind(&AudioRenderer::Flush, audio_renderer_)); |
491 | 473 |
492 if (pipeline_filter_) | 474 if (video_renderer_) |
493 closures->push(base::Bind(&Filter::Flush, pipeline_filter_)); | 475 closures->push(base::Bind(&VideoRenderer::Flush, video_renderer_)); |
494 | 476 |
495 RunInParallel(closures.Pass(), done_cb); | 477 RunInParallel(closures.Pass(), done_cb); |
496 } | 478 } |
497 | 479 |
498 void Pipeline::DoPlay(const base::Closure& done_cb) { | 480 void Pipeline::DoPlay(const base::Closure& done_cb) { |
499 DCHECK(message_loop_->BelongsToCurrentThread()); | 481 DCHECK(message_loop_->BelongsToCurrentThread()); |
500 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); | 482 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); |
501 | 483 |
502 if (audio_renderer_) | 484 if (audio_renderer_) |
503 closures->push(base::Bind(&AudioRenderer::Play, audio_renderer_)); | 485 closures->push(base::Bind(&AudioRenderer::Play, audio_renderer_)); |
504 | 486 |
505 if (pipeline_filter_) | 487 if (video_renderer_) |
506 closures->push(base::Bind(&Filter::Play, pipeline_filter_)); | 488 closures->push(base::Bind(&VideoRenderer::Play, video_renderer_)); |
507 | 489 |
508 RunInSeries(closures.Pass(), done_cb); | 490 RunInSeries(closures.Pass(), done_cb); |
509 } | 491 } |
510 | 492 |
511 void Pipeline::DoStop(const base::Closure& done_cb) { | 493 void Pipeline::DoStop(const base::Closure& done_cb) { |
512 DCHECK(message_loop_->BelongsToCurrentThread()); | 494 DCHECK(message_loop_->BelongsToCurrentThread()); |
513 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); | 495 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); |
514 | 496 |
515 if (demuxer_) | 497 if (demuxer_) |
516 closures->push(base::Bind(&Demuxer::Stop, demuxer_)); | 498 closures->push(base::Bind(&Demuxer::Stop, demuxer_)); |
517 | 499 |
518 if (audio_renderer_) | 500 if (audio_renderer_) |
519 closures->push(base::Bind(&AudioRenderer::Stop, audio_renderer_)); | 501 closures->push(base::Bind(&AudioRenderer::Stop, audio_renderer_)); |
520 | 502 |
521 if (pipeline_filter_) | 503 if (video_renderer_) |
522 closures->push(base::Bind(&Filter::Stop, pipeline_filter_)); | 504 closures->push(base::Bind(&VideoRenderer::Stop, video_renderer_)); |
523 | 505 |
524 RunInSeries(closures.Pass(), done_cb); | 506 RunInSeries(closures.Pass(), done_cb); |
525 } | 507 } |
526 | 508 |
527 void Pipeline::AddBufferedByteRange(int64 start, int64 end) { | 509 void Pipeline::AddBufferedByteRange(int64 start, int64 end) { |
528 DCHECK(IsRunning()); | 510 DCHECK(IsRunning()); |
529 base::AutoLock auto_lock(lock_); | 511 base::AutoLock auto_lock(lock_); |
530 buffered_byte_ranges_.Add(start, end); | 512 buffered_byte_ranges_.Add(start, end); |
531 did_loading_progress_ = true; | 513 did_loading_progress_ = true; |
532 } | 514 } |
533 | 515 |
534 void Pipeline::AddBufferedTimeRange(base::TimeDelta start, | 516 void Pipeline::AddBufferedTimeRange(base::TimeDelta start, |
535 base::TimeDelta end) { | 517 base::TimeDelta end) { |
536 DCHECK(IsRunning()); | 518 DCHECK(IsRunning()); |
537 base::AutoLock auto_lock(lock_); | 519 base::AutoLock auto_lock(lock_); |
538 buffered_time_ranges_.Add(start, end); | 520 buffered_time_ranges_.Add(start, end); |
539 did_loading_progress_ = true; | 521 did_loading_progress_ = true; |
540 } | 522 } |
541 | 523 |
542 void Pipeline::SetNaturalVideoSize(const gfx::Size& size) { | 524 void Pipeline::OnNaturalVideoSizeChanged(const gfx::Size& size) { |
543 DCHECK(IsRunning()); | 525 DCHECK(IsRunning()); |
544 media_log_->AddEvent(media_log_->CreateVideoSizeSetEvent( | 526 media_log_->AddEvent(media_log_->CreateVideoSizeSetEvent( |
545 size.width(), size.height())); | 527 size.width(), size.height())); |
546 | 528 |
547 base::AutoLock auto_lock(lock_); | 529 base::AutoLock auto_lock(lock_); |
548 natural_size_ = size; | 530 natural_size_ = size; |
549 } | 531 } |
550 | 532 |
551 void Pipeline::NotifyEnded() { | 533 void Pipeline::OnRendererEnded() { |
552 DCHECK(IsRunning()); | 534 DCHECK(IsRunning()); |
553 message_loop_->PostTask(FROM_HERE, base::Bind( | 535 message_loop_->PostTask(FROM_HERE, base::Bind( |
554 &Pipeline::NotifyEndedTask, this)); | 536 &Pipeline::OnRendererEndedTask, this)); |
555 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED)); | 537 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED)); |
556 } | 538 } |
557 | 539 |
558 // Called from any thread. | 540 // Called from any thread. |
559 void Pipeline::OnFilterInitialize(PipelineStatus status) { | 541 void Pipeline::OnFilterInitialize(PipelineStatus status) { |
560 // Continue the initialize task by proceeding to the next stage. | 542 // Continue the initialize task by proceeding to the next stage. |
561 message_loop_->PostTask(FROM_HERE, base::Bind( | 543 message_loop_->PostTask(FROM_HERE, base::Bind( |
562 &Pipeline::InitializeTask, this, status)); | 544 &Pipeline::InitializeTask, this, status)); |
563 } | 545 } |
564 | 546 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
601 const PipelineStatusCB& start_cb) { | 583 const PipelineStatusCB& start_cb) { |
602 DCHECK(message_loop_->BelongsToCurrentThread()); | 584 DCHECK(message_loop_->BelongsToCurrentThread()); |
603 DCHECK_EQ(kCreated, state_); | 585 DCHECK_EQ(kCreated, state_); |
604 filter_collection_ = filter_collection.Pass(); | 586 filter_collection_ = filter_collection.Pass(); |
605 ended_cb_ = ended_cb; | 587 ended_cb_ = ended_cb; |
606 error_cb_ = error_cb; | 588 error_cb_ = error_cb; |
607 seek_cb_ = start_cb; | 589 seek_cb_ = start_cb; |
608 | 590 |
609 // Kick off initialization. | 591 // Kick off initialization. |
610 pipeline_init_state_.reset(new PipelineInitState()); | 592 pipeline_init_state_.reset(new PipelineInitState()); |
611 pipeline_init_state_->composite = new CompositeFilter(message_loop_); | |
612 pipeline_init_state_->composite->SetHost(this); | |
613 | 593 |
614 SetState(kInitDemuxer); | 594 SetState(kInitDemuxer); |
615 InitializeDemuxer(); | 595 InitializeDemuxer(); |
616 } | 596 } |
617 | 597 |
618 // Main initialization method called on the pipeline thread. This code attempts | 598 // Main initialization method called on the pipeline thread. This code attempts |
619 // to use the specified filter factory to build a pipeline. | 599 // to use the specified filter factory to build a pipeline. |
620 // Initialization step performed in this method depends on current state of this | 600 // Initialization step performed in this method depends on current state of this |
621 // object, indicated by |state_|. After each step of initialization, this | 601 // object, indicated by |state_|. After each step of initialization, this |
622 // object transits to the next stage. It starts by creating a Demuxer, and then | 602 // object transits to the next stage. It starts by creating a Demuxer, and then |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
692 return; | 672 return; |
693 } | 673 } |
694 } | 674 } |
695 | 675 |
696 if (state_ == kInitVideoRenderer) { | 676 if (state_ == kInitVideoRenderer) { |
697 if (!IsPipelineOk() || !(HasAudio() || HasVideo())) { | 677 if (!IsPipelineOk() || !(HasAudio() || HasVideo())) { |
698 SetError(PIPELINE_ERROR_COULD_NOT_RENDER); | 678 SetError(PIPELINE_ERROR_COULD_NOT_RENDER); |
699 return; | 679 return; |
700 } | 680 } |
701 | 681 |
702 // Clear the collection of filters. | 682 // Clear initialization state now that we're done. |
703 filter_collection_->Clear(); | 683 filter_collection_.reset(); |
704 | |
705 pipeline_filter_ = pipeline_init_state_->composite; | |
706 | |
707 // Clear init state since we're done initializing. | |
708 pipeline_init_state_.reset(); | 684 pipeline_init_state_.reset(); |
709 | 685 |
710 // Initialization was successful, we are now considered paused, so it's safe | 686 // Initialization was successful, we are now considered paused, so it's safe |
711 // to set the initial playback rate and volume. | 687 // to set the initial playback rate and volume. |
712 PlaybackRateChangedTask(GetPlaybackRate()); | 688 PlaybackRateChangedTask(GetPlaybackRate()); |
713 VolumeChangedTask(GetVolume()); | 689 VolumeChangedTask(GetVolume()); |
714 | 690 |
715 // Fire a seek request to get the renderers to preroll. We can skip a seek | 691 // Fire a seek request to get the renderers to preroll. We can skip a seek |
716 // here as the demuxer should be at the start of the stream. | 692 // here as the demuxer should be at the start of the stream. |
717 seek_pending_ = true; | 693 seek_pending_ = true; |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
796 pending_playback_rate_ = playback_rate; | 772 pending_playback_rate_ = playback_rate; |
797 playback_rate_change_pending_ = true; | 773 playback_rate_change_pending_ = true; |
798 return; | 774 return; |
799 } | 775 } |
800 | 776 |
801 { | 777 { |
802 base::AutoLock auto_lock(lock_); | 778 base::AutoLock auto_lock(lock_); |
803 clock_->SetPlaybackRate(playback_rate); | 779 clock_->SetPlaybackRate(playback_rate); |
804 } | 780 } |
805 | 781 |
806 // Notify |pipeline_filter_| if it has been initialized. If initialization | 782 // These will get set after initialization completes in case playback rate is |
807 // hasn't completed yet, the playback rate will be set when initialization | 783 // set prior to initialization. |
808 // completes. | 784 if (demuxer_) |
809 if (pipeline_filter_) { | |
810 demuxer_->SetPlaybackRate(playback_rate); | 785 demuxer_->SetPlaybackRate(playback_rate); |
811 pipeline_filter_->SetPlaybackRate(playback_rate); | 786 if (audio_renderer_) |
812 | 787 audio_renderer_->SetPlaybackRate(playback_rate_); |
813 if (audio_renderer_) | 788 if (video_renderer_) |
814 audio_renderer_->SetPlaybackRate(playback_rate_); | 789 video_renderer_->SetPlaybackRate(playback_rate_); |
815 } | |
816 } | 790 } |
817 | 791 |
818 void Pipeline::VolumeChangedTask(float volume) { | 792 void Pipeline::VolumeChangedTask(float volume) { |
819 DCHECK(message_loop_->BelongsToCurrentThread()); | 793 DCHECK(message_loop_->BelongsToCurrentThread()); |
820 if (!running_ || tearing_down_) | 794 if (!running_ || tearing_down_) |
821 return; | 795 return; |
822 | 796 |
823 if (audio_renderer_) | 797 if (audio_renderer_) |
824 audio_renderer_->SetVolume(volume); | 798 audio_renderer_->SetVolume(volume); |
825 } | 799 } |
(...skipping 27 matching lines...) Expand all Loading... |
853 | 827 |
854 // Kick off seeking! | 828 // Kick off seeking! |
855 { | 829 { |
856 base::AutoLock auto_lock(lock_); | 830 base::AutoLock auto_lock(lock_); |
857 if (clock_->IsPlaying()) | 831 if (clock_->IsPlaying()) |
858 clock_->Pause(); | 832 clock_->Pause(); |
859 } | 833 } |
860 DoPause(base::Bind(&Pipeline::OnFilterStateTransition, this)); | 834 DoPause(base::Bind(&Pipeline::OnFilterStateTransition, this)); |
861 } | 835 } |
862 | 836 |
863 void Pipeline::NotifyEndedTask() { | 837 void Pipeline::OnRendererEndedTask() { |
864 DCHECK(message_loop_->BelongsToCurrentThread()); | 838 DCHECK(message_loop_->BelongsToCurrentThread()); |
865 | 839 |
866 // We can only end if we were actually playing. | 840 // We can only end if we were actually playing. |
867 if (state_ != kStarted) { | 841 if (state_ != kStarted) { |
868 return; | 842 return; |
869 } | 843 } |
870 | 844 |
871 DCHECK(audio_renderer_ || video_renderer_); | 845 DCHECK(audio_renderer_ || video_renderer_); |
872 | 846 |
873 // Make sure every extant renderer has ended. | 847 // Make sure every extant renderer has ended. |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1020 break; | 994 break; |
1021 // default: intentionally left out to force new states to cause compiler | 995 // default: intentionally left out to force new states to cause compiler |
1022 // errors. | 996 // errors. |
1023 }; | 997 }; |
1024 } | 998 } |
1025 | 999 |
1026 void Pipeline::FinishDestroyingFiltersTask() { | 1000 void Pipeline::FinishDestroyingFiltersTask() { |
1027 DCHECK(message_loop_->BelongsToCurrentThread()); | 1001 DCHECK(message_loop_->BelongsToCurrentThread()); |
1028 DCHECK(IsPipelineStopped()); | 1002 DCHECK(IsPipelineStopped()); |
1029 | 1003 |
1030 // Clear filter references. | |
1031 audio_renderer_ = NULL; | 1004 audio_renderer_ = NULL; |
1032 video_renderer_ = NULL; | 1005 video_renderer_ = NULL; |
1033 demuxer_ = NULL; | 1006 demuxer_ = NULL; |
1034 | 1007 |
1035 pipeline_filter_ = NULL; | |
1036 | |
1037 if (error_caused_teardown_ && !IsPipelineOk() && !error_cb_.is_null()) | 1008 if (error_caused_teardown_ && !IsPipelineOk() && !error_cb_.is_null()) |
1038 error_cb_.Run(status_); | 1009 error_cb_.Run(status_); |
1039 | 1010 |
1040 if (stop_pending_) { | 1011 if (stop_pending_) { |
1041 stop_pending_ = false; | 1012 stop_pending_ = false; |
1042 ResetState(); | 1013 ResetState(); |
1043 // Notify the client that stopping has finished. | 1014 // Notify the client that stopping has finished. |
1044 base::ResetAndReturn(&stop_cb_).Run(); | 1015 base::ResetAndReturn(&stop_cb_).Run(); |
1045 } | 1016 } |
1046 | 1017 |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1149 if (!audio_renderer_) { | 1120 if (!audio_renderer_) { |
1150 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 1121 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); |
1151 return false; | 1122 return false; |
1152 } | 1123 } |
1153 | 1124 |
1154 audio_renderer_->Initialize( | 1125 audio_renderer_->Initialize( |
1155 decoder, | 1126 decoder, |
1156 base::Bind(&Pipeline::OnFilterInitialize, this), | 1127 base::Bind(&Pipeline::OnFilterInitialize, this), |
1157 base::Bind(&Pipeline::OnAudioUnderflow, this), | 1128 base::Bind(&Pipeline::OnAudioUnderflow, this), |
1158 base::Bind(&Pipeline::OnAudioTimeUpdate, this), | 1129 base::Bind(&Pipeline::OnAudioTimeUpdate, this), |
1159 base::Bind(&Pipeline::NotifyEnded, this), | 1130 base::Bind(&Pipeline::OnRendererEnded, this), |
1160 base::Bind(&Pipeline::OnAudioDisabled, this), | 1131 base::Bind(&Pipeline::OnAudioDisabled, this), |
1161 base::Bind(&Pipeline::SetError, this)); | 1132 base::Bind(&Pipeline::SetError, this)); |
1162 return true; | 1133 return true; |
1163 } | 1134 } |
1164 | 1135 |
1165 bool Pipeline::InitializeVideoRenderer( | 1136 bool Pipeline::InitializeVideoRenderer( |
1166 const scoped_refptr<VideoDecoder>& decoder) { | 1137 const scoped_refptr<VideoDecoder>& decoder) { |
1167 DCHECK(message_loop_->BelongsToCurrentThread()); | 1138 DCHECK(message_loop_->BelongsToCurrentThread()); |
1168 DCHECK(IsPipelineOk()); | 1139 DCHECK(IsPipelineOk()); |
1169 | 1140 |
1170 if (!decoder) | 1141 if (!decoder) |
1171 return false; | 1142 return false; |
1172 | 1143 |
1173 filter_collection_->SelectVideoRenderer( | 1144 filter_collection_->SelectVideoRenderer(&video_renderer_); |
1174 &pipeline_init_state_->video_renderer); | 1145 if (!video_renderer_) { |
1175 if (!pipeline_init_state_->video_renderer) { | |
1176 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 1146 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); |
1177 return false; | 1147 return false; |
1178 } | 1148 } |
1179 | 1149 |
1180 pipeline_init_state_->composite->AddFilter( | 1150 video_renderer_->Initialize( |
1181 pipeline_init_state_->video_renderer); | |
1182 | |
1183 pipeline_init_state_->video_renderer->Initialize( | |
1184 decoder, | 1151 decoder, |
1185 base::Bind(&Pipeline::OnFilterInitialize, this), | 1152 base::Bind(&Pipeline::OnFilterInitialize, this), |
1186 base::Bind(&Pipeline::OnUpdateStatistics, this), | 1153 base::Bind(&Pipeline::OnUpdateStatistics, this), |
1187 base::Bind(&Pipeline::OnVideoTimeUpdate, this)); | 1154 base::Bind(&Pipeline::OnVideoTimeUpdate, this), |
1188 | 1155 base::Bind(&Pipeline::OnNaturalVideoSizeChanged, this), |
1189 video_renderer_ = pipeline_init_state_->video_renderer; | 1156 base::Bind(&Pipeline::OnRendererEnded, this), |
| 1157 base::Bind(&Pipeline::SetError, this), |
| 1158 base::Bind(&Pipeline::GetMediaTime, this), |
| 1159 base::Bind(&Pipeline::GetMediaDuration, this)); |
1190 return true; | 1160 return true; |
1191 } | 1161 } |
1192 | 1162 |
1193 void Pipeline::TearDownPipeline() { | 1163 void Pipeline::TearDownPipeline() { |
1194 DCHECK(message_loop_->BelongsToCurrentThread()); | 1164 DCHECK(message_loop_->BelongsToCurrentThread()); |
1195 DCHECK_NE(kStopped, state_); | 1165 DCHECK_NE(kStopped, state_); |
1196 | 1166 |
1197 DCHECK(!tearing_down_ || // Teardown on Stop(). | 1167 DCHECK(!tearing_down_ || // Teardown on Stop(). |
1198 (tearing_down_ && error_caused_teardown_) || // Teardown on error. | 1168 (tearing_down_ && error_caused_teardown_) || // Teardown on error. |
1199 (tearing_down_ && stop_pending_)); // Stop during teardown by error. | 1169 (tearing_down_ && stop_pending_)); // Stop during teardown by error. |
(...skipping 10 matching lines...) Expand all Loading... |
1210 message_loop_->PostTask(FROM_HERE, base::Bind( | 1180 message_loop_->PostTask(FROM_HERE, base::Bind( |
1211 &Pipeline::FinishDestroyingFiltersTask, this)); | 1181 &Pipeline::FinishDestroyingFiltersTask, this)); |
1212 break; | 1182 break; |
1213 | 1183 |
1214 case kInitDemuxer: | 1184 case kInitDemuxer: |
1215 case kInitAudioDecoder: | 1185 case kInitAudioDecoder: |
1216 case kInitAudioRenderer: | 1186 case kInitAudioRenderer: |
1217 case kInitVideoDecoder: | 1187 case kInitVideoDecoder: |
1218 case kInitVideoRenderer: | 1188 case kInitVideoRenderer: |
1219 // Make it look like initialization was successful. | 1189 // Make it look like initialization was successful. |
1220 pipeline_filter_ = pipeline_init_state_->composite; | 1190 filter_collection_.reset(); |
1221 pipeline_init_state_.reset(); | 1191 pipeline_init_state_.reset(); |
1222 filter_collection_.reset(); | |
1223 | 1192 |
1224 SetState(kStopping); | 1193 SetState(kStopping); |
1225 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); | 1194 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); |
1226 | 1195 |
1227 FinishInitialization(); | 1196 FinishInitialization(); |
1228 break; | 1197 break; |
1229 | 1198 |
1230 case kPausing: | 1199 case kPausing: |
1231 case kSeeking: | 1200 case kSeeking: |
1232 case kFlushing: | 1201 case kFlushing: |
(...skipping 30 matching lines...) Expand all Loading... |
1263 scoped_ptr<std::queue<PipelineStatusCBFunc> > status_cbs( | 1232 scoped_ptr<std::queue<PipelineStatusCBFunc> > status_cbs( |
1264 new std::queue<PipelineStatusCBFunc>()); | 1233 new std::queue<PipelineStatusCBFunc>()); |
1265 | 1234 |
1266 if (!skip_demuxer_seek) | 1235 if (!skip_demuxer_seek) |
1267 status_cbs->push(base::Bind(&Demuxer::Seek, demuxer_, seek_timestamp)); | 1236 status_cbs->push(base::Bind(&Demuxer::Seek, demuxer_, seek_timestamp)); |
1268 | 1237 |
1269 if (audio_renderer_) | 1238 if (audio_renderer_) |
1270 status_cbs->push(base::Bind( | 1239 status_cbs->push(base::Bind( |
1271 &AudioRenderer::Seek, audio_renderer_, seek_timestamp)); | 1240 &AudioRenderer::Seek, audio_renderer_, seek_timestamp)); |
1272 | 1241 |
1273 if (pipeline_filter_) | 1242 if (video_renderer_) |
1274 status_cbs->push(base::Bind( | 1243 status_cbs->push(base::Bind( |
1275 &Filter::Seek, pipeline_filter_, seek_timestamp)); | 1244 &VideoRenderer::Seek, video_renderer_, seek_timestamp)); |
1276 | 1245 |
1277 RunInSeriesWithStatus(status_cbs.Pass(), base::Bind( | 1246 RunInSeriesWithStatus(status_cbs.Pass(), base::Bind( |
1278 &Pipeline::ReportStatus, this, done_cb)); | 1247 &Pipeline::ReportStatus, this, done_cb)); |
1279 } | 1248 } |
1280 | 1249 |
1281 void Pipeline::OnAudioUnderflow() { | 1250 void Pipeline::OnAudioUnderflow() { |
1282 if (!message_loop_->BelongsToCurrentThread()) { | 1251 if (!message_loop_->BelongsToCurrentThread()) { |
1283 message_loop_->PostTask(FROM_HERE, base::Bind( | 1252 message_loop_->PostTask(FROM_HERE, base::Bind( |
1284 &Pipeline::OnAudioUnderflow, this)); | 1253 &Pipeline::OnAudioUnderflow, this)); |
1285 return; | 1254 return; |
1286 } | 1255 } |
1287 | 1256 |
1288 if (state_ != kStarted) | 1257 if (state_ != kStarted) |
1289 return; | 1258 return; |
1290 | 1259 |
1291 if (audio_renderer_) | 1260 if (audio_renderer_) |
1292 audio_renderer_->ResumeAfterUnderflow(true); | 1261 audio_renderer_->ResumeAfterUnderflow(true); |
1293 } | 1262 } |
1294 | 1263 |
1295 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { | 1264 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { |
1296 lock_.AssertAcquired(); | 1265 lock_.AssertAcquired(); |
1297 if (!waiting_for_clock_update_) | 1266 if (!waiting_for_clock_update_) |
1298 return; | 1267 return; |
1299 | 1268 |
1300 waiting_for_clock_update_ = false; | 1269 waiting_for_clock_update_ = false; |
1301 clock_->Play(); | 1270 clock_->Play(); |
1302 } | 1271 } |
1303 | 1272 |
1304 } // namespace media | 1273 } // namespace media |
OLD | NEW |