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" |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
54 while (!notified_) | 54 while (!notified_) |
55 cv_.Wait(); | 55 cv_.Wait(); |
56 } | 56 } |
57 | 57 |
58 media::PipelineStatus PipelineStatusNotification::status() { | 58 media::PipelineStatus PipelineStatusNotification::status() { |
59 base::AutoLock auto_lock(lock_); | 59 base::AutoLock auto_lock(lock_); |
60 DCHECK(notified_); | 60 DCHECK(notified_); |
61 return status_; | 61 return status_; |
62 } | 62 } |
63 | 63 |
64 struct Pipeline::PipelineInitState { | 64 struct Pipeline::PipelineInitState { |
scherkus (not reviewing)
2012/07/10 03:58:22
I think we can remove this entirely very soon
| |
65 scoped_refptr<AudioDecoder> audio_decoder; | 65 scoped_refptr<AudioDecoder> audio_decoder; |
66 scoped_refptr<VideoDecoder> video_decoder; | 66 scoped_refptr<VideoDecoder> video_decoder; |
67 scoped_refptr<AudioRenderer> audio_renderer; | |
68 scoped_refptr<VideoRenderer> video_renderer; | 67 scoped_refptr<VideoRenderer> video_renderer; |
69 scoped_refptr<CompositeFilter> composite; | 68 scoped_refptr<CompositeFilter> composite; |
acolwell GONE FROM CHROMIUM
2012/07/10 16:34:37
If this is only holding video_renderer now can we
scherkus (not reviewing)
2012/07/17 03:43:00
Not yet because we set pipeline_filter_ to composi
| |
70 }; | 69 }; |
71 | 70 |
72 Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log) | 71 Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log) |
73 : message_loop_(message_loop->message_loop_proxy()), | 72 : message_loop_(message_loop->message_loop_proxy()), |
74 media_log_(media_log), | 73 media_log_(media_log), |
75 clock_(new Clock(&base::Time::Now)), | 74 clock_(new Clock(&base::Time::Now)), |
76 waiting_for_clock_update_(false), | 75 waiting_for_clock_update_(false), |
77 state_(kCreated), | 76 state_(kCreated), |
78 creation_time_(base::Time::Now()) { | 77 creation_time_(base::Time::Now()) { |
79 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); | 78 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); |
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
447 // Since the byte->time calculation is approximate, fudge the beginning & | 446 // Since the byte->time calculation is approximate, fudge the beginning & |
448 // ending areas to look better. | 447 // ending areas to look better. |
449 TimeDelta epsilon = clock_->Duration() / 100; | 448 TimeDelta epsilon = clock_->Duration() / 100; |
450 if (time_offset < epsilon) | 449 if (time_offset < epsilon) |
451 return TimeDelta(); | 450 return TimeDelta(); |
452 if (time_offset + epsilon > clock_->Duration()) | 451 if (time_offset + epsilon > clock_->Duration()) |
453 return clock_->Duration(); | 452 return clock_->Duration(); |
454 return time_offset; | 453 return time_offset; |
455 } | 454 } |
456 | 455 |
456 void Pipeline::DoPause(const base::Closure& done_cb) { | |
scherkus (not reviewing)
2012/07/10 03:58:22
these DoXXX() methods essentially replicate Compos
acolwell GONE FROM CHROMIUM
2012/07/10 16:34:37
Wow. This is not as clean as I had hoped. I think
scherkus (not reviewing)
2012/07/17 03:43:00
I played around with this for an hour or so and it
| |
457 base::Closure do_pause = done_cb; | |
458 | |
459 if (pipeline_filter_) { | |
scherkus (not reviewing)
2012/07/10 03:58:22
note that pipeline_filter_ ~= video_renderer_ (it'
acolwell GONE FROM CHROMIUM
2012/07/10 16:34:37
Any reason we shouldn't rename pipeline_filter_ ->
scherkus (not reviewing)
2012/07/17 03:43:00
We have an actual video_renderer_ that we use for
| |
460 do_pause = base::Bind(&Pipeline::RunOnPipelineThread, this, do_pause); | |
461 do_pause = base::Bind(&Filter::Pause, pipeline_filter_, do_pause); | |
462 } | |
463 | |
464 if (audio_renderer_) { | |
465 do_pause = base::Bind(&Pipeline::RunOnPipelineThread, this, do_pause); | |
466 do_pause = base::Bind(&AudioRenderer::Pause, audio_renderer_, do_pause); | |
467 } | |
468 | |
469 do_pause.Run(); | |
470 } | |
471 | |
472 void Pipeline::DoFlush(const base::Closure& done_cb) { | |
Ami GONE FROM CHROMIUM
2012/07/10 17:16:00
Before this CL CompositeFilter::Flush() was parall
scherkus (not reviewing)
2012/07/17 03:43:00
I forget why Flush() was parallel. Possibly as a w
| |
473 base::Closure do_flush = done_cb; | |
474 | |
475 if (pipeline_filter_) { | |
476 do_flush = base::Bind(&Pipeline::RunOnPipelineThread, this, do_flush); | |
477 do_flush = base::Bind(&Filter::Flush, pipeline_filter_, do_flush); | |
478 } | |
479 | |
480 if (audio_renderer_) { | |
481 do_flush = base::Bind(&Pipeline::RunOnPipelineThread, this, do_flush); | |
482 do_flush = base::Bind(&AudioRenderer::Flush, audio_renderer_, do_flush); | |
483 } | |
484 | |
485 do_flush.Run(); | |
486 } | |
487 | |
488 void Pipeline::DoPlay(const base::Closure& done_cb) { | |
489 base::Closure do_play = done_cb; | |
490 | |
491 if (pipeline_filter_) { | |
492 do_play = base::Bind(&Pipeline::RunOnPipelineThread, this, do_play); | |
493 do_play = base::Bind(&Filter::Play, pipeline_filter_, do_play); | |
494 } | |
495 | |
496 if (audio_renderer_) { | |
497 do_play = base::Bind(&Pipeline::RunOnPipelineThread, this, do_play); | |
498 do_play = base::Bind(&AudioRenderer::Play, audio_renderer_, do_play); | |
499 } | |
500 | |
501 do_play.Run(); | |
502 } | |
503 | |
504 void Pipeline::DoStop(const base::Closure& done_cb) { | |
505 base::Closure do_stop = done_cb; | |
506 | |
507 if (pipeline_filter_) { | |
508 do_stop = base::Bind(&Pipeline::RunOnPipelineThread, this, do_stop); | |
509 do_stop = base::Bind(&Filter::Stop, pipeline_filter_, do_stop); | |
510 } | |
511 | |
512 if (audio_renderer_) { | |
513 do_stop = base::Bind(&Pipeline::RunOnPipelineThread, this, do_stop); | |
514 do_stop = base::Bind(&AudioRenderer::Stop, audio_renderer_, do_stop); | |
515 } | |
516 | |
517 if (demuxer_) { | |
518 do_stop = base::Bind(&Pipeline::RunOnPipelineThread, this, do_stop); | |
519 do_stop = base::Bind(&Demuxer::Stop, demuxer_, do_stop); | |
520 } | |
521 | |
522 do_stop.Run(); | |
523 } | |
524 | |
457 void Pipeline::AddBufferedByteRange(int64 start, int64 end) { | 525 void Pipeline::AddBufferedByteRange(int64 start, int64 end) { |
458 DCHECK(IsRunning()); | 526 DCHECK(IsRunning()); |
459 base::AutoLock auto_lock(lock_); | 527 base::AutoLock auto_lock(lock_); |
460 buffered_byte_ranges_.Add(start, end); | 528 buffered_byte_ranges_.Add(start, end); |
461 did_loading_progress_ = true; | 529 did_loading_progress_ = true; |
462 } | 530 } |
463 | 531 |
464 void Pipeline::AddBufferedTimeRange(base::TimeDelta start, | 532 void Pipeline::AddBufferedTimeRange(base::TimeDelta start, |
465 base::TimeDelta end) { | 533 base::TimeDelta end) { |
466 DCHECK(IsRunning()); | 534 DCHECK(IsRunning()); |
(...skipping 11 matching lines...) Expand all Loading... | |
478 natural_size_ = size; | 546 natural_size_ = size; |
479 } | 547 } |
480 | 548 |
481 void Pipeline::NotifyEnded() { | 549 void Pipeline::NotifyEnded() { |
482 DCHECK(IsRunning()); | 550 DCHECK(IsRunning()); |
483 message_loop_->PostTask(FROM_HERE, base::Bind( | 551 message_loop_->PostTask(FROM_HERE, base::Bind( |
484 &Pipeline::NotifyEndedTask, this)); | 552 &Pipeline::NotifyEndedTask, this)); |
485 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED)); | 553 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED)); |
486 } | 554 } |
487 | 555 |
488 void Pipeline::DisableAudioRenderer() { | 556 void Pipeline::AudioRendererEnded() { |
489 DCHECK(IsRunning()); | 557 DCHECK(IsRunning()); |
558 message_loop_->PostTask(FROM_HERE, base::Bind( | |
559 &Pipeline::NotifyEndedTask, this)); | |
560 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED)); | |
561 } | |
490 | 562 |
491 // Disable renderer on the message loop. | 563 void Pipeline::AudioRendererDisabled() { |
564 DCHECK(IsRunning()); | |
492 message_loop_->PostTask(FROM_HERE, base::Bind( | 565 message_loop_->PostTask(FROM_HERE, base::Bind( |
493 &Pipeline::DisableAudioRendererTask, this)); | 566 &Pipeline::AudioRendererDisabledTask, this)); |
494 media_log_->AddEvent( | 567 media_log_->AddEvent( |
495 media_log_->CreateEvent(MediaLogEvent::AUDIO_RENDERER_DISABLED)); | 568 media_log_->CreateEvent(MediaLogEvent::AUDIO_RENDERER_DISABLED)); |
496 } | 569 } |
497 | 570 |
498 // Called from any thread. | 571 // Called from any thread. |
499 void Pipeline::OnFilterInitialize(PipelineStatus status) { | 572 void Pipeline::OnFilterInitialize(PipelineStatus status) { |
500 // Continue the initialize task by proceeding to the next stage. | 573 // Continue the initialize task by proceeding to the next stage. |
501 message_loop_->PostTask(FROM_HERE, base::Bind( | 574 message_loop_->PostTask(FROM_HERE, base::Bind( |
502 &Pipeline::InitializeTask, this, status)); | 575 &Pipeline::InitializeTask, this, status)); |
503 } | 576 } |
504 | 577 |
505 // Called from any thread. | 578 // Called from any thread. |
506 void Pipeline::OnFilterStateTransition() { | 579 void Pipeline::OnFilterStateTransition() { |
scherkus (not reviewing)
2012/07/10 04:02:52
we might be to remove this trampoline since the Do
acolwell GONE FROM CHROMIUM
2012/07/10 16:34:37
This is an unconditional post though. RunOnPipelin
Ami GONE FROM CHROMIUM
2012/07/10 17:16:00
I agree w/ acolwell and suspect this means RunOnPi
scherkus (not reviewing)
2012/07/17 03:43:00
Done.
| |
507 message_loop_->PostTask(FROM_HERE, base::Bind( | 580 message_loop_->PostTask(FROM_HERE, base::Bind( |
508 &Pipeline::FilterStateTransitionTask, this)); | 581 &Pipeline::FilterStateTransitionTask, this)); |
509 } | 582 } |
510 | 583 |
511 // Called from any thread. | 584 // Called from any thread. |
512 // This method makes the PipelineStatusCB behave like a Closure. It | 585 // This method makes the PipelineStatusCB behave like a Closure. It |
513 // makes it look like a host()->SetError() call followed by a call to | 586 // makes it look like a host()->SetError() call followed by a call to |
514 // OnFilterStateTransition() when errors occur. | 587 // OnFilterStateTransition() when errors occur. |
515 // | 588 // |
516 // TODO: Revisit this code when SetError() is removed from FilterHost and | 589 // TODO: Revisit this code when SetError() is removed from FilterHost and |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
739 | 812 |
740 { | 813 { |
741 base::AutoLock auto_lock(lock_); | 814 base::AutoLock auto_lock(lock_); |
742 clock_->SetPlaybackRate(playback_rate); | 815 clock_->SetPlaybackRate(playback_rate); |
743 } | 816 } |
744 | 817 |
745 // Notify |pipeline_filter_| if it has been initialized. If initialization | 818 // Notify |pipeline_filter_| if it has been initialized. If initialization |
746 // hasn't completed yet, the playback rate will be set when initialization | 819 // hasn't completed yet, the playback rate will be set when initialization |
747 // completes. | 820 // completes. |
748 if (pipeline_filter_) { | 821 if (pipeline_filter_) { |
749 DCHECK(demuxer_); | |
750 demuxer_->SetPlaybackRate(playback_rate); | 822 demuxer_->SetPlaybackRate(playback_rate); |
751 pipeline_filter_->SetPlaybackRate(playback_rate); | 823 pipeline_filter_->SetPlaybackRate(playback_rate); |
752 } | 824 } |
825 | |
826 if (audio_renderer_) | |
acolwell GONE FROM CHROMIUM
2012/07/10 16:34:37
This isn't consistent with the original code. It s
scherkus (not reviewing)
2012/07/17 03:43:00
Done.
| |
827 audio_renderer_->SetPlaybackRate(playback_rate_); | |
753 } | 828 } |
754 | 829 |
755 void Pipeline::VolumeChangedTask(float volume) { | 830 void Pipeline::VolumeChangedTask(float volume) { |
756 DCHECK(message_loop_->BelongsToCurrentThread()); | 831 DCHECK(message_loop_->BelongsToCurrentThread()); |
757 if (!running_ || tearing_down_) | 832 if (!running_ || tearing_down_) |
758 return; | 833 return; |
759 | 834 |
760 if (audio_renderer_) | 835 if (audio_renderer_) |
761 audio_renderer_->SetVolume(volume); | 836 audio_renderer_->SetVolume(volume); |
762 } | 837 } |
(...skipping 24 matching lines...) Expand all Loading... | |
787 SetState(kPausing); | 862 SetState(kPausing); |
788 seek_timestamp_ = time; | 863 seek_timestamp_ = time; |
789 seek_cb_ = seek_cb; | 864 seek_cb_ = seek_cb; |
790 | 865 |
791 // Kick off seeking! | 866 // Kick off seeking! |
792 { | 867 { |
793 base::AutoLock auto_lock(lock_); | 868 base::AutoLock auto_lock(lock_); |
794 if (clock_->IsPlaying()) | 869 if (clock_->IsPlaying()) |
795 clock_->Pause(); | 870 clock_->Pause(); |
796 } | 871 } |
797 pipeline_filter_->Pause( | 872 DoPause(base::Bind(&Pipeline::OnFilterStateTransition, this)); |
798 base::Bind(&Pipeline::OnFilterStateTransition, this)); | |
799 } | 873 } |
800 | 874 |
801 void Pipeline::NotifyEndedTask() { | 875 void Pipeline::NotifyEndedTask() { |
802 DCHECK(message_loop_->BelongsToCurrentThread()); | 876 DCHECK(message_loop_->BelongsToCurrentThread()); |
803 | 877 |
804 // We can only end if we were actually playing. | 878 // We can only end if we were actually playing. |
805 if (state_ != kStarted) { | 879 if (state_ != kStarted) { |
806 return; | 880 return; |
807 } | 881 } |
808 | 882 |
(...skipping 19 matching lines...) Expand all Loading... | |
828 // Transition to ended, executing the callback if present. | 902 // Transition to ended, executing the callback if present. |
829 SetState(kEnded); | 903 SetState(kEnded); |
830 { | 904 { |
831 base::AutoLock auto_lock(lock_); | 905 base::AutoLock auto_lock(lock_); |
832 clock_->EndOfStream(); | 906 clock_->EndOfStream(); |
833 } | 907 } |
834 | 908 |
835 ReportStatus(ended_cb_, status_); | 909 ReportStatus(ended_cb_, status_); |
836 } | 910 } |
837 | 911 |
838 void Pipeline::DisableAudioRendererTask() { | 912 void Pipeline::AudioRendererDisabledTask() { |
839 DCHECK(message_loop_->BelongsToCurrentThread()); | 913 DCHECK(message_loop_->BelongsToCurrentThread()); |
840 | 914 |
841 base::AutoLock auto_lock(lock_); | 915 base::AutoLock auto_lock(lock_); |
842 has_audio_ = false; | 916 has_audio_ = false; |
843 audio_disabled_ = true; | 917 audio_disabled_ = true; |
844 | 918 |
845 // Notify our demuxer that we're no longer rendering audio. | 919 // Notify our demuxer that we're no longer rendering audio. |
846 demuxer_->OnAudioRendererDisabled(); | 920 demuxer_->OnAudioRendererDisabled(); |
847 | 921 |
848 // Start clock since there is no more audio to | 922 // Start clock since there is no more audio to |
(...skipping 26 matching lines...) Expand all Loading... | |
875 // to the next state if needed. | 949 // to the next state if needed. |
876 SetState(FindNextState(state_)); | 950 SetState(FindNextState(state_)); |
877 if (state_ == kSeeking) { | 951 if (state_ == kSeeking) { |
878 base::AutoLock auto_lock(lock_); | 952 base::AutoLock auto_lock(lock_); |
879 clock_->SetTime(seek_timestamp_, seek_timestamp_); | 953 clock_->SetTime(seek_timestamp_, seek_timestamp_); |
880 } | 954 } |
881 | 955 |
882 // Carry out the action for the current state. | 956 // Carry out the action for the current state. |
883 if (TransientState(state_)) { | 957 if (TransientState(state_)) { |
884 if (state_ == kPausing) { | 958 if (state_ == kPausing) { |
885 pipeline_filter_->Pause( | 959 DoPause(base::Bind(&Pipeline::OnFilterStateTransition, this)); |
886 base::Bind(&Pipeline::OnFilterStateTransition, this)); | |
887 } else if (state_ == kFlushing) { | 960 } else if (state_ == kFlushing) { |
888 pipeline_filter_->Flush( | 961 DoFlush(base::Bind(&Pipeline::OnFilterStateTransition, this)); |
889 base::Bind(&Pipeline::OnFilterStateTransition, this)); | |
890 } else if (state_ == kSeeking) { | 962 } else if (state_ == kSeeking) { |
891 DoSeek(seek_timestamp_); | 963 DoSeek(seek_timestamp_); |
892 } else if (state_ == kStarting) { | 964 } else if (state_ == kStarting) { |
893 pipeline_filter_->Play( | 965 DoPlay(base::Bind(&Pipeline::OnFilterStateTransition, this)); |
894 base::Bind(&Pipeline::OnFilterStateTransition, this)); | |
895 } else if (state_ == kStopping) { | 966 } else if (state_ == kStopping) { |
896 DoStop(base::Bind(&Pipeline::OnFilterStateTransition, this)); | 967 DoStop(base::Bind(&Pipeline::OnFilterStateTransition, this)); |
897 } else { | 968 } else { |
898 NOTREACHED() << "Unexpected state: " << state_; | 969 NOTREACHED() << "Unexpected state: " << state_; |
899 } | 970 } |
900 } else if (state_ == kStarted) { | 971 } else if (state_ == kStarted) { |
901 FinishInitialization(); | 972 FinishInitialization(); |
902 | 973 |
903 // Finally, complete the seek. | 974 // Finally, complete the seek. |
904 seek_pending_ = false; | 975 seek_pending_ = false; |
(...skipping 25 matching lines...) Expand all Loading... | |
930 | 1001 |
931 void Pipeline::TeardownStateTransitionTask() { | 1002 void Pipeline::TeardownStateTransitionTask() { |
932 DCHECK(IsPipelineTearingDown()); | 1003 DCHECK(IsPipelineTearingDown()); |
933 switch (state_) { | 1004 switch (state_) { |
934 case kStopping: | 1005 case kStopping: |
935 SetState(error_caused_teardown_ ? kError : kStopped); | 1006 SetState(error_caused_teardown_ ? kError : kStopped); |
936 FinishDestroyingFiltersTask(); | 1007 FinishDestroyingFiltersTask(); |
937 break; | 1008 break; |
938 case kPausing: | 1009 case kPausing: |
939 SetState(kFlushing); | 1010 SetState(kFlushing); |
940 pipeline_filter_->Flush( | 1011 DoFlush(base::Bind(&Pipeline::OnTeardownStateTransition, this)); |
941 base::Bind(&Pipeline::OnTeardownStateTransition, this)); | |
942 break; | 1012 break; |
943 case kFlushing: | 1013 case kFlushing: |
944 SetState(kStopping); | 1014 SetState(kStopping); |
945 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); | 1015 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); |
946 break; | 1016 break; |
947 | 1017 |
948 case kCreated: | 1018 case kCreated: |
949 case kError: | 1019 case kError: |
950 case kInitDemuxer: | 1020 case kInitDemuxer: |
951 case kInitAudioDecoder: | 1021 case kInitAudioDecoder: |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1079 } | 1149 } |
1080 | 1150 |
1081 bool Pipeline::InitializeAudioRenderer( | 1151 bool Pipeline::InitializeAudioRenderer( |
1082 const scoped_refptr<AudioDecoder>& decoder) { | 1152 const scoped_refptr<AudioDecoder>& decoder) { |
1083 DCHECK(message_loop_->BelongsToCurrentThread()); | 1153 DCHECK(message_loop_->BelongsToCurrentThread()); |
1084 DCHECK(IsPipelineOk()); | 1154 DCHECK(IsPipelineOk()); |
1085 | 1155 |
1086 if (!decoder) | 1156 if (!decoder) |
1087 return false; | 1157 return false; |
1088 | 1158 |
1089 filter_collection_->SelectAudioRenderer( | 1159 filter_collection_->SelectAudioRenderer(&audio_renderer_); |
1090 &pipeline_init_state_->audio_renderer); | 1160 if (!audio_renderer_) { |
1091 if (!pipeline_init_state_->audio_renderer) { | |
1092 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 1161 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); |
1093 return false; | 1162 return false; |
1094 } | 1163 } |
1095 | 1164 |
1096 pipeline_init_state_->composite->AddFilter( | 1165 audio_renderer_->SetHost(this); |
scherkus (not reviewing)
2012/07/10 04:02:52
I think SetHost() can go away after we replace ARH
acolwell GONE FROM CHROMIUM
2012/07/10 16:34:37
I think we should just add the callbacks now. I ca
scherkus (not reviewing)
2012/07/17 03:43:00
Done.
| |
1097 pipeline_init_state_->audio_renderer); | 1166 audio_renderer_->Initialize( |
1098 | |
1099 pipeline_init_state_->audio_renderer->Initialize( | |
1100 decoder, | 1167 decoder, |
1101 base::Bind(&Pipeline::OnFilterInitialize, this), | 1168 base::Bind(&Pipeline::OnFilterInitialize, this), |
1102 base::Bind(&Pipeline::OnAudioUnderflow, this), | 1169 base::Bind(&Pipeline::OnAudioUnderflow, this), |
1103 base::Bind(&Pipeline::OnAudioTimeUpdate, this)); | 1170 base::Bind(&Pipeline::OnAudioTimeUpdate, this)); |
1104 | |
1105 audio_renderer_ = pipeline_init_state_->audio_renderer; | |
1106 return true; | 1171 return true; |
1107 } | 1172 } |
1108 | 1173 |
1109 bool Pipeline::InitializeVideoRenderer( | 1174 bool Pipeline::InitializeVideoRenderer( |
1110 const scoped_refptr<VideoDecoder>& decoder) { | 1175 const scoped_refptr<VideoDecoder>& decoder) { |
1111 DCHECK(message_loop_->BelongsToCurrentThread()); | 1176 DCHECK(message_loop_->BelongsToCurrentThread()); |
1112 DCHECK(IsPipelineOk()); | 1177 DCHECK(IsPipelineOk()); |
1113 | 1178 |
1114 if (!decoder) | 1179 if (!decoder) |
1115 return false; | 1180 return false; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1181 if (seek_pending_) { | 1246 if (seek_pending_) { |
1182 seek_pending_ = false; | 1247 seek_pending_ = false; |
1183 FinishInitialization(); | 1248 FinishInitialization(); |
1184 } | 1249 } |
1185 | 1250 |
1186 break; | 1251 break; |
1187 | 1252 |
1188 case kStarted: | 1253 case kStarted: |
1189 case kEnded: | 1254 case kEnded: |
1190 SetState(kPausing); | 1255 SetState(kPausing); |
1191 pipeline_filter_->Pause( | 1256 DoPause(base::Bind(&Pipeline::OnTeardownStateTransition, this)); |
1192 base::Bind(&Pipeline::OnTeardownStateTransition, this)); | |
1193 break; | 1257 break; |
1194 | 1258 |
1195 case kStopping: | 1259 case kStopping: |
1196 case kStopped: | 1260 case kStopped: |
1197 NOTREACHED() << "Unexpected state for teardown: " << state_; | 1261 NOTREACHED() << "Unexpected state for teardown: " << state_; |
1198 break; | 1262 break; |
1199 // default: intentionally left out to force new states to cause compiler | 1263 // default: intentionally left out to force new states to cause compiler |
1200 // errors. | 1264 // errors. |
1201 }; | 1265 }; |
1202 } | 1266 } |
1203 | 1267 |
1204 void Pipeline::DoStop(const base::Closure& callback) { | |
1205 if (demuxer_) { | |
1206 demuxer_->Stop(base::Bind( | |
1207 &Pipeline::OnDemuxerStopDone, this, callback)); | |
1208 return; | |
1209 } | |
1210 | |
1211 OnDemuxerStopDone(callback); | |
1212 } | |
1213 | |
1214 void Pipeline::OnDemuxerStopDone(const base::Closure& callback) { | |
1215 if (!message_loop_->BelongsToCurrentThread()) { | |
1216 message_loop_->PostTask(FROM_HERE, base::Bind( | |
1217 &Pipeline::OnDemuxerStopDone, this, callback)); | |
1218 return; | |
1219 } | |
1220 | |
1221 if (pipeline_filter_) { | |
1222 pipeline_filter_->Stop(callback); | |
1223 return; | |
1224 } | |
1225 | |
1226 callback.Run(); | |
1227 } | |
1228 | |
1229 void Pipeline::DoSeek(TimeDelta seek_timestamp) { | 1268 void Pipeline::DoSeek(TimeDelta seek_timestamp) { |
1230 // TODO(acolwell): We might be able to convert this if (demuxer_) into a | 1269 // TODO(acolwell): We might be able to convert this if (demuxer_) into a |
1231 // DCHECK(). Further investigation is needed to make sure this won't introduce | 1270 // DCHECK(). Further investigation is needed to make sure this won't introduce |
1232 // a bug. | 1271 // a bug. |
scherkus (not reviewing)
2012/07/10 03:58:22
FYI I think it's impossible for demuxer_ to be NUL
acolwell GONE FROM CHROMIUM
2012/07/10 16:34:37
Go for it. We'll see if it goes boom.
scherkus (not reviewing)
2012/07/17 03:43:00
Committed separately as r146024.
| |
1233 if (demuxer_) { | 1272 if (demuxer_) { |
1234 demuxer_->Seek(seek_timestamp, base::Bind( | 1273 demuxer_->Seek(seek_timestamp, base::Bind( |
1235 &Pipeline::OnDemuxerSeekDone, this, seek_timestamp)); | 1274 &Pipeline::OnDemuxerSeekDone, this, seek_timestamp)); |
1236 return; | 1275 return; |
1237 } | 1276 } |
1238 | 1277 |
1239 OnDemuxerSeekDone(seek_timestamp, PIPELINE_OK); | 1278 OnDemuxerSeekDone(seek_timestamp, PIPELINE_OK); |
1240 } | 1279 } |
1241 | 1280 |
1242 void Pipeline::OnDemuxerSeekDone(TimeDelta seek_timestamp, | 1281 void Pipeline::OnDemuxerSeekDone(TimeDelta seek_timestamp, |
1243 PipelineStatus status) { | 1282 PipelineStatus status) { |
1244 if (!message_loop_->BelongsToCurrentThread()) { | 1283 if (!message_loop_->BelongsToCurrentThread()) { |
1245 message_loop_->PostTask(FROM_HERE, base::Bind( | 1284 message_loop_->PostTask(FROM_HERE, base::Bind( |
1246 &Pipeline::OnDemuxerSeekDone, this, seek_timestamp, status)); | 1285 &Pipeline::OnDemuxerSeekDone, this, seek_timestamp, status)); |
1247 return; | 1286 return; |
1248 } | 1287 } |
1249 | 1288 |
1289 if (status == PIPELINE_OK && audio_renderer_) { | |
1290 audio_renderer_->Seek(seek_timestamp, base::Bind( | |
1291 &Pipeline::OnAudioRendererSeekDone, this, seek_timestamp)); | |
1292 return; | |
1293 } | |
1294 | |
1295 OnAudioRendererSeekDone(seek_timestamp, status); | |
1296 } | |
1297 | |
1298 void Pipeline::OnAudioRendererSeekDone(base::TimeDelta seek_timestamp, | |
1299 PipelineStatus status) { | |
1300 if (!message_loop_->BelongsToCurrentThread()) { | |
1301 message_loop_->PostTask(FROM_HERE, base::Bind( | |
1302 &Pipeline::OnAudioRendererSeekDone, this, seek_timestamp, status)); | |
1303 return; | |
1304 } | |
1305 | |
1250 PipelineStatusCB done_cb = | 1306 PipelineStatusCB done_cb = |
1251 base::Bind(&Pipeline::OnFilterStateTransitionWithStatus, this); | 1307 base::Bind(&Pipeline::OnFilterStateTransitionWithStatus, this); |
1252 | 1308 |
1253 if (status == PIPELINE_OK && pipeline_filter_) { | 1309 if (status == PIPELINE_OK && pipeline_filter_) { |
1254 pipeline_filter_->Seek(seek_timestamp, done_cb); | 1310 pipeline_filter_->Seek(seek_timestamp, done_cb); |
1255 return; | 1311 return; |
1256 } | 1312 } |
1257 | 1313 |
1258 ReportStatus(done_cb, status); | 1314 ReportStatus(done_cb, status); |
1259 } | 1315 } |
(...skipping 14 matching lines...) Expand all Loading... | |
1274 | 1330 |
1275 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { | 1331 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { |
1276 lock_.AssertAcquired(); | 1332 lock_.AssertAcquired(); |
1277 if (!waiting_for_clock_update_) | 1333 if (!waiting_for_clock_update_) |
1278 return; | 1334 return; |
1279 | 1335 |
1280 waiting_for_clock_update_ = false; | 1336 waiting_for_clock_update_ = false; |
1281 clock_->Play(); | 1337 clock_->Play(); |
1282 } | 1338 } |
1283 | 1339 |
1340 void Pipeline::RunOnPipelineThread(const base::Closure& closure) { | |
1341 if (!message_loop_->BelongsToCurrentThread()) { | |
1342 message_loop_->PostTask(FROM_HERE, base::Bind( | |
1343 &Pipeline::RunOnPipelineThread, this, closure)); | |
1344 return; | |
1345 } | |
1346 closure.Run(); | |
1347 } | |
1348 | |
1284 } // namespace media | 1349 } // namespace media |
OLD | NEW |