Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 // TODO(scherkus): clean up PipelineImpl... too many crazy function names, | 5 // TODO(scherkus): clean up PipelineImpl... too many crazy function names, |
| 6 // potential deadlocks, etc... | 6 // potential deadlocks, etc... |
| 7 | 7 |
| 8 #include "media/base/pipeline_impl.h" | 8 #include "media/base/pipeline_impl.h" |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| (...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 600 DCHECK(IsRunning()); | 600 DCHECK(IsRunning()); |
| 601 | 601 |
| 602 // Disable renderer on the message loop. | 602 // Disable renderer on the message loop. |
| 603 message_loop_->PostTask(FROM_HERE, | 603 message_loop_->PostTask(FROM_HERE, |
| 604 base::Bind(&PipelineImpl::DisableAudioRendererTask, this)); | 604 base::Bind(&PipelineImpl::DisableAudioRendererTask, this)); |
| 605 media_log_->AddEvent( | 605 media_log_->AddEvent( |
| 606 media_log_->CreateEvent(MediaLogEvent::AUDIO_RENDERER_DISABLED)); | 606 media_log_->CreateEvent(MediaLogEvent::AUDIO_RENDERER_DISABLED)); |
| 607 } | 607 } |
| 608 | 608 |
| 609 // Called from any thread. | 609 // Called from any thread. |
| 610 void PipelineImpl::OnFilterInitialize() { | 610 void PipelineImpl::OnFilterInitialize(PipelineStatus status) { |
| 611 // Continue the initialize task by proceeding to the next stage. | 611 // Continue the initialize task by proceeding to the next stage. |
| 612 message_loop_->PostTask(FROM_HERE, | 612 message_loop_->PostTask( |
| 613 base::Bind(&PipelineImpl::InitializeTask, this)); | 613 FROM_HERE, base::Bind(&PipelineImpl::InitializeTask, this, status)); |
| 614 } | 614 } |
| 615 | 615 |
| 616 // Called from any thread. | 616 // Called from any thread. |
| 617 void PipelineImpl::OnFilterStateTransition() { | 617 void PipelineImpl::OnFilterStateTransition() { |
| 618 message_loop_->PostTask(FROM_HERE, | 618 message_loop_->PostTask(FROM_HERE, |
| 619 base::Bind(&PipelineImpl::FilterStateTransitionTask, this)); | 619 base::Bind(&PipelineImpl::FilterStateTransitionTask, this)); |
| 620 } | 620 } |
| 621 | 621 |
| 622 // Called from any thread. | 622 // Called from any thread. |
| 623 // This method makes the FilterStatusCB behave like a Closure. It | 623 // This method makes the FilterStatusCB behave like a Closure. It |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 675 // VideoDecoder to the Demuxer's video stream, and then connects the | 675 // VideoDecoder to the Demuxer's video stream, and then connects the |
| 676 // VideoDecoder to a VideoRenderer. | 676 // VideoDecoder to a VideoRenderer. |
| 677 // | 677 // |
| 678 // When all required filters have been created and have called their | 678 // When all required filters have been created and have called their |
| 679 // FilterHost's InitializationComplete() method, the pipeline will update its | 679 // FilterHost's InitializationComplete() method, the pipeline will update its |
| 680 // state to kStarted and |init_callback_|, will be executed. | 680 // state to kStarted and |init_callback_|, will be executed. |
| 681 // | 681 // |
| 682 // TODO(hclam): InitializeTask() is now starting the pipeline asynchronously. It | 682 // TODO(hclam): InitializeTask() is now starting the pipeline asynchronously. It |
| 683 // works like a big state change table. If we no longer need to start filters | 683 // works like a big state change table. If we no longer need to start filters |
| 684 // in order, we need to get rid of all the state change. | 684 // in order, we need to get rid of all the state change. |
| 685 void PipelineImpl::InitializeTask() { | 685 void PipelineImpl::InitializeTask(PipelineStatus last_stage_status) { |
| 686 DCHECK_EQ(MessageLoop::current(), message_loop_); | 686 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 687 | 687 |
| 688 if (last_stage_status != PIPELINE_OK) { | |
| 689 // Currently only VideoDecoders have a recoverable error code. | |
| 690 if (state_ == kInitVideoDecoder && | |
| 691 last_stage_status == DECODER_ERROR_NOT_SUPPORTED) { | |
| 692 bool discarded = DiscardFilter(pipeline_init_state_->video_decoder_); | |
| 693 DCHECK(discarded); | |
| 694 state_ = kInitAudioRenderer; | |
|
scherkus (not reviewing)
2011/12/06 00:27:44
does this fall back to software or is that handled
Ami GONE FROM CHROMIUM
2011/12/07 00:03:04
The former.
| |
| 695 } else { | |
| 696 SetError(last_stage_status); | |
| 697 } | |
| 698 } | |
| 699 | |
| 688 // If we have received the stop or error signal, return immediately. | 700 // If we have received the stop or error signal, return immediately. |
| 689 if (IsPipelineStopPending() || IsPipelineStopped() || !IsPipelineOk()) | 701 if (IsPipelineStopPending() || IsPipelineStopped() || !IsPipelineOk()) |
| 690 return; | 702 return; |
| 691 | 703 |
| 692 DCHECK(state_ == kInitDemuxer || | 704 DCHECK(state_ == kInitDemuxer || |
| 693 state_ == kInitAudioDecoder || | 705 state_ == kInitAudioDecoder || |
| 694 state_ == kInitAudioRenderer || | 706 state_ == kInitAudioRenderer || |
| 695 state_ == kInitVideoDecoder || | 707 state_ == kInitVideoDecoder || |
| 696 state_ == kInitVideoRenderer); | 708 state_ == kInitVideoRenderer); |
| 697 | 709 |
| (...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1121 stop_cb.Run(status_); | 1133 stop_cb.Run(status_); |
| 1122 } | 1134 } |
| 1123 } | 1135 } |
| 1124 | 1136 |
| 1125 tearing_down_ = false; | 1137 tearing_down_ = false; |
| 1126 error_caused_teardown_ = false; | 1138 error_caused_teardown_ = false; |
| 1127 } | 1139 } |
| 1128 | 1140 |
| 1129 bool PipelineImpl::PrepareFilter(scoped_refptr<Filter> filter) { | 1141 bool PipelineImpl::PrepareFilter(scoped_refptr<Filter> filter) { |
| 1130 bool ret = pipeline_init_state_->composite_->AddFilter(filter.get()); | 1142 bool ret = pipeline_init_state_->composite_->AddFilter(filter.get()); |
| 1131 | 1143 if (!ret) |
| 1132 if (!ret) { | |
| 1133 SetError(PIPELINE_ERROR_INITIALIZATION_FAILED); | 1144 SetError(PIPELINE_ERROR_INITIALIZATION_FAILED); |
| 1134 } | |
| 1135 return ret; | 1145 return ret; |
| 1136 } | 1146 } |
| 1137 | 1147 |
| 1148 bool PipelineImpl::DiscardFilter(scoped_refptr<Filter> filter) { | |
| 1149 bool ret = pipeline_init_state_->composite_->RemoveFilter(filter.get()); | |
|
scherkus (not reviewing)
2011/12/06 00:27:44
can we CHECK() inside of methods like RemoveFilter
Ami GONE FROM CHROMIUM
2011/12/07 00:03:04
Hell yes we can!
(bonus points for the use of "fr
| |
| 1150 if (!ret) | |
| 1151 SetError(PIPELINE_ERROR_INITIALIZATION_FAILED); | |
| 1152 return ret; | |
| 1153 } | |
| 1154 | |
| 1138 void PipelineImpl::InitializeDemuxer() { | 1155 void PipelineImpl::InitializeDemuxer() { |
| 1139 DCHECK_EQ(MessageLoop::current(), message_loop_); | 1156 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 1140 DCHECK(IsPipelineOk()); | 1157 DCHECK(IsPipelineOk()); |
| 1141 | 1158 |
| 1142 filter_collection_->GetDemuxerFactory()->Build( | 1159 filter_collection_->GetDemuxerFactory()->Build( |
| 1143 url_, base::Bind(&PipelineImpl::OnDemuxerBuilt, this)); | 1160 url_, base::Bind(&PipelineImpl::OnDemuxerBuilt, this)); |
| 1144 } | 1161 } |
| 1145 | 1162 |
| 1146 void PipelineImpl::OnDemuxerBuilt(PipelineStatus status, Demuxer* demuxer) { | 1163 void PipelineImpl::OnDemuxerBuilt(PipelineStatus status, Demuxer* demuxer) { |
| 1147 if (MessageLoop::current() != message_loop_) { | 1164 if (MessageLoop::current() != message_loop_) { |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1165 demuxer_ = demuxer; | 1182 demuxer_ = demuxer; |
| 1166 demuxer_->set_host(this); | 1183 demuxer_->set_host(this); |
| 1167 | 1184 |
| 1168 { | 1185 { |
| 1169 base::AutoLock auto_lock(lock_); | 1186 base::AutoLock auto_lock(lock_); |
| 1170 // We do not want to start the clock running. We only want to set the base | 1187 // We do not want to start the clock running. We only want to set the base |
| 1171 // media time so our timestamp calculations will be correct. | 1188 // media time so our timestamp calculations will be correct. |
| 1172 clock_->SetTime(demuxer_->GetStartTime()); | 1189 clock_->SetTime(demuxer_->GetStartTime()); |
| 1173 } | 1190 } |
| 1174 | 1191 |
| 1175 OnFilterInitialize(); | 1192 OnFilterInitialize(PIPELINE_OK); |
| 1176 } | 1193 } |
| 1177 | 1194 |
| 1178 bool PipelineImpl::InitializeAudioDecoder( | 1195 bool PipelineImpl::InitializeAudioDecoder( |
| 1179 const scoped_refptr<Demuxer>& demuxer) { | 1196 const scoped_refptr<Demuxer>& demuxer) { |
| 1180 DCHECK_EQ(MessageLoop::current(), message_loop_); | 1197 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 1181 DCHECK(IsPipelineOk()); | 1198 DCHECK(IsPipelineOk()); |
| 1182 | 1199 |
| 1183 scoped_refptr<DemuxerStream> stream = | 1200 scoped_refptr<DemuxerStream> stream = |
| 1184 demuxer->GetStream(DemuxerStream::AUDIO); | 1201 demuxer->GetStream(DemuxerStream::AUDIO); |
| 1185 | 1202 |
| 1186 if (!stream) | 1203 if (!stream) |
| 1187 return false; | 1204 return false; |
| 1188 | 1205 |
| 1189 scoped_refptr<AudioDecoder> audio_decoder; | 1206 scoped_refptr<AudioDecoder> audio_decoder; |
| 1190 filter_collection_->SelectAudioDecoder(&audio_decoder); | 1207 filter_collection_->SelectAudioDecoder(&audio_decoder); |
| 1191 | 1208 |
| 1192 if (!audio_decoder) { | 1209 if (!audio_decoder) { |
| 1193 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 1210 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); |
| 1194 return false; | 1211 return false; |
| 1195 } | 1212 } |
| 1196 | 1213 |
| 1197 if (!PrepareFilter(audio_decoder)) | 1214 if (!PrepareFilter(audio_decoder)) |
| 1198 return false; | 1215 return false; |
| 1199 | 1216 |
| 1200 pipeline_init_state_->audio_decoder_ = audio_decoder; | 1217 pipeline_init_state_->audio_decoder_ = audio_decoder; |
| 1201 audio_decoder->Initialize( | 1218 audio_decoder->Initialize( |
| 1202 stream, | 1219 stream, |
| 1203 base::Bind(&PipelineImpl::OnFilterInitialize, this), | 1220 base::Bind(&PipelineImpl::OnFilterInitialize, this, PIPELINE_OK), |
| 1204 base::Bind(&PipelineImpl::OnUpdateStatistics, this)); | 1221 base::Bind(&PipelineImpl::OnUpdateStatistics, this)); |
| 1205 return true; | 1222 return true; |
| 1206 } | 1223 } |
| 1207 | 1224 |
| 1208 bool PipelineImpl::InitializeVideoDecoder( | 1225 bool PipelineImpl::InitializeVideoDecoder( |
| 1209 const scoped_refptr<Demuxer>& demuxer) { | 1226 const scoped_refptr<Demuxer>& demuxer) { |
| 1210 DCHECK_EQ(MessageLoop::current(), message_loop_); | 1227 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 1211 DCHECK(IsPipelineOk()); | 1228 DCHECK(IsPipelineOk()); |
| 1212 | 1229 |
| 1213 scoped_refptr<DemuxerStream> stream; | 1230 scoped_refptr<DemuxerStream> stream; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1250 if (!audio_renderer_) { | 1267 if (!audio_renderer_) { |
| 1251 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 1268 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); |
| 1252 return false; | 1269 return false; |
| 1253 } | 1270 } |
| 1254 | 1271 |
| 1255 if (!PrepareFilter(audio_renderer_)) | 1272 if (!PrepareFilter(audio_renderer_)) |
| 1256 return false; | 1273 return false; |
| 1257 | 1274 |
| 1258 audio_renderer_->Initialize( | 1275 audio_renderer_->Initialize( |
| 1259 decoder, | 1276 decoder, |
| 1260 base::Bind(&PipelineImpl::OnFilterInitialize, this), | 1277 base::Bind(&PipelineImpl::OnFilterInitialize, this, PIPELINE_OK), |
| 1261 base::Bind(&PipelineImpl::OnAudioUnderflow, this)); | 1278 base::Bind(&PipelineImpl::OnAudioUnderflow, this)); |
| 1262 return true; | 1279 return true; |
| 1263 } | 1280 } |
| 1264 | 1281 |
| 1265 bool PipelineImpl::InitializeVideoRenderer( | 1282 bool PipelineImpl::InitializeVideoRenderer( |
| 1266 const scoped_refptr<VideoDecoder>& decoder) { | 1283 const scoped_refptr<VideoDecoder>& decoder) { |
| 1267 DCHECK_EQ(MessageLoop::current(), message_loop_); | 1284 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 1268 DCHECK(IsPipelineOk()); | 1285 DCHECK(IsPipelineOk()); |
| 1269 | 1286 |
| 1270 if (!decoder) | 1287 if (!decoder) |
| 1271 return false; | 1288 return false; |
| 1272 | 1289 |
| 1273 filter_collection_->SelectVideoRenderer(&video_renderer_); | 1290 filter_collection_->SelectVideoRenderer(&video_renderer_); |
| 1274 if (!video_renderer_) { | 1291 if (!video_renderer_) { |
| 1275 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 1292 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); |
| 1276 return false; | 1293 return false; |
| 1277 } | 1294 } |
| 1278 | 1295 |
| 1279 if (!PrepareFilter(video_renderer_)) | 1296 if (!PrepareFilter(video_renderer_)) |
| 1280 return false; | 1297 return false; |
| 1281 | 1298 |
| 1282 video_renderer_->Initialize( | 1299 video_renderer_->Initialize( |
| 1283 decoder, | 1300 decoder, |
| 1284 base::Bind(&PipelineImpl::OnFilterInitialize, this), | 1301 base::Bind(&PipelineImpl::OnFilterInitialize, this, PIPELINE_OK), |
| 1285 base::Bind(&PipelineImpl::OnUpdateStatistics, this)); | 1302 base::Bind(&PipelineImpl::OnUpdateStatistics, this)); |
| 1286 return true; | 1303 return true; |
| 1287 } | 1304 } |
| 1288 | 1305 |
| 1289 void PipelineImpl::TearDownPipeline() { | 1306 void PipelineImpl::TearDownPipeline() { |
| 1290 DCHECK_EQ(MessageLoop::current(), message_loop_); | 1307 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 1291 DCHECK_NE(kStopped, state_); | 1308 DCHECK_NE(kStopped, state_); |
| 1292 | 1309 |
| 1293 DCHECK(!tearing_down_ || // Teardown on Stop(). | 1310 DCHECK(!tearing_down_ || // Teardown on Stop(). |
| 1294 (tearing_down_ && error_caused_teardown_) || // Teardown on error. | 1311 (tearing_down_ && error_caused_teardown_) || // Teardown on error. |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1431 message_loop_->PostTask(FROM_HERE, | 1448 message_loop_->PostTask(FROM_HERE, |
| 1432 base::Bind(&PipelineImpl::NotifyCanPlayThrough, this)); | 1449 base::Bind(&PipelineImpl::NotifyCanPlayThrough, this)); |
| 1433 } | 1450 } |
| 1434 | 1451 |
| 1435 void PipelineImpl::NotifyCanPlayThrough() { | 1452 void PipelineImpl::NotifyCanPlayThrough() { |
| 1436 DCHECK_EQ(MessageLoop::current(), message_loop_); | 1453 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 1437 NotifyNetworkEventTask(CAN_PLAY_THROUGH); | 1454 NotifyNetworkEventTask(CAN_PLAY_THROUGH); |
| 1438 } | 1455 } |
| 1439 | 1456 |
| 1440 } // namespace media | 1457 } // namespace media |
| OLD | NEW |