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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 { |
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 tearing_down_(false), | 73 tearing_down_(false), |
75 playback_rate_change_pending_(false), | 74 playback_rate_change_pending_(false), |
76 did_loading_progress_(false), | 75 did_loading_progress_(false), |
(...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
577 // FilterHost's InitializationComplete() method, the pipeline will update its | 576 // FilterHost's InitializationComplete() method, the pipeline will update its |
578 // state to kStarted and |init_cb_|, will be executed. | 577 // state to kStarted and |init_cb_|, will be executed. |
579 // | 578 // |
580 // TODO(hclam): InitializeTask() is now starting the pipeline asynchronously. It | 579 // TODO(hclam): InitializeTask() is now starting the pipeline asynchronously. It |
581 // works like a big state change table. If we no longer need to start filters | 580 // works like a big state change table. If we no longer need to start filters |
582 // in order, we need to get rid of all the state change. | 581 // in order, we need to get rid of all the state change. |
583 void Pipeline::InitializeTask(PipelineStatus last_stage_status) { | 582 void Pipeline::InitializeTask(PipelineStatus last_stage_status) { |
584 DCHECK(message_loop_->BelongsToCurrentThread()); | 583 DCHECK(message_loop_->BelongsToCurrentThread()); |
585 | 584 |
586 if (last_stage_status != PIPELINE_OK) { | 585 if (last_stage_status != PIPELINE_OK) { |
587 // Currently only VideoDecoders have a recoverable error code. | 586 SetError(last_stage_status); |
588 if (state_ == kInitVideoDecoder && | 587 return; |
589 last_stage_status == DECODER_ERROR_NOT_SUPPORTED) { | |
590 state_ = kInitAudioRenderer; | |
591 } else { | |
592 SetError(last_stage_status); | |
593 return; | |
594 } | |
595 } | 588 } |
596 | 589 |
597 // If we have received the stop or error signal, return immediately. | 590 // If we have received the stop or error signal, return immediately. |
598 if (!stop_cb_.is_null() || state_ == kStopped || !IsPipelineOk()) | 591 if (!stop_cb_.is_null() || state_ == kStopped || !IsPipelineOk()) |
599 return; | 592 return; |
600 | 593 |
601 DCHECK(state_ == kInitDemuxer || | 594 DCHECK(state_ == kInitDemuxer || |
602 state_ == kInitAudioDecoder || | 595 state_ == kInitAudioDecoder || |
603 state_ == kInitAudioRenderer || | 596 state_ == kInitAudioRenderer || |
604 state_ == kInitVideoDecoder || | |
605 state_ == kInitVideoRenderer); | 597 state_ == kInitVideoRenderer); |
606 | 598 |
607 // Demuxer created, create audio decoder. | 599 // Demuxer created, create audio decoder. |
608 if (state_ == kInitDemuxer) { | 600 if (state_ == kInitDemuxer) { |
609 SetState(kInitAudioDecoder); | 601 SetState(kInitAudioDecoder); |
610 // If this method returns false, then there's no audio stream. | 602 // If this method returns false, then there's no audio stream. |
611 if (InitializeAudioDecoder(demuxer_)) | 603 if (InitializeAudioDecoder(demuxer_)) |
612 return; | 604 return; |
613 } | 605 } |
614 | 606 |
615 // Assuming audio decoder was created, create audio renderer. | 607 // Assuming audio decoder was created, create audio renderer. |
616 if (state_ == kInitAudioDecoder) { | 608 if (state_ == kInitAudioDecoder) { |
617 SetState(kInitAudioRenderer); | 609 SetState(kInitAudioRenderer); |
618 | 610 |
619 // Returns false if there's no audio stream. | 611 // Returns false if there's no audio stream. |
620 if (InitializeAudioRenderer(pipeline_init_state_->audio_decoder)) { | 612 if (InitializeAudioRenderer(pipeline_init_state_->audio_decoder)) { |
621 base::AutoLock auto_lock(lock_); | 613 base::AutoLock auto_lock(lock_); |
622 has_audio_ = true; | 614 has_audio_ = true; |
623 return; | 615 return; |
624 } | 616 } |
625 } | 617 } |
626 | 618 |
627 // Assuming audio renderer was created, create video decoder. | 619 // Assuming audio renderer was created, create video renderer. |
628 if (state_ == kInitAudioRenderer) { | 620 if (state_ == kInitAudioRenderer) { |
629 // Then perform the stage of initialization, i.e. initialize video decoder. | |
630 SetState(kInitVideoDecoder); | |
631 if (InitializeVideoDecoder(demuxer_)) | |
632 return; | |
633 } | |
634 | |
635 // Assuming video decoder was created, create video renderer. | |
636 if (state_ == kInitVideoDecoder) { | |
637 SetState(kInitVideoRenderer); | 621 SetState(kInitVideoRenderer); |
638 if (InitializeVideoRenderer(pipeline_init_state_->video_decoder)) { | 622 if (InitializeVideoRenderer(demuxer_->GetStream(DemuxerStream::VIDEO))) { |
639 base::AutoLock auto_lock(lock_); | 623 base::AutoLock auto_lock(lock_); |
640 has_video_ = true; | 624 has_video_ = true; |
641 return; | 625 return; |
642 } | 626 } |
643 } | 627 } |
644 | 628 |
645 if (state_ == kInitVideoRenderer) { | 629 if (state_ == kInitVideoRenderer) { |
646 if (!IsPipelineOk() || !(HasAudio() || HasVideo())) { | 630 if (!IsPipelineOk() || !(HasAudio() || HasVideo())) { |
647 SetError(PIPELINE_ERROR_COULD_NOT_RENDER); | 631 SetError(PIPELINE_ERROR_COULD_NOT_RENDER); |
648 return; | 632 return; |
(...skipping 27 matching lines...) Expand all Loading... |
676 // additional calls, however most of this logic will be changing. | 660 // additional calls, however most of this logic will be changing. |
677 void Pipeline::StopTask(const base::Closure& stop_cb) { | 661 void Pipeline::StopTask(const base::Closure& stop_cb) { |
678 DCHECK(message_loop_->BelongsToCurrentThread()); | 662 DCHECK(message_loop_->BelongsToCurrentThread()); |
679 DCHECK(stop_cb_.is_null()); | 663 DCHECK(stop_cb_.is_null()); |
680 | 664 |
681 if (state_ == kStopped) { | 665 if (state_ == kStopped) { |
682 stop_cb.Run(); | 666 stop_cb.Run(); |
683 return; | 667 return; |
684 } | 668 } |
685 | 669 |
686 if (video_decoder_) { | 670 if (video_renderer_) |
687 video_decoder_->PrepareForShutdownHack(); | 671 video_renderer_->PrepareForShutdownHack(); |
688 video_decoder_ = NULL; | |
689 } | |
690 | 672 |
691 if (tearing_down_ && status_ != PIPELINE_OK) { | 673 if (tearing_down_ && status_ != PIPELINE_OK) { |
692 // If we are stopping due to SetError(), stop normally instead of | 674 // If we are stopping due to SetError(), stop normally instead of |
693 // going to error state and calling |error_cb_|. This converts | 675 // going to error state and calling |error_cb_|. This converts |
694 // the teardown in progress from an error teardown into one that acts | 676 // the teardown in progress from an error teardown into one that acts |
695 // like the error never occurred. | 677 // like the error never occurred. |
696 base::AutoLock auto_lock(lock_); | 678 base::AutoLock auto_lock(lock_); |
697 status_ = PIPELINE_OK; | 679 status_ = PIPELINE_OK; |
698 } | 680 } |
699 | 681 |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
963 break; | 945 break; |
964 case kFlushing: | 946 case kFlushing: |
965 SetState(kStopping); | 947 SetState(kStopping); |
966 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); | 948 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); |
967 break; | 949 break; |
968 | 950 |
969 case kCreated: | 951 case kCreated: |
970 case kInitDemuxer: | 952 case kInitDemuxer: |
971 case kInitAudioDecoder: | 953 case kInitAudioDecoder: |
972 case kInitAudioRenderer: | 954 case kInitAudioRenderer: |
973 case kInitVideoDecoder: | |
974 case kInitVideoRenderer: | 955 case kInitVideoRenderer: |
975 case kSeeking: | 956 case kSeeking: |
976 case kStarting: | 957 case kStarting: |
977 case kStopped: | 958 case kStopped: |
978 case kStarted: | 959 case kStarted: |
979 NOTREACHED() << "Unexpected state for teardown: " << state_; | 960 NOTREACHED() << "Unexpected state for teardown: " << state_; |
980 break; | 961 break; |
981 // default: intentionally left out to force new states to cause compiler | 962 // default: intentionally left out to force new states to cause compiler |
982 // errors. | 963 // errors. |
983 }; | 964 }; |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1057 return false; | 1038 return false; |
1058 } | 1039 } |
1059 | 1040 |
1060 pipeline_init_state_->audio_decoder->Initialize( | 1041 pipeline_init_state_->audio_decoder->Initialize( |
1061 stream, | 1042 stream, |
1062 base::Bind(&Pipeline::OnFilterInitialize, this), | 1043 base::Bind(&Pipeline::OnFilterInitialize, this), |
1063 base::Bind(&Pipeline::OnUpdateStatistics, this)); | 1044 base::Bind(&Pipeline::OnUpdateStatistics, this)); |
1064 return true; | 1045 return true; |
1065 } | 1046 } |
1066 | 1047 |
1067 bool Pipeline::InitializeVideoDecoder( | |
1068 const scoped_refptr<Demuxer>& demuxer) { | |
1069 DCHECK(message_loop_->BelongsToCurrentThread()); | |
1070 DCHECK(IsPipelineOk()); | |
1071 DCHECK(demuxer); | |
1072 | |
1073 scoped_refptr<DemuxerStream> stream = | |
1074 demuxer->GetStream(DemuxerStream::VIDEO); | |
1075 | |
1076 if (!stream) | |
1077 return false; | |
1078 | |
1079 filter_collection_->SelectVideoDecoder(&pipeline_init_state_->video_decoder); | |
1080 | |
1081 if (!pipeline_init_state_->video_decoder) { | |
1082 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | |
1083 return false; | |
1084 } | |
1085 | |
1086 pipeline_init_state_->video_decoder->Initialize( | |
1087 stream, | |
1088 base::Bind(&Pipeline::OnFilterInitialize, this), | |
1089 base::Bind(&Pipeline::OnUpdateStatistics, this)); | |
1090 | |
1091 video_decoder_ = pipeline_init_state_->video_decoder; | |
1092 return true; | |
1093 } | |
1094 | |
1095 bool Pipeline::InitializeAudioRenderer( | 1048 bool Pipeline::InitializeAudioRenderer( |
1096 const scoped_refptr<AudioDecoder>& decoder) { | 1049 const scoped_refptr<AudioDecoder>& decoder) { |
1097 DCHECK(message_loop_->BelongsToCurrentThread()); | 1050 DCHECK(message_loop_->BelongsToCurrentThread()); |
1098 DCHECK(IsPipelineOk()); | 1051 DCHECK(IsPipelineOk()); |
1099 | 1052 |
1100 if (!decoder) | 1053 if (!decoder) |
1101 return false; | 1054 return false; |
1102 | 1055 |
1103 filter_collection_->SelectAudioRenderer(&audio_renderer_); | 1056 filter_collection_->SelectAudioRenderer(&audio_renderer_); |
1104 if (!audio_renderer_) { | 1057 if (!audio_renderer_) { |
1105 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 1058 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); |
1106 return false; | 1059 return false; |
1107 } | 1060 } |
1108 | 1061 |
1109 audio_renderer_->Initialize( | 1062 audio_renderer_->Initialize( |
1110 decoder, | 1063 decoder, |
1111 base::Bind(&Pipeline::OnFilterInitialize, this), | 1064 base::Bind(&Pipeline::OnFilterInitialize, this), |
1112 base::Bind(&Pipeline::OnAudioUnderflow, this), | 1065 base::Bind(&Pipeline::OnAudioUnderflow, this), |
1113 base::Bind(&Pipeline::OnAudioTimeUpdate, this), | 1066 base::Bind(&Pipeline::OnAudioTimeUpdate, this), |
1114 base::Bind(&Pipeline::OnAudioRendererEnded, this), | 1067 base::Bind(&Pipeline::OnAudioRendererEnded, this), |
1115 base::Bind(&Pipeline::OnAudioDisabled, this), | 1068 base::Bind(&Pipeline::OnAudioDisabled, this), |
1116 base::Bind(&Pipeline::SetError, this)); | 1069 base::Bind(&Pipeline::SetError, this)); |
1117 return true; | 1070 return true; |
1118 } | 1071 } |
1119 | 1072 |
1120 bool Pipeline::InitializeVideoRenderer( | 1073 bool Pipeline::InitializeVideoRenderer( |
1121 const scoped_refptr<VideoDecoder>& decoder) { | 1074 const scoped_refptr<DemuxerStream>& stream) { |
1122 DCHECK(message_loop_->BelongsToCurrentThread()); | 1075 DCHECK(message_loop_->BelongsToCurrentThread()); |
1123 DCHECK(IsPipelineOk()); | 1076 DCHECK(IsPipelineOk()); |
1124 | 1077 |
1125 if (!decoder) | 1078 if (!stream) |
1126 return false; | 1079 return false; |
1127 | 1080 |
1128 filter_collection_->SelectVideoRenderer(&video_renderer_); | 1081 filter_collection_->SelectVideoRenderer(&video_renderer_); |
1129 if (!video_renderer_) { | 1082 if (!video_renderer_) { |
1130 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 1083 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); |
1131 return false; | 1084 return false; |
1132 } | 1085 } |
1133 | 1086 |
1134 video_renderer_->Initialize( | 1087 video_renderer_->Initialize( |
1135 decoder, | 1088 stream, |
| 1089 *filter_collection_->GetVideoDecoders(), |
1136 base::Bind(&Pipeline::OnFilterInitialize, this), | 1090 base::Bind(&Pipeline::OnFilterInitialize, this), |
1137 base::Bind(&Pipeline::OnUpdateStatistics, this), | 1091 base::Bind(&Pipeline::OnUpdateStatistics, this), |
1138 base::Bind(&Pipeline::OnVideoTimeUpdate, this), | 1092 base::Bind(&Pipeline::OnVideoTimeUpdate, this), |
1139 base::Bind(&Pipeline::OnNaturalVideoSizeChanged, this), | 1093 base::Bind(&Pipeline::OnNaturalVideoSizeChanged, this), |
1140 base::Bind(&Pipeline::OnVideoRendererEnded, this), | 1094 base::Bind(&Pipeline::OnVideoRendererEnded, this), |
1141 base::Bind(&Pipeline::SetError, this), | 1095 base::Bind(&Pipeline::SetError, this), |
1142 base::Bind(&Pipeline::GetMediaTime, this), | 1096 base::Bind(&Pipeline::GetMediaTime, this), |
1143 base::Bind(&Pipeline::GetMediaDuration, this)); | 1097 base::Bind(&Pipeline::GetMediaDuration, this)); |
| 1098 filter_collection_->GetVideoDecoders()->clear(); |
1144 return true; | 1099 return true; |
1145 } | 1100 } |
1146 | 1101 |
1147 void Pipeline::TearDownPipeline() { | 1102 void Pipeline::TearDownPipeline() { |
1148 DCHECK(message_loop_->BelongsToCurrentThread()); | 1103 DCHECK(message_loop_->BelongsToCurrentThread()); |
1149 DCHECK_NE(kStopped, state_); | 1104 DCHECK_NE(kStopped, state_); |
1150 | 1105 |
1151 // We're either... | 1106 // We're either... |
1152 // 1) ...tearing down due to Stop() (it doesn't set tearing_down_) | 1107 // 1) ...tearing down due to Stop() (it doesn't set tearing_down_) |
1153 // 2) ...tearing down due to an error (it does set tearing_down_) | 1108 // 2) ...tearing down due to an error (it does set tearing_down_) |
(...skipping 13 matching lines...) Expand all Loading... |
1167 SetState(kStopped); | 1122 SetState(kStopped); |
1168 // Need to put this in the message loop to make sure that it comes | 1123 // Need to put this in the message loop to make sure that it comes |
1169 // after any pending callback tasks that are already queued. | 1124 // after any pending callback tasks that are already queued. |
1170 message_loop_->PostTask(FROM_HERE, base::Bind( | 1125 message_loop_->PostTask(FROM_HERE, base::Bind( |
1171 &Pipeline::FinishDestroyingFiltersTask, this)); | 1126 &Pipeline::FinishDestroyingFiltersTask, this)); |
1172 break; | 1127 break; |
1173 | 1128 |
1174 case kInitDemuxer: | 1129 case kInitDemuxer: |
1175 case kInitAudioDecoder: | 1130 case kInitAudioDecoder: |
1176 case kInitAudioRenderer: | 1131 case kInitAudioRenderer: |
1177 case kInitVideoDecoder: | |
1178 case kInitVideoRenderer: | 1132 case kInitVideoRenderer: |
1179 // Make it look like initialization was successful. | 1133 // Make it look like initialization was successful. |
1180 filter_collection_.reset(); | 1134 filter_collection_.reset(); |
1181 pipeline_init_state_.reset(); | 1135 pipeline_init_state_.reset(); |
1182 | 1136 |
1183 SetState(kStopping); | 1137 SetState(kStopping); |
1184 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); | 1138 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); |
1185 | 1139 |
1186 FinishInitialization(); | 1140 FinishInitialization(); |
1187 break; | 1141 break; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1256 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { | 1210 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { |
1257 lock_.AssertAcquired(); | 1211 lock_.AssertAcquired(); |
1258 if (!waiting_for_clock_update_) | 1212 if (!waiting_for_clock_update_) |
1259 return; | 1213 return; |
1260 | 1214 |
1261 waiting_for_clock_update_ = false; | 1215 waiting_for_clock_update_ = false; |
1262 clock_->Play(); | 1216 clock_->Play(); |
1263 } | 1217 } |
1264 | 1218 |
1265 } // namespace media | 1219 } // namespace media |
OLD | NEW |