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 { |
Ami GONE FROM CHROMIUM
2012/08/09 20:30:18
drop this struct now (and bind the audio decoder i
acolwell GONE FROM CHROMIUM
2012/08/09 22:23:32
I can't really do this w/o moving the kInitAudioDe
| |
65 scoped_refptr<AudioDecoder> audio_decoder; | 65 scoped_refptr<AudioDecoder> audio_decoder; |
66 scoped_refptr<VideoDecoder> video_decoder; | |
67 }; | 66 }; |
68 | 67 |
69 Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log) | 68 Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log) |
70 : message_loop_(message_loop->message_loop_proxy()), | 69 : message_loop_(message_loop->message_loop_proxy()), |
71 media_log_(media_log), | 70 media_log_(media_log), |
72 running_(false), | 71 running_(false), |
73 seek_pending_(false), | 72 seek_pending_(false), |
74 stop_pending_(false), | 73 stop_pending_(false), |
75 tearing_down_(false), | 74 tearing_down_(false), |
76 error_caused_teardown_(false), | 75 error_caused_teardown_(false), |
(...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
602 // FilterHost's InitializationComplete() method, the pipeline will update its | 601 // FilterHost's InitializationComplete() method, the pipeline will update its |
603 // state to kStarted and |init_cb_|, will be executed. | 602 // state to kStarted and |init_cb_|, will be executed. |
604 // | 603 // |
605 // TODO(hclam): InitializeTask() is now starting the pipeline asynchronously. It | 604 // TODO(hclam): InitializeTask() is now starting the pipeline asynchronously. It |
606 // works like a big state change table. If we no longer need to start filters | 605 // works like a big state change table. If we no longer need to start filters |
607 // in order, we need to get rid of all the state change. | 606 // in order, we need to get rid of all the state change. |
608 void Pipeline::InitializeTask(PipelineStatus last_stage_status) { | 607 void Pipeline::InitializeTask(PipelineStatus last_stage_status) { |
609 DCHECK(message_loop_->BelongsToCurrentThread()); | 608 DCHECK(message_loop_->BelongsToCurrentThread()); |
610 | 609 |
611 if (last_stage_status != PIPELINE_OK) { | 610 if (last_stage_status != PIPELINE_OK) { |
612 // Currently only VideoDecoders have a recoverable error code. | 611 SetError(last_stage_status); |
613 if (state_ == kInitVideoDecoder && | 612 return; |
614 last_stage_status == DECODER_ERROR_NOT_SUPPORTED) { | |
615 state_ = kInitAudioRenderer; | |
616 } else { | |
617 SetError(last_stage_status); | |
618 return; | |
619 } | |
620 } | 613 } |
621 | 614 |
622 // If we have received the stop or error signal, return immediately. | 615 // If we have received the stop or error signal, return immediately. |
623 if (IsPipelineStopPending() || IsPipelineStopped() || !IsPipelineOk()) | 616 if (IsPipelineStopPending() || IsPipelineStopped() || !IsPipelineOk()) |
624 return; | 617 return; |
625 | 618 |
626 DCHECK(state_ == kInitDemuxer || | 619 DCHECK(state_ == kInitDemuxer || |
627 state_ == kInitAudioDecoder || | 620 state_ == kInitAudioDecoder || |
628 state_ == kInitAudioRenderer || | 621 state_ == kInitAudioRenderer || |
629 state_ == kInitVideoDecoder || | |
630 state_ == kInitVideoRenderer); | 622 state_ == kInitVideoRenderer); |
631 | 623 |
632 // Demuxer created, create audio decoder. | 624 // Demuxer created, create audio decoder. |
633 if (state_ == kInitDemuxer) { | 625 if (state_ == kInitDemuxer) { |
634 SetState(kInitAudioDecoder); | 626 SetState(kInitAudioDecoder); |
635 // If this method returns false, then there's no audio stream. | 627 // If this method returns false, then there's no audio stream. |
636 if (InitializeAudioDecoder(demuxer_)) | 628 if (InitializeAudioDecoder(demuxer_)) |
637 return; | 629 return; |
638 } | 630 } |
639 | 631 |
640 // Assuming audio decoder was created, create audio renderer. | 632 // Assuming audio decoder was created, create audio renderer. |
641 if (state_ == kInitAudioDecoder) { | 633 if (state_ == kInitAudioDecoder) { |
642 SetState(kInitAudioRenderer); | 634 SetState(kInitAudioRenderer); |
643 | 635 |
644 // Returns false if there's no audio stream. | 636 // Returns false if there's no audio stream. |
645 if (InitializeAudioRenderer(pipeline_init_state_->audio_decoder)) { | 637 if (InitializeAudioRenderer(pipeline_init_state_->audio_decoder)) { |
646 base::AutoLock auto_lock(lock_); | 638 base::AutoLock auto_lock(lock_); |
647 has_audio_ = true; | 639 has_audio_ = true; |
648 return; | 640 return; |
649 } | 641 } |
650 } | 642 } |
651 | 643 |
652 // Assuming audio renderer was created, create video decoder. | 644 // Assuming audio renderer was created, create video decoder. |
Ami GONE FROM CHROMIUM
2012/08/09 20:30:18
s/decoder/renderer/
acolwell GONE FROM CHROMIUM
2012/08/09 22:23:32
Done.
| |
653 if (state_ == kInitAudioRenderer) { | 645 if (state_ == kInitAudioRenderer) { |
654 // Then perform the stage of initialization, i.e. initialize video decoder. | |
655 SetState(kInitVideoDecoder); | |
656 if (InitializeVideoDecoder(demuxer_)) | |
657 return; | |
658 } | |
659 | |
660 // Assuming video decoder was created, create video renderer. | |
661 if (state_ == kInitVideoDecoder) { | |
662 SetState(kInitVideoRenderer); | 646 SetState(kInitVideoRenderer); |
663 if (InitializeVideoRenderer(pipeline_init_state_->video_decoder)) { | 647 if (InitializeVideoRenderer(demuxer_->GetStream(DemuxerStream::VIDEO))) { |
664 base::AutoLock auto_lock(lock_); | 648 base::AutoLock auto_lock(lock_); |
665 has_video_ = true; | 649 has_video_ = true; |
666 return; | 650 return; |
667 } | 651 } |
668 } | 652 } |
669 | 653 |
670 if (state_ == kInitVideoRenderer) { | 654 if (state_ == kInitVideoRenderer) { |
671 if (!IsPipelineOk() || !(HasAudio() || HasVideo())) { | 655 if (!IsPipelineOk() || !(HasAudio() || HasVideo())) { |
672 SetError(PIPELINE_ERROR_COULD_NOT_RENDER); | 656 SetError(PIPELINE_ERROR_COULD_NOT_RENDER); |
673 return; | 657 return; |
(...skipping 23 matching lines...) Expand all Loading... | |
697 // We stop the filters in the reverse order. | 681 // We stop the filters in the reverse order. |
698 // | 682 // |
699 // TODO(scherkus): beware! this can get posted multiple times since we post | 683 // TODO(scherkus): beware! this can get posted multiple times since we post |
700 // Stop() tasks even if we've already stopped. Perhaps this should no-op for | 684 // Stop() tasks even if we've already stopped. Perhaps this should no-op for |
701 // additional calls, however most of this logic will be changing. | 685 // additional calls, however most of this logic will be changing. |
702 void Pipeline::StopTask(const base::Closure& stop_cb) { | 686 void Pipeline::StopTask(const base::Closure& stop_cb) { |
703 DCHECK(message_loop_->BelongsToCurrentThread()); | 687 DCHECK(message_loop_->BelongsToCurrentThread()); |
704 DCHECK(!IsPipelineStopPending()); | 688 DCHECK(!IsPipelineStopPending()); |
705 DCHECK_NE(state_, kStopped); | 689 DCHECK_NE(state_, kStopped); |
706 | 690 |
707 if (video_decoder_) { | 691 if (video_renderer_) |
708 video_decoder_->PrepareForShutdownHack(); | 692 video_renderer_->PrepareForShutdownHack(); |
709 video_decoder_ = NULL; | |
710 } | |
711 | 693 |
712 if (IsPipelineTearingDown() && error_caused_teardown_) { | 694 if (IsPipelineTearingDown() && error_caused_teardown_) { |
713 // If we are stopping due to SetError(), stop normally instead of | 695 // If we are stopping due to SetError(), stop normally instead of |
714 // going to error state and calling |error_cb_|. This converts | 696 // going to error state and calling |error_cb_|. This converts |
715 // the teardown in progress from an error teardown into one that acts | 697 // the teardown in progress from an error teardown into one that acts |
716 // like the error never occurred. | 698 // like the error never occurred. |
717 base::AutoLock auto_lock(lock_); | 699 base::AutoLock auto_lock(lock_); |
718 status_ = PIPELINE_OK; | 700 status_ = PIPELINE_OK; |
719 error_caused_teardown_ = false; | 701 error_caused_teardown_ = false; |
720 } | 702 } |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
978 case kFlushing: | 960 case kFlushing: |
979 SetState(kStopping); | 961 SetState(kStopping); |
980 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); | 962 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); |
981 break; | 963 break; |
982 | 964 |
983 case kCreated: | 965 case kCreated: |
984 case kError: | 966 case kError: |
985 case kInitDemuxer: | 967 case kInitDemuxer: |
986 case kInitAudioDecoder: | 968 case kInitAudioDecoder: |
987 case kInitAudioRenderer: | 969 case kInitAudioRenderer: |
988 case kInitVideoDecoder: | |
989 case kInitVideoRenderer: | 970 case kInitVideoRenderer: |
990 case kSeeking: | 971 case kSeeking: |
991 case kStarting: | 972 case kStarting: |
992 case kStopped: | 973 case kStopped: |
993 case kStarted: | 974 case kStarted: |
994 case kEnded: | 975 case kEnded: |
995 NOTREACHED() << "Unexpected state for teardown: " << state_; | 976 NOTREACHED() << "Unexpected state for teardown: " << state_; |
996 break; | 977 break; |
997 // default: intentionally left out to force new states to cause compiler | 978 // default: intentionally left out to force new states to cause compiler |
998 // errors. | 979 // errors. |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1079 return false; | 1060 return false; |
1080 } | 1061 } |
1081 | 1062 |
1082 pipeline_init_state_->audio_decoder->Initialize( | 1063 pipeline_init_state_->audio_decoder->Initialize( |
1083 stream, | 1064 stream, |
1084 base::Bind(&Pipeline::OnFilterInitialize, this), | 1065 base::Bind(&Pipeline::OnFilterInitialize, this), |
1085 base::Bind(&Pipeline::OnUpdateStatistics, this)); | 1066 base::Bind(&Pipeline::OnUpdateStatistics, this)); |
1086 return true; | 1067 return true; |
1087 } | 1068 } |
1088 | 1069 |
1089 bool Pipeline::InitializeVideoDecoder( | |
1090 const scoped_refptr<Demuxer>& demuxer) { | |
1091 DCHECK(message_loop_->BelongsToCurrentThread()); | |
1092 DCHECK(IsPipelineOk()); | |
1093 DCHECK(demuxer); | |
1094 | |
1095 scoped_refptr<DemuxerStream> stream = | |
1096 demuxer->GetStream(DemuxerStream::VIDEO); | |
1097 | |
1098 if (!stream) | |
1099 return false; | |
1100 | |
1101 filter_collection_->SelectVideoDecoder(&pipeline_init_state_->video_decoder); | |
1102 | |
1103 if (!pipeline_init_state_->video_decoder) { | |
1104 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | |
1105 return false; | |
1106 } | |
1107 | |
1108 pipeline_init_state_->video_decoder->Initialize( | |
1109 stream, | |
1110 base::Bind(&Pipeline::OnFilterInitialize, this), | |
1111 base::Bind(&Pipeline::OnUpdateStatistics, this)); | |
1112 | |
1113 video_decoder_ = pipeline_init_state_->video_decoder; | |
1114 return true; | |
1115 } | |
1116 | |
1117 bool Pipeline::InitializeAudioRenderer( | 1070 bool Pipeline::InitializeAudioRenderer( |
1118 const scoped_refptr<AudioDecoder>& decoder) { | 1071 const scoped_refptr<AudioDecoder>& decoder) { |
1119 DCHECK(message_loop_->BelongsToCurrentThread()); | 1072 DCHECK(message_loop_->BelongsToCurrentThread()); |
1120 DCHECK(IsPipelineOk()); | 1073 DCHECK(IsPipelineOk()); |
1121 | 1074 |
1122 if (!decoder) | 1075 if (!decoder) |
1123 return false; | 1076 return false; |
1124 | 1077 |
1125 filter_collection_->SelectAudioRenderer(&audio_renderer_); | 1078 filter_collection_->SelectAudioRenderer(&audio_renderer_); |
1126 if (!audio_renderer_) { | 1079 if (!audio_renderer_) { |
1127 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 1080 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); |
1128 return false; | 1081 return false; |
1129 } | 1082 } |
1130 | 1083 |
1131 audio_renderer_->Initialize( | 1084 audio_renderer_->Initialize( |
1132 decoder, | 1085 decoder, |
1133 base::Bind(&Pipeline::OnFilterInitialize, this), | 1086 base::Bind(&Pipeline::OnFilterInitialize, this), |
1134 base::Bind(&Pipeline::OnAudioUnderflow, this), | 1087 base::Bind(&Pipeline::OnAudioUnderflow, this), |
1135 base::Bind(&Pipeline::OnAudioTimeUpdate, this), | 1088 base::Bind(&Pipeline::OnAudioTimeUpdate, this), |
1136 base::Bind(&Pipeline::OnRendererEnded, this), | 1089 base::Bind(&Pipeline::OnRendererEnded, this), |
1137 base::Bind(&Pipeline::OnAudioDisabled, this), | 1090 base::Bind(&Pipeline::OnAudioDisabled, this), |
1138 base::Bind(&Pipeline::SetError, this)); | 1091 base::Bind(&Pipeline::SetError, this)); |
1139 return true; | 1092 return true; |
1140 } | 1093 } |
1141 | 1094 |
1142 bool Pipeline::InitializeVideoRenderer( | 1095 bool Pipeline::InitializeVideoRenderer( |
1143 const scoped_refptr<VideoDecoder>& decoder) { | 1096 const scoped_refptr<DemuxerStream>& stream) { |
1144 DCHECK(message_loop_->BelongsToCurrentThread()); | 1097 DCHECK(message_loop_->BelongsToCurrentThread()); |
1145 DCHECK(IsPipelineOk()); | 1098 DCHECK(IsPipelineOk()); |
1146 | 1099 |
1147 if (!decoder) | 1100 if (!stream) |
1148 return false; | 1101 return false; |
1149 | 1102 |
1150 filter_collection_->SelectVideoRenderer(&video_renderer_); | 1103 filter_collection_->SelectVideoRenderer(&video_renderer_); |
1151 if (!video_renderer_) { | 1104 if (!video_renderer_) { |
1152 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 1105 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); |
1153 return false; | 1106 return false; |
1154 } | 1107 } |
1155 | 1108 |
1156 video_renderer_->Initialize( | 1109 video_renderer_->Initialize( |
1157 decoder, | 1110 stream, |
1111 filter_collection_->GetVideoDecoders(), | |
1158 base::Bind(&Pipeline::OnFilterInitialize, this), | 1112 base::Bind(&Pipeline::OnFilterInitialize, this), |
1159 base::Bind(&Pipeline::OnUpdateStatistics, this), | 1113 base::Bind(&Pipeline::OnUpdateStatistics, this), |
1160 base::Bind(&Pipeline::OnVideoTimeUpdate, this), | 1114 base::Bind(&Pipeline::OnVideoTimeUpdate, this), |
1161 base::Bind(&Pipeline::OnNaturalVideoSizeChanged, this), | 1115 base::Bind(&Pipeline::OnNaturalVideoSizeChanged, this), |
1162 base::Bind(&Pipeline::OnRendererEnded, this), | 1116 base::Bind(&Pipeline::OnRendererEnded, this), |
1163 base::Bind(&Pipeline::SetError, this), | 1117 base::Bind(&Pipeline::SetError, this), |
1164 base::Bind(&Pipeline::GetMediaTime, this), | 1118 base::Bind(&Pipeline::GetMediaTime, this), |
1165 base::Bind(&Pipeline::GetMediaDuration, this)); | 1119 base::Bind(&Pipeline::GetMediaDuration, this)); |
1120 filter_collection_->GetVideoDecoders().clear(); | |
1166 return true; | 1121 return true; |
1167 } | 1122 } |
1168 | 1123 |
1169 void Pipeline::TearDownPipeline() { | 1124 void Pipeline::TearDownPipeline() { |
1170 DCHECK(message_loop_->BelongsToCurrentThread()); | 1125 DCHECK(message_loop_->BelongsToCurrentThread()); |
1171 DCHECK_NE(kStopped, state_); | 1126 DCHECK_NE(kStopped, state_); |
1172 | 1127 |
1173 DCHECK(!tearing_down_ || // Teardown on Stop(). | 1128 DCHECK(!tearing_down_ || // Teardown on Stop(). |
1174 (tearing_down_ && error_caused_teardown_) || // Teardown on error. | 1129 (tearing_down_ && error_caused_teardown_) || // Teardown on error. |
1175 (tearing_down_ && stop_pending_)); // Stop during teardown by error. | 1130 (tearing_down_ && stop_pending_)); // Stop during teardown by error. |
(...skipping 10 matching lines...) Expand all Loading... | |
1186 SetState(kStopped); | 1141 SetState(kStopped); |
1187 // Need to put this in the message loop to make sure that it comes | 1142 // Need to put this in the message loop to make sure that it comes |
1188 // after any pending callback tasks that are already queued. | 1143 // after any pending callback tasks that are already queued. |
1189 message_loop_->PostTask(FROM_HERE, base::Bind( | 1144 message_loop_->PostTask(FROM_HERE, base::Bind( |
1190 &Pipeline::FinishDestroyingFiltersTask, this)); | 1145 &Pipeline::FinishDestroyingFiltersTask, this)); |
1191 break; | 1146 break; |
1192 | 1147 |
1193 case kInitDemuxer: | 1148 case kInitDemuxer: |
1194 case kInitAudioDecoder: | 1149 case kInitAudioDecoder: |
1195 case kInitAudioRenderer: | 1150 case kInitAudioRenderer: |
1196 case kInitVideoDecoder: | |
1197 case kInitVideoRenderer: | 1151 case kInitVideoRenderer: |
1198 // Make it look like initialization was successful. | 1152 // Make it look like initialization was successful. |
1199 filter_collection_.reset(); | 1153 filter_collection_.reset(); |
1200 pipeline_init_state_.reset(); | 1154 pipeline_init_state_.reset(); |
1201 | 1155 |
1202 SetState(kStopping); | 1156 SetState(kStopping); |
1203 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); | 1157 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); |
1204 | 1158 |
1205 FinishInitialization(); | 1159 FinishInitialization(); |
1206 break; | 1160 break; |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1276 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { | 1230 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { |
1277 lock_.AssertAcquired(); | 1231 lock_.AssertAcquired(); |
1278 if (!waiting_for_clock_update_) | 1232 if (!waiting_for_clock_update_) |
1279 return; | 1233 return; |
1280 | 1234 |
1281 waiting_for_clock_update_ = false; | 1235 waiting_for_clock_update_ = false; |
1282 clock_->Play(); | 1236 clock_->Play(); |
1283 } | 1237 } |
1284 | 1238 |
1285 } // namespace media | 1239 } // namespace media |
OLD | NEW |