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/clock.h" | 21 #include "media/base/clock.h" |
21 #include "media/base/composite_filter.h" | 22 #include "media/base/composite_filter.h" |
22 #include "media/base/filter_collection.h" | 23 #include "media/base/filter_collection.h" |
23 #include "media/base/media_log.h" | 24 #include "media/base/media_log.h" |
24 #include "media/base/video_decoder.h" | 25 #include "media/base/video_decoder.h" |
25 #include "media/base/video_renderer.h" | 26 #include "media/base/video_renderer.h" |
26 | 27 |
27 using base::TimeDelta; | 28 using base::TimeDelta; |
28 | 29 |
29 namespace media { | 30 namespace media { |
(...skipping 27 matching lines...) Expand all Loading... | |
57 | 58 |
58 media::PipelineStatus PipelineStatusNotification::status() { | 59 media::PipelineStatus PipelineStatusNotification::status() { |
59 base::AutoLock auto_lock(lock_); | 60 base::AutoLock auto_lock(lock_); |
60 DCHECK(notified_); | 61 DCHECK(notified_); |
61 return status_; | 62 return status_; |
62 } | 63 } |
63 | 64 |
64 struct Pipeline::PipelineInitState { | 65 struct Pipeline::PipelineInitState { |
65 scoped_refptr<AudioDecoder> audio_decoder; | 66 scoped_refptr<AudioDecoder> audio_decoder; |
66 scoped_refptr<VideoDecoder> video_decoder; | 67 scoped_refptr<VideoDecoder> video_decoder; |
67 scoped_refptr<AudioRenderer> audio_renderer; | |
68 scoped_refptr<VideoRenderer> video_renderer; | 68 scoped_refptr<VideoRenderer> video_renderer; |
69 scoped_refptr<CompositeFilter> composite; | 69 scoped_refptr<CompositeFilter> composite; |
70 }; | 70 }; |
71 | 71 |
72 Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log) | 72 Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log) |
73 : message_loop_(message_loop->message_loop_proxy()), | 73 : message_loop_(message_loop->message_loop_proxy()), |
74 media_log_(media_log), | 74 media_log_(media_log), |
75 clock_(new Clock(&base::Time::Now)), | 75 clock_(new Clock(&base::Time::Now)), |
76 waiting_for_clock_update_(false), | 76 waiting_for_clock_update_(false), |
77 state_(kCreated), | 77 state_(kCreated), |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
383 TimeDelta Pipeline::GetTime() const { | 383 TimeDelta Pipeline::GetTime() const { |
384 DCHECK(IsRunning()); | 384 DCHECK(IsRunning()); |
385 return GetCurrentTime(); | 385 return GetCurrentTime(); |
386 } | 386 } |
387 | 387 |
388 TimeDelta Pipeline::GetDuration() const { | 388 TimeDelta Pipeline::GetDuration() const { |
389 DCHECK(IsRunning()); | 389 DCHECK(IsRunning()); |
390 return GetMediaDuration(); | 390 return GetMediaDuration(); |
391 } | 391 } |
392 | 392 |
393 void Pipeline::OnAudioDisabled() { | |
394 DCHECK(IsRunning()); | |
395 message_loop_->PostTask(FROM_HERE, base::Bind( | |
396 &Pipeline::AudioDisabledTask, this)); | |
397 media_log_->AddEvent( | |
398 media_log_->CreateEvent(MediaLogEvent::AUDIO_RENDERER_DISABLED)); | |
399 } | |
400 | |
393 void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) { | 401 void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) { |
394 DCHECK(time <= max_time); | 402 DCHECK(time <= max_time); |
395 DCHECK(IsRunning()); | 403 DCHECK(IsRunning()); |
396 base::AutoLock auto_lock(lock_); | 404 base::AutoLock auto_lock(lock_); |
397 | 405 |
398 if (!has_audio_) | 406 if (!has_audio_) |
399 return; | 407 return; |
400 if (waiting_for_clock_update_ && time < clock_->Elapsed()) | 408 if (waiting_for_clock_update_ && time < clock_->Elapsed()) |
401 return; | 409 return; |
402 | 410 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
453 // Since the byte->time calculation is approximate, fudge the beginning & | 461 // Since the byte->time calculation is approximate, fudge the beginning & |
454 // ending areas to look better. | 462 // ending areas to look better. |
455 TimeDelta epsilon = clock_->Duration() / 100; | 463 TimeDelta epsilon = clock_->Duration() / 100; |
456 if (time_offset < epsilon) | 464 if (time_offset < epsilon) |
457 return TimeDelta(); | 465 return TimeDelta(); |
458 if (time_offset + epsilon > clock_->Duration()) | 466 if (time_offset + epsilon > clock_->Duration()) |
459 return clock_->Duration(); | 467 return clock_->Duration(); |
460 return time_offset; | 468 return time_offset; |
461 } | 469 } |
462 | 470 |
471 void Pipeline::DoPause(const base::Closure& done_cb) { | |
472 scoped_ptr<std::queue<ClosureCB> > closures(new std::queue<ClosureCB>); | |
473 | |
474 if (audio_renderer_) | |
475 closures->push(base::Bind(&AudioRenderer::Pause, audio_renderer_)); | |
476 | |
477 if (pipeline_filter_) | |
478 closures->push(base::Bind(&Filter::Pause, pipeline_filter_)); | |
479 | |
480 RunInSeries(closures.Pass(), done_cb); | |
481 } | |
482 | |
483 void Pipeline::DoFlush(const base::Closure& done_cb) { | |
484 scoped_ptr<std::queue<ClosureCB> > closures(new std::queue<ClosureCB>); | |
485 | |
486 if (audio_renderer_) | |
487 closures->push(base::Bind(&AudioRenderer::Flush, audio_renderer_)); | |
488 | |
489 if (pipeline_filter_) | |
490 closures->push(base::Bind(&Filter::Flush, pipeline_filter_)); | |
491 | |
492 RunInParallel(closures.Pass(), done_cb); | |
493 } | |
494 | |
495 void Pipeline::DoPlay(const base::Closure& done_cb) { | |
496 scoped_ptr<std::queue<ClosureCB> > closures(new std::queue<ClosureCB>); | |
497 | |
498 if (audio_renderer_) | |
499 closures->push(base::Bind(&AudioRenderer::Play, audio_renderer_)); | |
500 | |
501 if (pipeline_filter_) | |
502 closures->push(base::Bind(&Filter::Play, pipeline_filter_)); | |
503 | |
504 RunInSeries(closures.Pass(), done_cb); | |
505 } | |
506 | |
507 void Pipeline::DoStop(const base::Closure& done_cb) { | |
508 scoped_ptr<std::queue<ClosureCB> > closures(new std::queue<ClosureCB>); | |
509 | |
510 if (demuxer_) | |
511 closures->push(base::Bind(&Demuxer::Stop, demuxer_)); | |
512 | |
513 if (audio_renderer_) | |
514 closures->push(base::Bind(&AudioRenderer::Stop, audio_renderer_)); | |
515 | |
516 if (pipeline_filter_) | |
517 closures->push(base::Bind(&Filter::Stop, pipeline_filter_)); | |
518 | |
519 RunInSeries(closures.Pass(), done_cb); | |
520 } | |
521 | |
463 void Pipeline::AddBufferedByteRange(int64 start, int64 end) { | 522 void Pipeline::AddBufferedByteRange(int64 start, int64 end) { |
464 DCHECK(IsRunning()); | 523 DCHECK(IsRunning()); |
465 base::AutoLock auto_lock(lock_); | 524 base::AutoLock auto_lock(lock_); |
466 buffered_byte_ranges_.Add(start, end); | 525 buffered_byte_ranges_.Add(start, end); |
467 did_loading_progress_ = true; | 526 did_loading_progress_ = true; |
468 } | 527 } |
469 | 528 |
470 void Pipeline::AddBufferedTimeRange(base::TimeDelta start, | 529 void Pipeline::AddBufferedTimeRange(base::TimeDelta start, |
471 base::TimeDelta end) { | 530 base::TimeDelta end) { |
472 DCHECK(IsRunning()); | 531 DCHECK(IsRunning()); |
(...skipping 11 matching lines...) Expand all Loading... | |
484 natural_size_ = size; | 543 natural_size_ = size; |
485 } | 544 } |
486 | 545 |
487 void Pipeline::NotifyEnded() { | 546 void Pipeline::NotifyEnded() { |
488 DCHECK(IsRunning()); | 547 DCHECK(IsRunning()); |
489 message_loop_->PostTask(FROM_HERE, base::Bind( | 548 message_loop_->PostTask(FROM_HERE, base::Bind( |
490 &Pipeline::NotifyEndedTask, this)); | 549 &Pipeline::NotifyEndedTask, this)); |
491 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED)); | 550 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED)); |
492 } | 551 } |
493 | 552 |
494 void Pipeline::DisableAudioRenderer() { | |
495 DCHECK(IsRunning()); | |
496 | |
497 // Disable renderer on the message loop. | |
498 message_loop_->PostTask(FROM_HERE, base::Bind( | |
499 &Pipeline::DisableAudioRendererTask, this)); | |
500 media_log_->AddEvent( | |
501 media_log_->CreateEvent(MediaLogEvent::AUDIO_RENDERER_DISABLED)); | |
502 } | |
503 | |
504 // Called from any thread. | 553 // Called from any thread. |
505 void Pipeline::OnFilterInitialize(PipelineStatus status) { | 554 void Pipeline::OnFilterInitialize(PipelineStatus status) { |
506 // Continue the initialize task by proceeding to the next stage. | 555 // Continue the initialize task by proceeding to the next stage. |
507 message_loop_->PostTask(FROM_HERE, base::Bind( | 556 message_loop_->PostTask(FROM_HERE, base::Bind( |
508 &Pipeline::InitializeTask, this, status)); | 557 &Pipeline::InitializeTask, this, status)); |
509 } | 558 } |
510 | 559 |
511 // Called from any thread. | 560 // Called from any thread. |
512 void Pipeline::OnFilterStateTransition() { | 561 void Pipeline::OnFilterStateTransition() { |
513 message_loop_->PostTask(FROM_HERE, base::Bind( | 562 message_loop_->PostTask(FROM_HERE, base::Bind( |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
656 // Initialization was successful, we are now considered paused, so it's safe | 705 // Initialization was successful, we are now considered paused, so it's safe |
657 // to set the initial playback rate and volume. | 706 // to set the initial playback rate and volume. |
658 PlaybackRateChangedTask(GetPlaybackRate()); | 707 PlaybackRateChangedTask(GetPlaybackRate()); |
659 VolumeChangedTask(GetVolume()); | 708 VolumeChangedTask(GetVolume()); |
660 | 709 |
661 // Fire a seek request to get the renderers to preroll. We don't need to | 710 // Fire a seek request to get the renderers to preroll. We don't need to |
662 // tell the demuxer to seek since it should already be at the start. | 711 // tell the demuxer to seek since it should already be at the start. |
663 seek_pending_ = true; | 712 seek_pending_ = true; |
664 SetState(kSeeking); | 713 SetState(kSeeking); |
665 seek_timestamp_ = demuxer_->GetStartTime(); | 714 seek_timestamp_ = demuxer_->GetStartTime(); |
666 OnDemuxerSeekDone(seek_timestamp_, PIPELINE_OK); | 715 OnDemuxerSeekDone( |
716 base::Bind(&Pipeline::OnFilterStateTransitionWithStatus, this), | |
717 seek_timestamp_, PIPELINE_OK); | |
667 } | 718 } |
668 } | 719 } |
669 | 720 |
670 // This method is called as a result of the client calling Pipeline::Stop() or | 721 // This method is called as a result of the client calling Pipeline::Stop() or |
671 // as the result of an error condition. | 722 // as the result of an error condition. |
672 // We stop the filters in the reverse order. | 723 // We stop the filters in the reverse order. |
673 // | 724 // |
674 // TODO(scherkus): beware! this can get posted multiple times since we post | 725 // TODO(scherkus): beware! this can get posted multiple times since we post |
675 // Stop() tasks even if we've already stopped. Perhaps this should no-op for | 726 // Stop() tasks even if we've already stopped. Perhaps this should no-op for |
676 // additional calls, however most of this logic will be changing. | 727 // additional calls, however most of this logic will be changing. |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
745 | 796 |
746 { | 797 { |
747 base::AutoLock auto_lock(lock_); | 798 base::AutoLock auto_lock(lock_); |
748 clock_->SetPlaybackRate(playback_rate); | 799 clock_->SetPlaybackRate(playback_rate); |
749 } | 800 } |
750 | 801 |
751 // Notify |pipeline_filter_| if it has been initialized. If initialization | 802 // Notify |pipeline_filter_| if it has been initialized. If initialization |
752 // hasn't completed yet, the playback rate will be set when initialization | 803 // hasn't completed yet, the playback rate will be set when initialization |
753 // completes. | 804 // completes. |
754 if (pipeline_filter_) { | 805 if (pipeline_filter_) { |
755 DCHECK(demuxer_); | |
756 demuxer_->SetPlaybackRate(playback_rate); | 806 demuxer_->SetPlaybackRate(playback_rate); |
757 pipeline_filter_->SetPlaybackRate(playback_rate); | 807 pipeline_filter_->SetPlaybackRate(playback_rate); |
808 | |
809 if (audio_renderer_) | |
810 audio_renderer_->SetPlaybackRate(playback_rate_); | |
758 } | 811 } |
759 } | 812 } |
760 | 813 |
761 void Pipeline::VolumeChangedTask(float volume) { | 814 void Pipeline::VolumeChangedTask(float volume) { |
762 DCHECK(message_loop_->BelongsToCurrentThread()); | 815 DCHECK(message_loop_->BelongsToCurrentThread()); |
763 if (!running_ || tearing_down_) | 816 if (!running_ || tearing_down_) |
764 return; | 817 return; |
765 | 818 |
766 if (audio_renderer_) | 819 if (audio_renderer_) |
767 audio_renderer_->SetVolume(volume); | 820 audio_renderer_->SetVolume(volume); |
(...skipping 25 matching lines...) Expand all Loading... | |
793 SetState(kPausing); | 846 SetState(kPausing); |
794 seek_timestamp_ = std::max(time, demuxer_->GetStartTime()); | 847 seek_timestamp_ = std::max(time, demuxer_->GetStartTime()); |
795 seek_cb_ = seek_cb; | 848 seek_cb_ = seek_cb; |
796 | 849 |
797 // Kick off seeking! | 850 // Kick off seeking! |
798 { | 851 { |
799 base::AutoLock auto_lock(lock_); | 852 base::AutoLock auto_lock(lock_); |
800 if (clock_->IsPlaying()) | 853 if (clock_->IsPlaying()) |
801 clock_->Pause(); | 854 clock_->Pause(); |
802 } | 855 } |
803 pipeline_filter_->Pause( | 856 DoPause(base::Bind(&Pipeline::OnFilterStateTransition, this)); |
804 base::Bind(&Pipeline::OnFilterStateTransition, this)); | |
805 } | 857 } |
806 | 858 |
807 void Pipeline::NotifyEndedTask() { | 859 void Pipeline::NotifyEndedTask() { |
808 DCHECK(message_loop_->BelongsToCurrentThread()); | 860 DCHECK(message_loop_->BelongsToCurrentThread()); |
809 | 861 |
810 // We can only end if we were actually playing. | 862 // We can only end if we were actually playing. |
811 if (state_ != kStarted) { | 863 if (state_ != kStarted) { |
812 return; | 864 return; |
813 } | 865 } |
814 | 866 |
(...skipping 19 matching lines...) Expand all Loading... | |
834 // Transition to ended, executing the callback if present. | 886 // Transition to ended, executing the callback if present. |
835 SetState(kEnded); | 887 SetState(kEnded); |
836 { | 888 { |
837 base::AutoLock auto_lock(lock_); | 889 base::AutoLock auto_lock(lock_); |
838 clock_->EndOfStream(); | 890 clock_->EndOfStream(); |
839 } | 891 } |
840 | 892 |
841 ReportStatus(ended_cb_, status_); | 893 ReportStatus(ended_cb_, status_); |
842 } | 894 } |
843 | 895 |
844 void Pipeline::DisableAudioRendererTask() { | 896 void Pipeline::AudioDisabledTask() { |
845 DCHECK(message_loop_->BelongsToCurrentThread()); | 897 DCHECK(message_loop_->BelongsToCurrentThread()); |
846 | 898 |
847 base::AutoLock auto_lock(lock_); | 899 base::AutoLock auto_lock(lock_); |
848 has_audio_ = false; | 900 has_audio_ = false; |
849 audio_disabled_ = true; | 901 audio_disabled_ = true; |
850 | 902 |
851 // Notify our demuxer that we're no longer rendering audio. | 903 // Notify our demuxer that we're no longer rendering audio. |
852 demuxer_->OnAudioRendererDisabled(); | 904 demuxer_->OnAudioRendererDisabled(); |
853 | 905 |
854 // Start clock since there is no more audio to | 906 // Start clock since there is no more audio to |
(...skipping 26 matching lines...) Expand all Loading... | |
881 // to the next state if needed. | 933 // to the next state if needed. |
882 SetState(FindNextState(state_)); | 934 SetState(FindNextState(state_)); |
883 if (state_ == kSeeking) { | 935 if (state_ == kSeeking) { |
884 base::AutoLock auto_lock(lock_); | 936 base::AutoLock auto_lock(lock_); |
885 clock_->SetTime(seek_timestamp_, seek_timestamp_); | 937 clock_->SetTime(seek_timestamp_, seek_timestamp_); |
886 } | 938 } |
887 | 939 |
888 // Carry out the action for the current state. | 940 // Carry out the action for the current state. |
889 if (TransientState(state_)) { | 941 if (TransientState(state_)) { |
890 if (state_ == kPausing) { | 942 if (state_ == kPausing) { |
891 pipeline_filter_->Pause( | 943 DoPause(base::Bind(&Pipeline::OnFilterStateTransition, this)); |
892 base::Bind(&Pipeline::OnFilterStateTransition, this)); | |
893 } else if (state_ == kFlushing) { | 944 } else if (state_ == kFlushing) { |
894 pipeline_filter_->Flush( | 945 DoFlush(base::Bind(&Pipeline::OnFilterStateTransition, this)); |
895 base::Bind(&Pipeline::OnFilterStateTransition, this)); | |
896 } else if (state_ == kSeeking) { | 946 } else if (state_ == kSeeking) { |
897 DoSeek(seek_timestamp_); | 947 DoSeek(base::Bind(&Pipeline::OnFilterStateTransitionWithStatus, this), |
948 seek_timestamp_); | |
898 } else if (state_ == kStarting) { | 949 } else if (state_ == kStarting) { |
899 pipeline_filter_->Play( | 950 DoPlay(base::Bind(&Pipeline::OnFilterStateTransition, this)); |
900 base::Bind(&Pipeline::OnFilterStateTransition, this)); | |
901 } else if (state_ == kStopping) { | 951 } else if (state_ == kStopping) { |
902 DoStop(base::Bind(&Pipeline::OnFilterStateTransition, this)); | 952 DoStop(base::Bind(&Pipeline::OnFilterStateTransition, this)); |
903 } else { | 953 } else { |
904 NOTREACHED() << "Unexpected state: " << state_; | 954 NOTREACHED() << "Unexpected state: " << state_; |
905 } | 955 } |
906 } else if (state_ == kStarted) { | 956 } else if (state_ == kStarted) { |
907 FinishInitialization(); | 957 FinishInitialization(); |
908 | 958 |
909 // Finally, complete the seek. | 959 // Finally, complete the seek. |
910 seek_pending_ = false; | 960 seek_pending_ = false; |
(...skipping 25 matching lines...) Expand all Loading... | |
936 | 986 |
937 void Pipeline::TeardownStateTransitionTask() { | 987 void Pipeline::TeardownStateTransitionTask() { |
938 DCHECK(IsPipelineTearingDown()); | 988 DCHECK(IsPipelineTearingDown()); |
939 switch (state_) { | 989 switch (state_) { |
940 case kStopping: | 990 case kStopping: |
941 SetState(error_caused_teardown_ ? kError : kStopped); | 991 SetState(error_caused_teardown_ ? kError : kStopped); |
942 FinishDestroyingFiltersTask(); | 992 FinishDestroyingFiltersTask(); |
943 break; | 993 break; |
944 case kPausing: | 994 case kPausing: |
945 SetState(kFlushing); | 995 SetState(kFlushing); |
946 pipeline_filter_->Flush( | 996 DoFlush(base::Bind(&Pipeline::OnTeardownStateTransition, this)); |
947 base::Bind(&Pipeline::OnTeardownStateTransition, this)); | |
948 break; | 997 break; |
949 case kFlushing: | 998 case kFlushing: |
950 SetState(kStopping); | 999 SetState(kStopping); |
951 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); | 1000 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); |
952 break; | 1001 break; |
953 | 1002 |
954 case kCreated: | 1003 case kCreated: |
955 case kError: | 1004 case kError: |
956 case kInitDemuxer: | 1005 case kInitDemuxer: |
957 case kInitAudioDecoder: | 1006 case kInitAudioDecoder: |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1085 } | 1134 } |
1086 | 1135 |
1087 bool Pipeline::InitializeAudioRenderer( | 1136 bool Pipeline::InitializeAudioRenderer( |
1088 const scoped_refptr<AudioDecoder>& decoder) { | 1137 const scoped_refptr<AudioDecoder>& decoder) { |
1089 DCHECK(message_loop_->BelongsToCurrentThread()); | 1138 DCHECK(message_loop_->BelongsToCurrentThread()); |
1090 DCHECK(IsPipelineOk()); | 1139 DCHECK(IsPipelineOk()); |
1091 | 1140 |
1092 if (!decoder) | 1141 if (!decoder) |
1093 return false; | 1142 return false; |
1094 | 1143 |
1095 filter_collection_->SelectAudioRenderer( | 1144 filter_collection_->SelectAudioRenderer(&audio_renderer_); |
1096 &pipeline_init_state_->audio_renderer); | 1145 if (!audio_renderer_) { |
1097 if (!pipeline_init_state_->audio_renderer) { | |
1098 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 1146 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); |
1099 return false; | 1147 return false; |
1100 } | 1148 } |
1101 | 1149 |
1102 pipeline_init_state_->composite->AddFilter( | 1150 audio_renderer_->Initialize( |
1103 pipeline_init_state_->audio_renderer); | |
1104 | |
1105 pipeline_init_state_->audio_renderer->Initialize( | |
1106 decoder, | 1151 decoder, |
1107 base::Bind(&Pipeline::OnFilterInitialize, this), | 1152 base::Bind(&Pipeline::OnFilterInitialize, this), |
1108 base::Bind(&Pipeline::OnAudioUnderflow, this), | 1153 base::Bind(&Pipeline::OnAudioUnderflow, this), |
1109 base::Bind(&Pipeline::OnAudioTimeUpdate, this)); | 1154 base::Bind(&Pipeline::OnAudioTimeUpdate, this), |
1110 | 1155 base::Bind(&Pipeline::NotifyEnded, this), |
1111 audio_renderer_ = pipeline_init_state_->audio_renderer; | 1156 base::Bind(&Pipeline::OnAudioDisabled, this)); |
1112 return true; | 1157 return true; |
1113 } | 1158 } |
1114 | 1159 |
1115 bool Pipeline::InitializeVideoRenderer( | 1160 bool Pipeline::InitializeVideoRenderer( |
1116 const scoped_refptr<VideoDecoder>& decoder) { | 1161 const scoped_refptr<VideoDecoder>& decoder) { |
1117 DCHECK(message_loop_->BelongsToCurrentThread()); | 1162 DCHECK(message_loop_->BelongsToCurrentThread()); |
1118 DCHECK(IsPipelineOk()); | 1163 DCHECK(IsPipelineOk()); |
1119 | 1164 |
1120 if (!decoder) | 1165 if (!decoder) |
1121 return false; | 1166 return false; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1187 if (seek_pending_) { | 1232 if (seek_pending_) { |
1188 seek_pending_ = false; | 1233 seek_pending_ = false; |
1189 FinishInitialization(); | 1234 FinishInitialization(); |
1190 } | 1235 } |
1191 | 1236 |
1192 break; | 1237 break; |
1193 | 1238 |
1194 case kStarted: | 1239 case kStarted: |
1195 case kEnded: | 1240 case kEnded: |
1196 SetState(kPausing); | 1241 SetState(kPausing); |
1197 pipeline_filter_->Pause( | 1242 DoPause(base::Bind(&Pipeline::OnTeardownStateTransition, this)); |
1198 base::Bind(&Pipeline::OnTeardownStateTransition, this)); | |
1199 break; | 1243 break; |
1200 | 1244 |
1201 case kStopping: | 1245 case kStopping: |
1202 case kStopped: | 1246 case kStopped: |
1203 NOTREACHED() << "Unexpected state for teardown: " << state_; | 1247 NOTREACHED() << "Unexpected state for teardown: " << state_; |
1204 break; | 1248 break; |
1205 // default: intentionally left out to force new states to cause compiler | 1249 // default: intentionally left out to force new states to cause compiler |
1206 // errors. | 1250 // errors. |
1207 }; | 1251 }; |
1208 } | 1252 } |
1209 | 1253 |
1210 void Pipeline::DoStop(const base::Closure& callback) { | 1254 void Pipeline::DoSeek(const PipelineStatusCB& done_cb, |
1211 if (demuxer_) { | 1255 TimeDelta seek_timestamp) { |
1212 demuxer_->Stop(base::Bind( | 1256 demuxer_->Seek(seek_timestamp, base::Bind( |
acolwell GONE FROM CHROMIUM
2012/07/19 00:58:18
It feels like you should be able to do the same th
scherkus (not reviewing)
2012/07/19 21:29:02
Done and using the power of Bind() we don't need t
| |
1213 &Pipeline::OnDemuxerStopDone, this, callback)); | 1257 &Pipeline::OnDemuxerSeekDone, this, done_cb, seek_timestamp)); |
1258 } | |
1259 | |
1260 void Pipeline::OnDemuxerSeekDone(const PipelineStatusCB& done_cb, | |
1261 TimeDelta seek_timestamp, | |
1262 PipelineStatus status) { | |
1263 if (!message_loop_->BelongsToCurrentThread()) { | |
1264 message_loop_->PostTask(FROM_HERE, base::Bind( | |
1265 &Pipeline::OnDemuxerSeekDone, this, done_cb, seek_timestamp, status)); | |
1214 return; | 1266 return; |
1215 } | 1267 } |
1216 | 1268 |
1217 OnDemuxerStopDone(callback); | 1269 if (status == PIPELINE_OK && audio_renderer_) { |
1218 } | 1270 audio_renderer_->Seek(seek_timestamp, base::Bind( |
1219 | 1271 &Pipeline::OnAudioRendererSeekDone, this, done_cb, seek_timestamp)); |
1220 void Pipeline::OnDemuxerStopDone(const base::Closure& callback) { | |
1221 if (!message_loop_->BelongsToCurrentThread()) { | |
1222 message_loop_->PostTask(FROM_HERE, base::Bind( | |
1223 &Pipeline::OnDemuxerStopDone, this, callback)); | |
1224 return; | 1272 return; |
1225 } | 1273 } |
1226 | 1274 |
1227 if (pipeline_filter_) { | 1275 OnAudioRendererSeekDone(done_cb, seek_timestamp, status); |
1228 pipeline_filter_->Stop(callback); | 1276 } |
1277 | |
1278 void Pipeline::OnAudioRendererSeekDone(const PipelineStatusCB& done_cb, | |
1279 base::TimeDelta seek_timestamp, | |
1280 PipelineStatus status) { | |
1281 if (!message_loop_->BelongsToCurrentThread()) { | |
1282 message_loop_->PostTask(FROM_HERE, base::Bind( | |
1283 &Pipeline::OnAudioRendererSeekDone, this, done_cb, seek_timestamp, | |
1284 status)); | |
1229 return; | 1285 return; |
1230 } | 1286 } |
1231 | 1287 |
1232 callback.Run(); | 1288 if (status == PIPELINE_OK && pipeline_filter_) { |
1233 } | 1289 pipeline_filter_->Seek(seek_timestamp, base::Bind( |
1234 | 1290 &Pipeline::OnPipelineFilterSeekDone, this, done_cb)); |
1235 void Pipeline::DoSeek(TimeDelta seek_timestamp) { | |
1236 demuxer_->Seek(seek_timestamp, base::Bind( | |
1237 &Pipeline::OnDemuxerSeekDone, this, seek_timestamp)); | |
1238 } | |
1239 | |
1240 void Pipeline::OnDemuxerSeekDone(TimeDelta seek_timestamp, | |
1241 PipelineStatus status) { | |
1242 if (!message_loop_->BelongsToCurrentThread()) { | |
1243 message_loop_->PostTask(FROM_HERE, base::Bind( | |
1244 &Pipeline::OnDemuxerSeekDone, this, seek_timestamp, status)); | |
1245 return; | 1291 return; |
1246 } | 1292 } |
1247 | 1293 |
1248 PipelineStatusCB done_cb = | 1294 OnPipelineFilterSeekDone(done_cb, status); |
1249 base::Bind(&Pipeline::OnFilterStateTransitionWithStatus, this); | 1295 } |
1250 | 1296 |
1251 if (status == PIPELINE_OK && pipeline_filter_) { | 1297 void Pipeline::OnPipelineFilterSeekDone(const PipelineStatusCB& done_cb, |
1252 pipeline_filter_->Seek(seek_timestamp, done_cb); | 1298 PipelineStatus status) { |
1299 if (!message_loop_->BelongsToCurrentThread()) { | |
1300 message_loop_->PostTask(FROM_HERE, base::Bind( | |
1301 &Pipeline::OnPipelineFilterSeekDone, this, done_cb, status)); | |
1253 return; | 1302 return; |
1254 } | 1303 } |
1255 | 1304 |
1256 ReportStatus(done_cb, status); | 1305 ReportStatus(done_cb, status); |
1257 } | 1306 } |
1258 | 1307 |
1259 void Pipeline::OnAudioUnderflow() { | 1308 void Pipeline::OnAudioUnderflow() { |
1260 if (!message_loop_->BelongsToCurrentThread()) { | 1309 if (!message_loop_->BelongsToCurrentThread()) { |
1261 message_loop_->PostTask(FROM_HERE, base::Bind( | 1310 message_loop_->PostTask(FROM_HERE, base::Bind( |
1262 &Pipeline::OnAudioUnderflow, this)); | 1311 &Pipeline::OnAudioUnderflow, this)); |
(...skipping 10 matching lines...) Expand all Loading... | |
1273 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { | 1322 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { |
1274 lock_.AssertAcquired(); | 1323 lock_.AssertAcquired(); |
1275 if (!waiting_for_clock_update_) | 1324 if (!waiting_for_clock_update_) |
1276 return; | 1325 return; |
1277 | 1326 |
1278 waiting_for_clock_update_ = false; | 1327 waiting_for_clock_update_ = false; |
1279 clock_->Play(); | 1328 clock_->Play(); |
1280 } | 1329 } |
1281 | 1330 |
1282 } // namespace media | 1331 } // namespace media |
OLD | NEW |