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 "webkit/media/webmediaplayer_impl.h" | 5 #include "webkit/media/webmediaplayer_impl.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 pending_seek_seconds_(0.0f), | 146 pending_seek_seconds_(0.0f), |
147 client_(client), | 147 client_(client), |
148 delegate_(delegate), | 148 delegate_(delegate), |
149 media_log_(params.media_log()), | 149 media_log_(params.media_log()), |
150 accelerated_compositing_reported_(false), | 150 accelerated_compositing_reported_(false), |
151 incremented_externally_allocated_memory_(false), | 151 incremented_externally_allocated_memory_(false), |
152 gpu_factories_(params.gpu_factories()), | 152 gpu_factories_(params.gpu_factories()), |
153 is_local_source_(false), | 153 is_local_source_(false), |
154 supports_save_(true), | 154 supports_save_(true), |
155 starting_(false), | 155 starting_(false), |
| 156 chunk_demuxer_(NULL), |
156 pending_repaint_(false), | 157 pending_repaint_(false), |
157 video_frame_provider_client_(NULL) { | 158 video_frame_provider_client_(NULL) { |
158 media_log_->AddEvent( | 159 media_log_->AddEvent( |
159 media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_CREATED)); | 160 media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_CREATED)); |
160 | 161 |
161 CHECK(media_thread_.Start()); | 162 CHECK(media_thread_.Start()); |
162 pipeline_ = new media::Pipeline( | 163 pipeline_ = new media::Pipeline( |
163 media_thread_.message_loop_proxy(), media_log_); | 164 media_thread_.message_loop_proxy(), media_log_); |
164 | 165 |
165 // Let V8 know we started new thread if we did not do it yet. | 166 // Let V8 know we started new thread if we did not do it yet. |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 is_local_source_ = !gurl.SchemeIs("http") && !gurl.SchemeIs("https"); | 264 is_local_source_ = !gurl.SchemeIs("http") && !gurl.SchemeIs("https"); |
264 } | 265 } |
265 | 266 |
266 void WebMediaPlayerImpl::load(const WebKit::WebURL& url, | 267 void WebMediaPlayerImpl::load(const WebKit::WebURL& url, |
267 WebKit::WebMediaSource* media_source, | 268 WebKit::WebMediaSource* media_source, |
268 CORSMode cors_mode) { | 269 CORSMode cors_mode) { |
269 scoped_ptr<WebKit::WebMediaSource> ms(media_source); | 270 scoped_ptr<WebKit::WebMediaSource> ms(media_source); |
270 LoadSetup(url); | 271 LoadSetup(url); |
271 | 272 |
272 // Media source pipelines can start immediately. | 273 // Media source pipelines can start immediately. |
273 chunk_demuxer_ = new media::ChunkDemuxer( | |
274 BIND_TO_RENDER_LOOP_1(&WebMediaPlayerImpl::OnDemuxerOpened, | |
275 base::Passed(&ms)), | |
276 BIND_TO_RENDER_LOOP_2(&WebMediaPlayerImpl::OnNeedKey, "", ""), | |
277 base::Bind(&LogMediaSourceError, media_log_)); | |
278 | |
279 supports_save_ = false; | 274 supports_save_ = false; |
280 StartPipeline(); | 275 StartPipeline(media_source); |
281 } | 276 } |
282 | 277 |
283 void WebMediaPlayerImpl::LoadSetup(const WebKit::WebURL& url) { | 278 void WebMediaPlayerImpl::LoadSetup(const WebKit::WebURL& url) { |
284 GURL gurl(url); | 279 GURL gurl(url); |
285 UMA_HISTOGRAM_ENUMERATION("Media.URLScheme", URLScheme(gurl), kMaxURLScheme); | 280 UMA_HISTOGRAM_ENUMERATION("Media.URLScheme", URLScheme(gurl), kMaxURLScheme); |
286 | 281 |
287 // Set subresource URL for crash reporting. | 282 // Set subresource URL for crash reporting. |
288 base::debug::SetCrashKeyValue("subresource_url", gurl.spec()); | 283 base::debug::SetCrashKeyValue("subresource_url", gurl.spec()); |
289 | 284 |
290 // Handle any volume/preload changes that occurred before load(). | 285 // Handle any volume/preload changes that occurred before load(). |
(...skipping 814 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1105 | 1100 |
1106 void WebMediaPlayerImpl::DataSourceInitialized(const GURL& gurl, bool success) { | 1101 void WebMediaPlayerImpl::DataSourceInitialized(const GURL& gurl, bool success) { |
1107 DCHECK(main_loop_->BelongsToCurrentThread()); | 1102 DCHECK(main_loop_->BelongsToCurrentThread()); |
1108 | 1103 |
1109 if (!success) { | 1104 if (!success) { |
1110 SetNetworkState(WebMediaPlayer::NetworkStateFormatError); | 1105 SetNetworkState(WebMediaPlayer::NetworkStateFormatError); |
1111 Repaint(); | 1106 Repaint(); |
1112 return; | 1107 return; |
1113 } | 1108 } |
1114 | 1109 |
1115 StartPipeline(); | 1110 StartPipeline(NULL); |
1116 } | 1111 } |
1117 | 1112 |
1118 void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) { | 1113 void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) { |
1119 if (!is_downloading && network_state_ == WebMediaPlayer::NetworkStateLoading) | 1114 if (!is_downloading && network_state_ == WebMediaPlayer::NetworkStateLoading) |
1120 SetNetworkState(WebMediaPlayer::NetworkStateIdle); | 1115 SetNetworkState(WebMediaPlayer::NetworkStateIdle); |
1121 else if (is_downloading && network_state_ == WebMediaPlayer::NetworkStateIdle) | 1116 else if (is_downloading && network_state_ == WebMediaPlayer::NetworkStateIdle) |
1122 SetNetworkState(WebMediaPlayer::NetworkStateLoading); | 1117 SetNetworkState(WebMediaPlayer::NetworkStateLoading); |
1123 media_log_->AddEvent( | 1118 media_log_->AddEvent( |
1124 media_log_->CreateBooleanEvent( | 1119 media_log_->CreateBooleanEvent( |
1125 media::MediaLogEvent::NETWORK_ACTIVITY_SET, | 1120 media::MediaLogEvent::NETWORK_ACTIVITY_SET, |
1126 "is_downloading_data", is_downloading)); | 1121 "is_downloading_data", is_downloading)); |
1127 } | 1122 } |
1128 | 1123 |
1129 void WebMediaPlayerImpl::StartPipeline() { | 1124 void WebMediaPlayerImpl::StartPipeline(WebKit::WebMediaSource* media_source) { |
| 1125 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); |
| 1126 |
| 1127 scoped_ptr<media::FilterCollection> filter_collection( |
| 1128 new media::FilterCollection()); |
| 1129 |
| 1130 // Figure out which demuxer to use. |
| 1131 scoped_ptr<media::Demuxer> demuxer; |
| 1132 if (!media_source) { |
| 1133 DCHECK(!chunk_demuxer_); |
| 1134 DCHECK(data_source_); |
| 1135 |
| 1136 demuxer.reset(new media::FFmpegDemuxer( |
| 1137 media_thread_.message_loop_proxy(), data_source_, |
| 1138 BIND_TO_RENDER_LOOP_2(&WebMediaPlayerImpl::OnNeedKey, "", ""))); |
| 1139 } else { |
| 1140 DCHECK(!chunk_demuxer_); |
| 1141 DCHECK(!data_source_); |
| 1142 |
| 1143 scoped_ptr<WebKit::WebMediaSource> ms(media_source); |
| 1144 chunk_demuxer_ = new media::ChunkDemuxer( |
| 1145 BIND_TO_RENDER_LOOP_1(&WebMediaPlayerImpl::OnDemuxerOpened, |
| 1146 base::Passed(&ms)), |
| 1147 BIND_TO_RENDER_LOOP_2(&WebMediaPlayerImpl::OnNeedKey, "", ""), |
| 1148 base::Bind(&LogMediaSourceError, media_log_)); |
| 1149 demuxer.reset(chunk_demuxer_); |
| 1150 |
| 1151 // Disable GpuVideoDecoder creation until it supports codec config changes. |
| 1152 // TODO(acolwell): Remove this once http://crbug.com/151045 is fixed. |
| 1153 gpu_factories_ = NULL; |
| 1154 } |
| 1155 filter_collection->SetDemuxer(demuxer.Pass()); |
| 1156 |
| 1157 // Figure out if EME is enabled. |
| 1158 media::SetDecryptorReadyCB set_decryptor_ready_cb; |
| 1159 if (decryptor_) { |
| 1160 set_decryptor_ready_cb = base::Bind(&ProxyDecryptor::SetDecryptorReadyCB, |
| 1161 base::Unretained(decryptor_.get())); |
| 1162 } |
| 1163 |
| 1164 // Create our audio decoders and renderer. |
| 1165 ScopedVector<media::AudioDecoder> audio_decoders; |
| 1166 audio_decoders.push_back(new media::FFmpegAudioDecoder( |
| 1167 media_thread_.message_loop_proxy())); |
| 1168 if (cmd_line->HasSwitch(switches::kEnableOpusPlayback)) { |
| 1169 audio_decoders.push_back(new media::OpusAudioDecoder( |
| 1170 media_thread_.message_loop_proxy())); |
| 1171 } |
| 1172 |
| 1173 scoped_ptr<media::AudioRenderer> audio_renderer( |
| 1174 new media::AudioRendererImpl(media_thread_.message_loop_proxy(), |
| 1175 audio_source_provider_, |
| 1176 audio_decoders.Pass(), |
| 1177 set_decryptor_ready_cb)); |
| 1178 filter_collection->SetAudioRenderer(audio_renderer.Pass()); |
| 1179 |
| 1180 // Create our video decoders and renderer. |
| 1181 ScopedVector<media::VideoDecoder> video_decoders; |
| 1182 |
| 1183 if (gpu_factories_) { |
| 1184 video_decoders.push_back(new media::GpuVideoDecoder( |
| 1185 media_thread_.message_loop_proxy(), gpu_factories_)); |
| 1186 } |
| 1187 |
| 1188 video_decoders.push_back(new media::FFmpegVideoDecoder( |
| 1189 media_thread_.message_loop_proxy())); |
| 1190 |
| 1191 // TODO(phajdan.jr): Remove ifdefs when libvpx with vp9 support is released |
| 1192 // (http://crbug.com/174287) . |
| 1193 #if !defined(MEDIA_DISABLE_LIBVPX) |
| 1194 if (cmd_line->HasSwitch(switches::kEnableVp9Playback)) { |
| 1195 video_decoders.push_back(new media::VpxVideoDecoder( |
| 1196 media_thread_.message_loop_proxy())); |
| 1197 } |
| 1198 #endif // !defined(MEDIA_DISABLE_LIBVPX) |
| 1199 |
| 1200 scoped_ptr<media::VideoRenderer> video_renderer( |
| 1201 new media::VideoRendererBase( |
| 1202 media_thread_.message_loop_proxy(), |
| 1203 video_decoders.Pass(), |
| 1204 set_decryptor_ready_cb, |
| 1205 base::Bind(&WebMediaPlayerImpl::FrameReady, base::Unretained(this)), |
| 1206 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::SetOpaque), |
| 1207 true)); |
| 1208 filter_collection->SetVideoRenderer(video_renderer.Pass()); |
| 1209 |
| 1210 // ... and we're ready to go! |
1130 starting_ = true; | 1211 starting_ = true; |
1131 pipeline_->Start( | 1212 pipeline_->Start( |
1132 BuildFilterCollection(), | 1213 filter_collection.Pass(), |
1133 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded), | 1214 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded), |
1134 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineError), | 1215 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineError), |
1135 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineSeek), | 1216 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineSeek), |
1136 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingState), | 1217 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingState), |
1137 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChange)); | 1218 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChange)); |
1138 } | 1219 } |
1139 | 1220 |
1140 void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) { | 1221 void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) { |
1141 DCHECK(main_loop_->BelongsToCurrentThread()); | 1222 DCHECK(main_loop_->BelongsToCurrentThread()); |
1142 DVLOG(1) << "SetNetworkState: " << state; | 1223 DVLOG(1) << "SetNetworkState: " << state; |
(...skipping 15 matching lines...) Expand all Loading... |
1158 // Always notify to ensure client has the latest value. | 1239 // Always notify to ensure client has the latest value. |
1159 GetClient()->readyStateChanged(); | 1240 GetClient()->readyStateChanged(); |
1160 } | 1241 } |
1161 | 1242 |
1162 void WebMediaPlayerImpl::Destroy() { | 1243 void WebMediaPlayerImpl::Destroy() { |
1163 DCHECK(main_loop_->BelongsToCurrentThread()); | 1244 DCHECK(main_loop_->BelongsToCurrentThread()); |
1164 | 1245 |
1165 // Abort any pending IO so stopping the pipeline doesn't get blocked. | 1246 // Abort any pending IO so stopping the pipeline doesn't get blocked. |
1166 if (data_source_) | 1247 if (data_source_) |
1167 data_source_->Abort(); | 1248 data_source_->Abort(); |
1168 if (chunk_demuxer_) | 1249 if (chunk_demuxer_) { |
1169 chunk_demuxer_->Shutdown(); | 1250 chunk_demuxer_->Shutdown(); |
| 1251 chunk_demuxer_ = NULL; |
| 1252 } |
1170 | 1253 |
1171 if (gpu_factories_) { | 1254 if (gpu_factories_) { |
1172 gpu_factories_->Abort(); | 1255 gpu_factories_->Abort(); |
1173 gpu_factories_ = NULL; | 1256 gpu_factories_ = NULL; |
1174 } | 1257 } |
1175 | 1258 |
1176 // Make sure to kill the pipeline so there's no more media threads running. | 1259 // Make sure to kill the pipeline so there's no more media threads running. |
1177 // Note: stopping the pipeline might block for a long time. | 1260 // Note: stopping the pipeline might block for a long time. |
1178 base::WaitableEvent waiter(false, false); | 1261 base::WaitableEvent waiter(false, false); |
1179 pipeline_->Stop(base::Bind( | 1262 pipeline_->Stop(base::Bind( |
1180 &base::WaitableEvent::Signal, base::Unretained(&waiter))); | 1263 &base::WaitableEvent::Signal, base::Unretained(&waiter))); |
1181 waiter.Wait(); | 1264 waiter.Wait(); |
1182 | 1265 |
1183 // Let V8 know we are not using extra resources anymore. | 1266 // Let V8 know we are not using extra resources anymore. |
1184 if (incremented_externally_allocated_memory_) { | 1267 if (incremented_externally_allocated_memory_) { |
1185 v8::V8::AdjustAmountOfExternalAllocatedMemory(-kPlayerExtraMemory); | 1268 v8::V8::AdjustAmountOfExternalAllocatedMemory(-kPlayerExtraMemory); |
1186 incremented_externally_allocated_memory_ = false; | 1269 incremented_externally_allocated_memory_ = false; |
1187 } | 1270 } |
1188 | 1271 |
1189 media_thread_.Stop(); | 1272 media_thread_.Stop(); |
1190 | 1273 |
1191 // Release any final references now that everything has stopped. | 1274 // Release any final references now that everything has stopped. |
1192 data_source_ = NULL; | 1275 data_source_ = NULL; |
1193 chunk_demuxer_ = NULL; | |
1194 } | 1276 } |
1195 | 1277 |
1196 WebKit::WebMediaPlayerClient* WebMediaPlayerImpl::GetClient() { | 1278 WebKit::WebMediaPlayerClient* WebMediaPlayerImpl::GetClient() { |
1197 DCHECK(main_loop_->BelongsToCurrentThread()); | 1279 DCHECK(main_loop_->BelongsToCurrentThread()); |
1198 DCHECK(client_); | 1280 DCHECK(client_); |
1199 return client_; | 1281 return client_; |
1200 } | 1282 } |
1201 | 1283 |
1202 WebKit::WebAudioSourceProvider* WebMediaPlayerImpl::audioSourceProvider() { | 1284 WebKit::WebAudioSourceProvider* WebMediaPlayerImpl::audioSourceProvider() { |
1203 return audio_source_provider_; | 1285 return audio_source_provider_; |
(...skipping 29 matching lines...) Expand all Loading... |
1233 current_frame_ = frame; | 1315 current_frame_ = frame; |
1234 | 1316 |
1235 if (pending_repaint_) | 1317 if (pending_repaint_) |
1236 return; | 1318 return; |
1237 | 1319 |
1238 pending_repaint_ = true; | 1320 pending_repaint_ = true; |
1239 main_loop_->PostTask(FROM_HERE, base::Bind( | 1321 main_loop_->PostTask(FROM_HERE, base::Bind( |
1240 &WebMediaPlayerImpl::Repaint, AsWeakPtr())); | 1322 &WebMediaPlayerImpl::Repaint, AsWeakPtr())); |
1241 } | 1323 } |
1242 | 1324 |
1243 scoped_ptr<media::FilterCollection> | |
1244 WebMediaPlayerImpl::BuildFilterCollection() { | |
1245 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); | |
1246 | |
1247 scoped_ptr<media::FilterCollection> filter_collection( | |
1248 new media::FilterCollection()); | |
1249 | |
1250 // Figure out which demuxer to use. | |
1251 if (data_source_) { | |
1252 DCHECK(!chunk_demuxer_); | |
1253 filter_collection->SetDemuxer(new media::FFmpegDemuxer( | |
1254 media_thread_.message_loop_proxy(), data_source_, | |
1255 BIND_TO_RENDER_LOOP_2(&WebMediaPlayerImpl::OnNeedKey, "", ""))); | |
1256 } else { | |
1257 DCHECK(chunk_demuxer_); | |
1258 filter_collection->SetDemuxer(chunk_demuxer_); | |
1259 | |
1260 // Disable GpuVideoDecoder creation until it supports codec config changes. | |
1261 // TODO(acolwell): Remove this once http://crbug.com/151045 is fixed. | |
1262 gpu_factories_ = NULL; | |
1263 } | |
1264 | |
1265 // Figure out if EME is enabled. | |
1266 media::SetDecryptorReadyCB set_decryptor_ready_cb; | |
1267 if (decryptor_) { | |
1268 set_decryptor_ready_cb = base::Bind(&ProxyDecryptor::SetDecryptorReadyCB, | |
1269 base::Unretained(decryptor_.get())); | |
1270 } | |
1271 | |
1272 // Create our audio decoders and renderer. | |
1273 ScopedVector<media::AudioDecoder> audio_decoders; | |
1274 audio_decoders.push_back(new media::FFmpegAudioDecoder( | |
1275 media_thread_.message_loop_proxy())); | |
1276 if (cmd_line->HasSwitch(switches::kEnableOpusPlayback)) { | |
1277 audio_decoders.push_back(new media::OpusAudioDecoder( | |
1278 media_thread_.message_loop_proxy())); | |
1279 } | |
1280 | |
1281 scoped_ptr<media::AudioRenderer> audio_renderer( | |
1282 new media::AudioRendererImpl(media_thread_.message_loop_proxy(), | |
1283 audio_source_provider_, | |
1284 audio_decoders.Pass(), | |
1285 set_decryptor_ready_cb)); | |
1286 filter_collection->SetAudioRenderer(audio_renderer.Pass()); | |
1287 | |
1288 // Create our video decoders and renderer. | |
1289 ScopedVector<media::VideoDecoder> video_decoders; | |
1290 | |
1291 if (gpu_factories_) { | |
1292 video_decoders.push_back(new media::GpuVideoDecoder( | |
1293 media_thread_.message_loop_proxy(), gpu_factories_)); | |
1294 } | |
1295 | |
1296 video_decoders.push_back(new media::FFmpegVideoDecoder( | |
1297 media_thread_.message_loop_proxy())); | |
1298 | |
1299 // TODO(phajdan.jr): Remove ifdefs when libvpx with vp9 support is released | |
1300 // (http://crbug.com/174287) . | |
1301 #if !defined(MEDIA_DISABLE_LIBVPX) | |
1302 if (cmd_line->HasSwitch(switches::kEnableVp9Playback)) { | |
1303 video_decoders.push_back(new media::VpxVideoDecoder( | |
1304 media_thread_.message_loop_proxy())); | |
1305 } | |
1306 #endif // !defined(MEDIA_DISABLE_LIBVPX) | |
1307 | |
1308 scoped_ptr<media::VideoRenderer> video_renderer( | |
1309 new media::VideoRendererBase( | |
1310 media_thread_.message_loop_proxy(), | |
1311 video_decoders.Pass(), | |
1312 set_decryptor_ready_cb, | |
1313 base::Bind(&WebMediaPlayerImpl::FrameReady, base::Unretained(this)), | |
1314 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::SetOpaque), | |
1315 true)); | |
1316 filter_collection->SetVideoRenderer(video_renderer.Pass()); | |
1317 | |
1318 return filter_collection.Pass(); | |
1319 } | |
1320 | |
1321 } // namespace webkit_media | 1325 } // namespace webkit_media |
OLD | NEW |