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/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
13 #include "base/message_loop.h" | 13 #include "base/message_loop.h" |
14 #include "base/stl_util.h" | 14 #include "base/stl_util.h" |
15 #include "base/string_util.h" | 15 #include "base/string_util.h" |
16 #include "base/synchronization/condition_variable.h" | 16 #include "base/synchronization/condition_variable.h" |
17 #include "media/base/audio_decoder.h" | 17 #include "media/base/audio_decoder.h" |
18 #include "media/base/clock.h" | 18 #include "media/base/clock.h" |
19 #include "media/base/composite_filter.h" | 19 #include "media/base/composite_filter.h" |
20 #include "media/base/composite_filter.h" | |
21 #include "media/base/filter_collection.h" | 20 #include "media/base/filter_collection.h" |
22 #include "media/base/filters.h" | 21 #include "media/base/filters.h" |
23 #include "media/base/media_log.h" | 22 #include "media/base/media_log.h" |
24 | 23 |
25 namespace media { | 24 namespace media { |
26 | 25 |
27 PipelineStatusNotification::PipelineStatusNotification() | 26 PipelineStatusNotification::PipelineStatusNotification() |
28 : cv_(&lock_), status_(PIPELINE_OK), notified_(false) { | 27 : cv_(&lock_), status_(PIPELINE_OK), notified_(false) { |
29 } | 28 } |
30 | 29 |
(...skipping 610 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
641 // TODO(hclam): InitializeTask() is now starting the pipeline asynchronously. It | 640 // TODO(hclam): InitializeTask() is now starting the pipeline asynchronously. It |
642 // works like a big state change table. If we no longer need to start filters | 641 // works like a big state change table. If we no longer need to start filters |
643 // in order, we need to get rid of all the state change. | 642 // in order, we need to get rid of all the state change. |
644 void Pipeline::InitializeTask(PipelineStatus last_stage_status) { | 643 void Pipeline::InitializeTask(PipelineStatus last_stage_status) { |
645 DCHECK_EQ(MessageLoop::current(), message_loop_); | 644 DCHECK_EQ(MessageLoop::current(), message_loop_); |
646 | 645 |
647 if (last_stage_status != PIPELINE_OK) { | 646 if (last_stage_status != PIPELINE_OK) { |
648 // Currently only VideoDecoders have a recoverable error code. | 647 // Currently only VideoDecoders have a recoverable error code. |
649 if (state_ == kInitVideoDecoder && | 648 if (state_ == kInitVideoDecoder && |
650 last_stage_status == DECODER_ERROR_NOT_SUPPORTED) { | 649 last_stage_status == DECODER_ERROR_NOT_SUPPORTED) { |
651 pipeline_init_state_->composite->RemoveFilter( | |
652 pipeline_init_state_->video_decoder.get()); | |
653 state_ = kInitAudioRenderer; | 650 state_ = kInitAudioRenderer; |
654 } else { | 651 } else { |
655 SetError(last_stage_status); | 652 SetError(last_stage_status); |
656 } | 653 } |
657 } | 654 } |
658 | 655 |
659 // If we have received the stop or error signal, return immediately. | 656 // If we have received the stop or error signal, return immediately. |
660 if (IsPipelineStopPending() || IsPipelineStopped() || !IsPipelineOk()) | 657 if (IsPipelineStopPending() || IsPipelineStopped() || !IsPipelineOk()) |
661 return; | 658 return; |
662 | 659 |
(...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1154 clock_->SetTime(demuxer_->GetStartTime(), demuxer_->GetStartTime()); | 1151 clock_->SetTime(demuxer_->GetStartTime(), demuxer_->GetStartTime()); |
1155 } | 1152 } |
1156 | 1153 |
1157 OnFilterInitialize(PIPELINE_OK); | 1154 OnFilterInitialize(PIPELINE_OK); |
1158 } | 1155 } |
1159 | 1156 |
1160 bool Pipeline::InitializeAudioDecoder( | 1157 bool Pipeline::InitializeAudioDecoder( |
1161 const scoped_refptr<Demuxer>& demuxer) { | 1158 const scoped_refptr<Demuxer>& demuxer) { |
1162 DCHECK_EQ(MessageLoop::current(), message_loop_); | 1159 DCHECK_EQ(MessageLoop::current(), message_loop_); |
1163 DCHECK(IsPipelineOk()); | 1160 DCHECK(IsPipelineOk()); |
| 1161 DCHECK(demuxer); |
1164 | 1162 |
1165 scoped_refptr<DemuxerStream> stream = | 1163 scoped_refptr<DemuxerStream> stream = |
1166 demuxer->GetStream(DemuxerStream::AUDIO); | 1164 demuxer->GetStream(DemuxerStream::AUDIO); |
1167 | 1165 |
1168 if (!stream) | 1166 if (!stream) |
1169 return false; | 1167 return false; |
1170 | 1168 |
1171 filter_collection_->SelectAudioDecoder(&pipeline_init_state_->audio_decoder); | 1169 filter_collection_->SelectAudioDecoder(&pipeline_init_state_->audio_decoder); |
1172 | 1170 |
1173 if (!pipeline_init_state_->audio_decoder) { | 1171 if (!pipeline_init_state_->audio_decoder) { |
1174 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 1172 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); |
1175 return false; | 1173 return false; |
1176 } | 1174 } |
1177 | 1175 |
1178 pipeline_init_state_->audio_decoder->Initialize( | 1176 pipeline_init_state_->audio_decoder->Initialize( |
1179 stream, | 1177 stream, |
1180 base::Bind(&Pipeline::OnFilterInitialize, this), | 1178 base::Bind(&Pipeline::OnFilterInitialize, this), |
1181 base::Bind(&Pipeline::OnUpdateStatistics, this)); | 1179 base::Bind(&Pipeline::OnUpdateStatistics, this)); |
1182 return true; | 1180 return true; |
1183 } | 1181 } |
1184 | 1182 |
1185 bool Pipeline::InitializeVideoDecoder( | 1183 bool Pipeline::InitializeVideoDecoder( |
1186 const scoped_refptr<Demuxer>& demuxer) { | 1184 const scoped_refptr<Demuxer>& demuxer) { |
1187 DCHECK_EQ(MessageLoop::current(), message_loop_); | 1185 DCHECK_EQ(MessageLoop::current(), message_loop_); |
1188 DCHECK(IsPipelineOk()); | 1186 DCHECK(IsPipelineOk()); |
| 1187 DCHECK(demuxer); |
1189 | 1188 |
1190 scoped_refptr<DemuxerStream> stream; | 1189 scoped_refptr<DemuxerStream> stream = |
| 1190 demuxer->GetStream(DemuxerStream::VIDEO); |
1191 | 1191 |
1192 if (demuxer) { | 1192 if (!stream) |
1193 stream = demuxer->GetStream(DemuxerStream::VIDEO); | 1193 return false; |
1194 | 1194 |
1195 if (!stream) | 1195 filter_collection_->SelectVideoDecoder(&pipeline_init_state_->video_decoder); |
1196 return false; | |
1197 } | |
1198 | 1196 |
1199 filter_collection_->SelectVideoDecoder(&video_decoder_); | 1197 if (!pipeline_init_state_->video_decoder) { |
1200 | |
1201 if (!video_decoder_) { | |
1202 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 1198 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); |
1203 return false; | 1199 return false; |
1204 } | 1200 } |
1205 | 1201 |
1206 if (!PrepareFilter(video_decoder_)) | 1202 pipeline_init_state_->video_decoder->Initialize( |
1207 return false; | |
1208 | |
1209 pipeline_init_state_->video_decoder = video_decoder_; | |
1210 video_decoder_->Initialize( | |
1211 stream, | 1203 stream, |
1212 base::Bind(&Pipeline::OnFilterInitialize, this), | 1204 base::Bind(&Pipeline::OnFilterInitialize, this), |
1213 base::Bind(&Pipeline::OnUpdateStatistics, this)); | 1205 base::Bind(&Pipeline::OnUpdateStatistics, this)); |
| 1206 |
| 1207 video_decoder_ = pipeline_init_state_->video_decoder; |
1214 return true; | 1208 return true; |
1215 } | 1209 } |
1216 | 1210 |
1217 bool Pipeline::InitializeAudioRenderer( | 1211 bool Pipeline::InitializeAudioRenderer( |
1218 const scoped_refptr<AudioDecoder>& decoder) { | 1212 const scoped_refptr<AudioDecoder>& decoder) { |
1219 DCHECK_EQ(MessageLoop::current(), message_loop_); | 1213 DCHECK_EQ(MessageLoop::current(), message_loop_); |
1220 DCHECK(IsPipelineOk()); | 1214 DCHECK(IsPipelineOk()); |
1221 | 1215 |
1222 if (!decoder) | 1216 if (!decoder) |
1223 return false; | 1217 return false; |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1348 &Pipeline::OnDemuxerStopDone, this, callback)); | 1342 &Pipeline::OnDemuxerStopDone, this, callback)); |
1349 return; | 1343 return; |
1350 } | 1344 } |
1351 | 1345 |
1352 if (pipeline_filter_) { | 1346 if (pipeline_filter_) { |
1353 pipeline_filter_->Stop(callback); | 1347 pipeline_filter_->Stop(callback); |
1354 return; | 1348 return; |
1355 } | 1349 } |
1356 | 1350 |
1357 callback.Run(); | 1351 callback.Run(); |
1358 | |
1359 } | 1352 } |
1360 | 1353 |
1361 void Pipeline::DoSeek(base::TimeDelta seek_timestamp) { | 1354 void Pipeline::DoSeek(base::TimeDelta seek_timestamp) { |
1362 // TODO(acolwell) : We might be able to convert this if (demuxer_) into a | 1355 // TODO(acolwell) : We might be able to convert this if (demuxer_) into a |
1363 // DCHECK(). Further investigation is needed to make sure this won't introduce | 1356 // DCHECK(). Further investigation is needed to make sure this won't introduce |
1364 // a bug. | 1357 // a bug. |
1365 if (demuxer_) { | 1358 if (demuxer_) { |
1366 demuxer_->Seek(seek_timestamp, base::Bind( | 1359 demuxer_->Seek(seek_timestamp, base::Bind( |
1367 &Pipeline::OnDemuxerSeekDone, this, seek_timestamp)); | 1360 &Pipeline::OnDemuxerSeekDone, this, seek_timestamp)); |
1368 return; | 1361 return; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1417 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { | 1410 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { |
1418 lock_.AssertAcquired(); | 1411 lock_.AssertAcquired(); |
1419 if (!waiting_for_clock_update_) | 1412 if (!waiting_for_clock_update_) |
1420 return; | 1413 return; |
1421 | 1414 |
1422 waiting_for_clock_update_ = false; | 1415 waiting_for_clock_update_ = false; |
1423 clock_->Play(); | 1416 clock_->Play(); |
1424 } | 1417 } |
1425 | 1418 |
1426 } // namespace media | 1419 } // namespace media |
OLD | NEW |