 Chromium Code Reviews
 Chromium Code Reviews Issue 8686010:
  <video> decode in hardware!  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src
    
  
    Issue 8686010:
  <video> decode in hardware!  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src| 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 568 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 579 DCHECK(IsRunning()); | 579 DCHECK(IsRunning()); | 
| 580 | 580 | 
| 581 // Disable renderer on the message loop. | 581 // Disable renderer on the message loop. | 
| 582 message_loop_->PostTask(FROM_HERE, | 582 message_loop_->PostTask(FROM_HERE, | 
| 583 base::Bind(&PipelineImpl::DisableAudioRendererTask, this)); | 583 base::Bind(&PipelineImpl::DisableAudioRendererTask, this)); | 
| 584 media_log_->AddEvent( | 584 media_log_->AddEvent( | 
| 585 media_log_->CreateEvent(MediaLogEvent::AUDIO_RENDERER_DISABLED)); | 585 media_log_->CreateEvent(MediaLogEvent::AUDIO_RENDERER_DISABLED)); | 
| 586 } | 586 } | 
| 587 | 587 | 
| 588 // Called from any thread. | 588 // Called from any thread. | 
| 589 void PipelineImpl::OnFilterInitialize() { | 589 void PipelineImpl::OnFilterInitialize(PipelineStatus status) { | 
| 590 // Continue the initialize task by proceeding to the next stage. | 590 // Continue the initialize task by proceeding to the next stage. | 
| 591 message_loop_->PostTask(FROM_HERE, | 591 message_loop_->PostTask( | 
| 592 base::Bind(&PipelineImpl::InitializeTask, this)); | 592 FROM_HERE, base::Bind(&PipelineImpl::InitializeTask, this, status)); | 
| 593 } | 593 } | 
| 594 | 594 | 
| 595 // Called from any thread. | 595 // Called from any thread. | 
| 596 void PipelineImpl::OnFilterStateTransition() { | 596 void PipelineImpl::OnFilterStateTransition() { | 
| 597 message_loop_->PostTask(FROM_HERE, | 597 message_loop_->PostTask(FROM_HERE, | 
| 598 base::Bind(&PipelineImpl::FilterStateTransitionTask, this)); | 598 base::Bind(&PipelineImpl::FilterStateTransitionTask, this)); | 
| 599 } | 599 } | 
| 600 | 600 | 
| 601 // Called from any thread. | 601 // Called from any thread. | 
| 602 // This method makes the FilterStatusCB behave like a Closure. It | 602 // This method makes the FilterStatusCB behave like a Closure. It | 
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 654 // VideoDecoder to the Demuxer's video stream, and then connects the | 654 // VideoDecoder to the Demuxer's video stream, and then connects the | 
| 655 // VideoDecoder to a VideoRenderer. | 655 // VideoDecoder to a VideoRenderer. | 
| 656 // | 656 // | 
| 657 // When all required filters have been created and have called their | 657 // When all required filters have been created and have called their | 
| 658 // FilterHost's InitializationComplete() method, the pipeline will update its | 658 // FilterHost's InitializationComplete() method, the pipeline will update its | 
| 659 // state to kStarted and |init_callback_|, will be executed. | 659 // state to kStarted and |init_callback_|, will be executed. | 
| 660 // | 660 // | 
| 661 // TODO(hclam): InitializeTask() is now starting the pipeline asynchronously. It | 661 // TODO(hclam): InitializeTask() is now starting the pipeline asynchronously. It | 
| 662 // works like a big state change table. If we no longer need to start filters | 662 // works like a big state change table. If we no longer need to start filters | 
| 663 // in order, we need to get rid of all the state change. | 663 // in order, we need to get rid of all the state change. | 
| 664 void PipelineImpl::InitializeTask() { | 664 void PipelineImpl::InitializeTask(PipelineStatus last_stage_status) { | 
| 665 DCHECK_EQ(MessageLoop::current(), message_loop_); | 665 DCHECK_EQ(MessageLoop::current(), message_loop_); | 
| 666 | 666 | 
| 667 if (last_stage_status != PIPELINE_OK) { | |
| 668 // Currently only VideoDecoders have a recoverable error code. | |
| 669 if (state_ == kInitVideoDecoder && | |
| 670 last_stage_status == DECODER_ERROR_NOT_SUPPORTED) { | |
| 671 DiscardFilter(pipeline_init_state_->video_decoder_); | |
| 672 state_ = kInitAudioRenderer; | |
| 673 } else { | |
| 674 SetError(last_stage_status); | |
| 675 } | |
| 676 } | |
| 677 | |
| 667 // If we have received the stop or error signal, return immediately. | 678 // If we have received the stop or error signal, return immediately. | 
| 668 if (IsPipelineStopPending() || IsPipelineStopped() || !IsPipelineOk()) | 679 if (IsPipelineStopPending() || IsPipelineStopped() || !IsPipelineOk()) | 
| 669 return; | 680 return; | 
| 670 | 681 | 
| 671 DCHECK(state_ == kInitDemuxer || | 682 DCHECK(state_ == kInitDemuxer || | 
| 672 state_ == kInitAudioDecoder || | 683 state_ == kInitAudioDecoder || | 
| 673 state_ == kInitAudioRenderer || | 684 state_ == kInitAudioRenderer || | 
| 674 state_ == kInitVideoDecoder || | 685 state_ == kInitVideoDecoder || | 
| 675 state_ == kInitVideoRenderer); | 686 state_ == kInitVideoRenderer); | 
| 676 | 687 | 
| (...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1104 stop_cb.Run(status_); | 1115 stop_cb.Run(status_); | 
| 1105 } | 1116 } | 
| 1106 } | 1117 } | 
| 1107 | 1118 | 
| 1108 tearing_down_ = false; | 1119 tearing_down_ = false; | 
| 1109 error_caused_teardown_ = false; | 1120 error_caused_teardown_ = false; | 
| 1110 } | 1121 } | 
| 1111 | 1122 | 
| 1112 bool PipelineImpl::PrepareFilter(scoped_refptr<Filter> filter) { | 1123 bool PipelineImpl::PrepareFilter(scoped_refptr<Filter> filter) { | 
| 1113 bool ret = pipeline_init_state_->composite_->AddFilter(filter.get()); | 1124 bool ret = pipeline_init_state_->composite_->AddFilter(filter.get()); | 
| 1125 if (!ret) | |
| 1126 SetError(PIPELINE_ERROR_INITIALIZATION_FAILED); | |
| 1127 return ret; | |
| 1128 } | |
| 1114 | 1129 | 
| 1115 if (!ret) { | 1130 void PipelineImpl::DiscardFilter(scoped_refptr<Filter> filter) { | 
| 
scherkus (not reviewing)
2011/12/09 00:26:20
nit: maybe RemoveFilter() or even inline the code?
 
Ami GONE FROM CHROMIUM
2011/12/09 22:55:50
Done.
 | |
| 1116 SetError(PIPELINE_ERROR_INITIALIZATION_FAILED); | 1131 pipeline_init_state_->composite_->RemoveFilter(filter.get()); | 
| 1117 } | |
| 1118 return ret; | |
| 1119 } | 1132 } | 
| 1120 | 1133 | 
| 1121 void PipelineImpl::InitializeDemuxer() { | 1134 void PipelineImpl::InitializeDemuxer() { | 
| 1122 DCHECK_EQ(MessageLoop::current(), message_loop_); | 1135 DCHECK_EQ(MessageLoop::current(), message_loop_); | 
| 1123 DCHECK(IsPipelineOk()); | 1136 DCHECK(IsPipelineOk()); | 
| 1124 | 1137 | 
| 1125 filter_collection_->GetDemuxerFactory()->Build( | 1138 filter_collection_->GetDemuxerFactory()->Build( | 
| 1126 url_, base::Bind(&PipelineImpl::OnDemuxerBuilt, this)); | 1139 url_, base::Bind(&PipelineImpl::OnDemuxerBuilt, this)); | 
| 1127 } | 1140 } | 
| 1128 | 1141 | 
| (...skipping 19 matching lines...) Expand all Loading... | |
| 1148 demuxer_ = demuxer; | 1161 demuxer_ = demuxer; | 
| 1149 demuxer_->set_host(this); | 1162 demuxer_->set_host(this); | 
| 1150 | 1163 | 
| 1151 { | 1164 { | 
| 1152 base::AutoLock auto_lock(lock_); | 1165 base::AutoLock auto_lock(lock_); | 
| 1153 // We do not want to start the clock running. We only want to set the base | 1166 // We do not want to start the clock running. We only want to set the base | 
| 1154 // media time so our timestamp calculations will be correct. | 1167 // media time so our timestamp calculations will be correct. | 
| 1155 clock_->SetTime(demuxer_->GetStartTime()); | 1168 clock_->SetTime(demuxer_->GetStartTime()); | 
| 1156 } | 1169 } | 
| 1157 | 1170 | 
| 1158 OnFilterInitialize(); | 1171 OnFilterInitialize(PIPELINE_OK); | 
| 1159 } | 1172 } | 
| 1160 | 1173 | 
| 1161 bool PipelineImpl::InitializeAudioDecoder( | 1174 bool PipelineImpl::InitializeAudioDecoder( | 
| 1162 const scoped_refptr<Demuxer>& demuxer) { | 1175 const scoped_refptr<Demuxer>& demuxer) { | 
| 1163 DCHECK_EQ(MessageLoop::current(), message_loop_); | 1176 DCHECK_EQ(MessageLoop::current(), message_loop_); | 
| 1164 DCHECK(IsPipelineOk()); | 1177 DCHECK(IsPipelineOk()); | 
| 1165 | 1178 | 
| 1166 scoped_refptr<DemuxerStream> stream = | 1179 scoped_refptr<DemuxerStream> stream = | 
| 1167 demuxer->GetStream(DemuxerStream::AUDIO); | 1180 demuxer->GetStream(DemuxerStream::AUDIO); | 
| 1168 | 1181 | 
| 1169 if (!stream) | 1182 if (!stream) | 
| 1170 return false; | 1183 return false; | 
| 1171 | 1184 | 
| 1172 scoped_refptr<AudioDecoder> audio_decoder; | 1185 scoped_refptr<AudioDecoder> audio_decoder; | 
| 1173 filter_collection_->SelectAudioDecoder(&audio_decoder); | 1186 filter_collection_->SelectAudioDecoder(&audio_decoder); | 
| 1174 | 1187 | 
| 1175 if (!audio_decoder) { | 1188 if (!audio_decoder) { | 
| 1176 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 1189 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 
| 1177 return false; | 1190 return false; | 
| 1178 } | 1191 } | 
| 1179 | 1192 | 
| 1180 if (!PrepareFilter(audio_decoder)) | 1193 if (!PrepareFilter(audio_decoder)) | 
| 1181 return false; | 1194 return false; | 
| 1182 | 1195 | 
| 1183 pipeline_init_state_->audio_decoder_ = audio_decoder; | 1196 pipeline_init_state_->audio_decoder_ = audio_decoder; | 
| 1184 audio_decoder->Initialize( | 1197 audio_decoder->Initialize( | 
| 1185 stream, | 1198 stream, | 
| 1186 base::Bind(&PipelineImpl::OnFilterInitialize, this), | 1199 base::Bind(&PipelineImpl::OnFilterInitialize, this, PIPELINE_OK), | 
| 1187 base::Bind(&PipelineImpl::OnUpdateStatistics, this)); | 1200 base::Bind(&PipelineImpl::OnUpdateStatistics, this)); | 
| 1188 return true; | 1201 return true; | 
| 1189 } | 1202 } | 
| 1190 | 1203 | 
| 1191 bool PipelineImpl::InitializeVideoDecoder( | 1204 bool PipelineImpl::InitializeVideoDecoder( | 
| 1192 const scoped_refptr<Demuxer>& demuxer) { | 1205 const scoped_refptr<Demuxer>& demuxer) { | 
| 1193 DCHECK_EQ(MessageLoop::current(), message_loop_); | 1206 DCHECK_EQ(MessageLoop::current(), message_loop_); | 
| 1194 DCHECK(IsPipelineOk()); | 1207 DCHECK(IsPipelineOk()); | 
| 1195 | 1208 | 
| 1196 scoped_refptr<DemuxerStream> stream; | 1209 scoped_refptr<DemuxerStream> stream; | 
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1233 if (!audio_renderer_) { | 1246 if (!audio_renderer_) { | 
| 1234 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 1247 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 
| 1235 return false; | 1248 return false; | 
| 1236 } | 1249 } | 
| 1237 | 1250 | 
| 1238 if (!PrepareFilter(audio_renderer_)) | 1251 if (!PrepareFilter(audio_renderer_)) | 
| 1239 return false; | 1252 return false; | 
| 1240 | 1253 | 
| 1241 audio_renderer_->Initialize( | 1254 audio_renderer_->Initialize( | 
| 1242 decoder, | 1255 decoder, | 
| 1243 base::Bind(&PipelineImpl::OnFilterInitialize, this), | 1256 base::Bind(&PipelineImpl::OnFilterInitialize, this, PIPELINE_OK), | 
| 1244 base::Bind(&PipelineImpl::OnAudioUnderflow, this)); | 1257 base::Bind(&PipelineImpl::OnAudioUnderflow, this)); | 
| 1245 return true; | 1258 return true; | 
| 1246 } | 1259 } | 
| 1247 | 1260 | 
| 1248 bool PipelineImpl::InitializeVideoRenderer( | 1261 bool PipelineImpl::InitializeVideoRenderer( | 
| 1249 const scoped_refptr<VideoDecoder>& decoder) { | 1262 const scoped_refptr<VideoDecoder>& decoder) { | 
| 1250 DCHECK_EQ(MessageLoop::current(), message_loop_); | 1263 DCHECK_EQ(MessageLoop::current(), message_loop_); | 
| 1251 DCHECK(IsPipelineOk()); | 1264 DCHECK(IsPipelineOk()); | 
| 1252 | 1265 | 
| 1253 if (!decoder) | 1266 if (!decoder) | 
| 1254 return false; | 1267 return false; | 
| 1255 | 1268 | 
| 1256 filter_collection_->SelectVideoRenderer(&video_renderer_); | 1269 filter_collection_->SelectVideoRenderer(&video_renderer_); | 
| 1257 if (!video_renderer_) { | 1270 if (!video_renderer_) { | 
| 1258 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 1271 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 
| 1259 return false; | 1272 return false; | 
| 1260 } | 1273 } | 
| 1261 | 1274 | 
| 1262 if (!PrepareFilter(video_renderer_)) | 1275 if (!PrepareFilter(video_renderer_)) | 
| 1263 return false; | 1276 return false; | 
| 1264 | 1277 | 
| 1265 video_renderer_->Initialize( | 1278 video_renderer_->Initialize( | 
| 1266 decoder, | 1279 decoder, | 
| 1267 base::Bind(&PipelineImpl::OnFilterInitialize, this), | 1280 base::Bind(&PipelineImpl::OnFilterInitialize, this, PIPELINE_OK), | 
| 1268 base::Bind(&PipelineImpl::OnUpdateStatistics, this)); | 1281 base::Bind(&PipelineImpl::OnUpdateStatistics, this)); | 
| 1269 return true; | 1282 return true; | 
| 1270 } | 1283 } | 
| 1271 | 1284 | 
| 1272 void PipelineImpl::TearDownPipeline() { | 1285 void PipelineImpl::TearDownPipeline() { | 
| 1273 DCHECK_EQ(MessageLoop::current(), message_loop_); | 1286 DCHECK_EQ(MessageLoop::current(), message_loop_); | 
| 1274 DCHECK_NE(kStopped, state_); | 1287 DCHECK_NE(kStopped, state_); | 
| 1275 | 1288 | 
| 1276 DCHECK(!tearing_down_ || // Teardown on Stop(). | 1289 DCHECK(!tearing_down_ || // Teardown on Stop(). | 
| 1277 (tearing_down_ && error_caused_teardown_) || // Teardown on error. | 1290 (tearing_down_ && error_caused_teardown_) || // Teardown on error. | 
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1414 message_loop_->PostTask(FROM_HERE, | 1427 message_loop_->PostTask(FROM_HERE, | 
| 1415 base::Bind(&PipelineImpl::NotifyCanPlayThrough, this)); | 1428 base::Bind(&PipelineImpl::NotifyCanPlayThrough, this)); | 
| 1416 } | 1429 } | 
| 1417 | 1430 | 
| 1418 void PipelineImpl::NotifyCanPlayThrough() { | 1431 void PipelineImpl::NotifyCanPlayThrough() { | 
| 1419 DCHECK_EQ(MessageLoop::current(), message_loop_); | 1432 DCHECK_EQ(MessageLoop::current(), message_loop_); | 
| 1420 NotifyNetworkEventTask(CAN_PLAY_THROUGH); | 1433 NotifyNetworkEventTask(CAN_PLAY_THROUGH); | 
| 1421 } | 1434 } | 
| 1422 | 1435 | 
| 1423 } // namespace media | 1436 } // namespace media | 
| OLD | NEW |