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 #include "webkit/glue/webmediaplayer_impl.h" | 5 #include "webkit/glue/webmediaplayer_impl.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/callback.h" | 10 #include "base/callback.h" |
(...skipping 12 matching lines...) Expand all Loading... |
23 #include "media/filters/null_audio_renderer.h" | 23 #include "media/filters/null_audio_renderer.h" |
24 #include "third_party/WebKit/Source/WebKit/chromium/public/WebRect.h" | 24 #include "third_party/WebKit/Source/WebKit/chromium/public/WebRect.h" |
25 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h" | 25 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h" |
26 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h" | 26 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h" |
27 #include "third_party/WebKit/Source/WebKit/chromium/public/WebVideoFrame.h" | 27 #include "third_party/WebKit/Source/WebKit/chromium/public/WebVideoFrame.h" |
28 #include "webkit/glue/media/buffered_data_source.h" | 28 #include "webkit/glue/media/buffered_data_source.h" |
29 #include "webkit/glue/media/simple_data_source.h" | 29 #include "webkit/glue/media/simple_data_source.h" |
30 #include "webkit/glue/media/media_stream_client.h" | 30 #include "webkit/glue/media/media_stream_client.h" |
31 #include "webkit/glue/media/video_renderer_impl.h" | 31 #include "webkit/glue/media/video_renderer_impl.h" |
32 #include "webkit/glue/media/web_video_renderer.h" | 32 #include "webkit/glue/media/web_video_renderer.h" |
| 33 #include "webkit/glue/webmediaplayer_proxy.h" |
33 #include "webkit/glue/webvideoframe_impl.h" | 34 #include "webkit/glue/webvideoframe_impl.h" |
34 | 35 |
35 using WebKit::WebCanvas; | 36 using WebKit::WebCanvas; |
36 using WebKit::WebRect; | 37 using WebKit::WebRect; |
37 using WebKit::WebSize; | 38 using WebKit::WebSize; |
38 using media::PipelineStatus; | 39 using media::PipelineStatus; |
39 | 40 |
40 namespace { | 41 namespace { |
41 | 42 |
42 // Limits the maximum outstanding repaints posted on render thread. | |
43 // This number of 50 is a guess, it does not take too much memory on the task | |
44 // queue but gives up a pretty good latency on repaint. | |
45 const int kMaxOutstandingRepaints = 50; | |
46 | |
47 // Limits the range of playback rate. | 43 // Limits the range of playback rate. |
48 // | 44 // |
49 // TODO(kylep): Revisit these. | 45 // TODO(kylep): Revisit these. |
50 // | 46 // |
51 // Vista has substantially lower performance than XP or Windows7. If you speed | 47 // Vista has substantially lower performance than XP or Windows7. If you speed |
52 // up a video too much, it can't keep up, and rendering stops updating except on | 48 // up a video too much, it can't keep up, and rendering stops updating except on |
53 // the time bar. For really high speeds, audio becomes a bottleneck and we just | 49 // the time bar. For really high speeds, audio becomes a bottleneck and we just |
54 // use up the data we have, which may not achieve the speed requested, but will | 50 // use up the data we have, which may not achieve the speed requested, but will |
55 // not crash the tab. | 51 // not crash the tab. |
56 // | 52 // |
(...skipping 22 matching lines...) Expand all Loading... |
79 } | 75 } |
80 | 76 |
81 // Now we can safely cast to int64 microseconds. | 77 // Now we can safely cast to int64 microseconds. |
82 return base::TimeDelta::FromMicroseconds(static_cast<int64>(integer)); | 78 return base::TimeDelta::FromMicroseconds(static_cast<int64>(integer)); |
83 } | 79 } |
84 | 80 |
85 } // namespace | 81 } // namespace |
86 | 82 |
87 namespace webkit_glue { | 83 namespace webkit_glue { |
88 | 84 |
89 ///////////////////////////////////////////////////////////////////////////// | |
90 // WebMediaPlayerImpl::Proxy implementation | |
91 | |
92 WebMediaPlayerImpl::Proxy::Proxy(MessageLoop* render_loop, | |
93 WebMediaPlayerImpl* webmediaplayer) | |
94 : render_loop_(render_loop), | |
95 webmediaplayer_(webmediaplayer), | |
96 outstanding_repaints_(0) { | |
97 DCHECK(render_loop_); | |
98 DCHECK(webmediaplayer_); | |
99 } | |
100 | |
101 WebMediaPlayerImpl::Proxy::~Proxy() { | |
102 Detach(); | |
103 } | |
104 | |
105 void WebMediaPlayerImpl::Proxy::Repaint() { | |
106 base::AutoLock auto_lock(lock_); | |
107 if (outstanding_repaints_ < kMaxOutstandingRepaints) { | |
108 ++outstanding_repaints_; | |
109 | |
110 render_loop_->PostTask(FROM_HERE, | |
111 NewRunnableMethod(this, &WebMediaPlayerImpl::Proxy::RepaintTask)); | |
112 } | |
113 } | |
114 | |
115 void WebMediaPlayerImpl::Proxy::SetVideoRenderer( | |
116 scoped_refptr<WebVideoRenderer> video_renderer) { | |
117 video_renderer_ = video_renderer; | |
118 } | |
119 | |
120 WebDataSourceBuildObserverHack* WebMediaPlayerImpl::Proxy::GetBuildObserver() { | |
121 if (!build_observer_.get()) | |
122 build_observer_.reset(NewCallback(this, &Proxy::AddDataSource)); | |
123 return build_observer_.get(); | |
124 } | |
125 | |
126 void WebMediaPlayerImpl::Proxy::Paint(SkCanvas* canvas, | |
127 const gfx::Rect& dest_rect) { | |
128 DCHECK(MessageLoop::current() == render_loop_); | |
129 if (video_renderer_) { | |
130 video_renderer_->Paint(canvas, dest_rect); | |
131 } | |
132 } | |
133 | |
134 void WebMediaPlayerImpl::Proxy::SetSize(const gfx::Rect& rect) { | |
135 DCHECK(MessageLoop::current() == render_loop_); | |
136 if (video_renderer_) { | |
137 video_renderer_->SetRect(rect); | |
138 } | |
139 } | |
140 | |
141 bool WebMediaPlayerImpl::Proxy::HasSingleOrigin() { | |
142 DCHECK(MessageLoop::current() == render_loop_); | |
143 | |
144 base::AutoLock auto_lock(data_sources_lock_); | |
145 | |
146 for (DataSourceList::iterator itr = data_sources_.begin(); | |
147 itr != data_sources_.end(); | |
148 itr++) { | |
149 if (!(*itr)->HasSingleOrigin()) | |
150 return false; | |
151 } | |
152 return true; | |
153 } | |
154 | |
155 void WebMediaPlayerImpl::Proxy::AbortDataSources() { | |
156 DCHECK(MessageLoop::current() == render_loop_); | |
157 base::AutoLock auto_lock(data_sources_lock_); | |
158 | |
159 for (DataSourceList::iterator itr = data_sources_.begin(); | |
160 itr != data_sources_.end(); | |
161 itr++) { | |
162 (*itr)->Abort(); | |
163 } | |
164 } | |
165 | |
166 void WebMediaPlayerImpl::Proxy::Detach() { | |
167 DCHECK(MessageLoop::current() == render_loop_); | |
168 webmediaplayer_ = NULL; | |
169 video_renderer_ = NULL; | |
170 | |
171 { | |
172 base::AutoLock auto_lock(data_sources_lock_); | |
173 data_sources_.clear(); | |
174 } | |
175 } | |
176 | |
177 void WebMediaPlayerImpl::Proxy::PipelineInitializationCallback( | |
178 PipelineStatus status) { | |
179 render_loop_->PostTask(FROM_HERE, NewRunnableMethod( | |
180 this, &WebMediaPlayerImpl::Proxy::PipelineInitializationTask, status)); | |
181 } | |
182 | |
183 void WebMediaPlayerImpl::Proxy::PipelineSeekCallback(PipelineStatus status) { | |
184 render_loop_->PostTask(FROM_HERE, NewRunnableMethod( | |
185 this, &WebMediaPlayerImpl::Proxy::PipelineSeekTask, status)); | |
186 } | |
187 | |
188 void WebMediaPlayerImpl::Proxy::PipelineEndedCallback(PipelineStatus status) { | |
189 render_loop_->PostTask(FROM_HERE, NewRunnableMethod( | |
190 this, &WebMediaPlayerImpl::Proxy::PipelineEndedTask, status)); | |
191 } | |
192 | |
193 void WebMediaPlayerImpl::Proxy::PipelineErrorCallback(PipelineStatus error) { | |
194 DCHECK_NE(error, media::PIPELINE_OK); | |
195 render_loop_->PostTask(FROM_HERE, NewRunnableMethod( | |
196 this, &WebMediaPlayerImpl::Proxy::PipelineErrorTask, error)); | |
197 } | |
198 | |
199 void WebMediaPlayerImpl::Proxy::NetworkEventCallback(PipelineStatus status) { | |
200 render_loop_->PostTask(FROM_HERE, NewRunnableMethod( | |
201 this, &WebMediaPlayerImpl::Proxy::NetworkEventTask, status)); | |
202 } | |
203 | |
204 void WebMediaPlayerImpl::Proxy::AddDataSource(WebDataSource* data_source) { | |
205 base::AutoLock auto_lock(data_sources_lock_); | |
206 data_sources_.push_back(make_scoped_refptr(data_source)); | |
207 } | |
208 | |
209 void WebMediaPlayerImpl::Proxy::RepaintTask() { | |
210 DCHECK(MessageLoop::current() == render_loop_); | |
211 { | |
212 base::AutoLock auto_lock(lock_); | |
213 --outstanding_repaints_; | |
214 DCHECK_GE(outstanding_repaints_, 0); | |
215 } | |
216 if (webmediaplayer_) { | |
217 webmediaplayer_->Repaint(); | |
218 } | |
219 } | |
220 | |
221 void WebMediaPlayerImpl::Proxy::PipelineInitializationTask( | |
222 PipelineStatus status) { | |
223 DCHECK(MessageLoop::current() == render_loop_); | |
224 if (webmediaplayer_) { | |
225 webmediaplayer_->OnPipelineInitialize(status); | |
226 } | |
227 } | |
228 | |
229 void WebMediaPlayerImpl::Proxy::PipelineSeekTask(PipelineStatus status) { | |
230 DCHECK(MessageLoop::current() == render_loop_); | |
231 if (webmediaplayer_) { | |
232 webmediaplayer_->OnPipelineSeek(status); | |
233 } | |
234 } | |
235 | |
236 void WebMediaPlayerImpl::Proxy::PipelineEndedTask(PipelineStatus status) { | |
237 DCHECK(MessageLoop::current() == render_loop_); | |
238 if (webmediaplayer_) { | |
239 webmediaplayer_->OnPipelineEnded(status); | |
240 } | |
241 } | |
242 | |
243 void WebMediaPlayerImpl::Proxy::PipelineErrorTask(PipelineStatus error) { | |
244 DCHECK(MessageLoop::current() == render_loop_); | |
245 if (webmediaplayer_) { | |
246 webmediaplayer_->OnPipelineError(error); | |
247 } | |
248 } | |
249 | |
250 void WebMediaPlayerImpl::Proxy::NetworkEventTask(PipelineStatus status) { | |
251 DCHECK(MessageLoop::current() == render_loop_); | |
252 if (webmediaplayer_) { | |
253 webmediaplayer_->OnNetworkEvent(status); | |
254 } | |
255 } | |
256 | |
257 void WebMediaPlayerImpl::Proxy::GetCurrentFrame( | |
258 scoped_refptr<media::VideoFrame>* frame_out) { | |
259 if (video_renderer_) | |
260 video_renderer_->GetCurrentFrame(frame_out); | |
261 } | |
262 | |
263 void WebMediaPlayerImpl::Proxy::PutCurrentFrame( | |
264 scoped_refptr<media::VideoFrame> frame) { | |
265 if (video_renderer_) | |
266 video_renderer_->PutCurrentFrame(frame); | |
267 } | |
268 | |
269 void WebMediaPlayerImpl::Proxy::DemuxerOpened(media::ChunkDemuxer* demuxer) { | |
270 render_loop_->PostTask(FROM_HERE, NewRunnableMethod( | |
271 this, &WebMediaPlayerImpl::Proxy::DemuxerOpenedTask, | |
272 scoped_refptr<media::ChunkDemuxer>(demuxer))); | |
273 } | |
274 | |
275 void WebMediaPlayerImpl::Proxy::DemuxerClosed() { | |
276 render_loop_->PostTask(FROM_HERE, NewRunnableMethod( | |
277 this, &WebMediaPlayerImpl::Proxy::DemuxerClosedTask)); | |
278 } | |
279 | |
280 void WebMediaPlayerImpl::Proxy::DemuxerFlush() { | |
281 if (chunk_demuxer_.get()) | |
282 chunk_demuxer_->FlushData(); | |
283 } | |
284 | |
285 bool WebMediaPlayerImpl::Proxy::DemuxerAppend(const uint8* data, | |
286 size_t length) { | |
287 if (chunk_demuxer_.get()) | |
288 return chunk_demuxer_->AppendData(data, length); | |
289 return false; | |
290 } | |
291 | |
292 void WebMediaPlayerImpl::Proxy::DemuxerEndOfStream( | |
293 media::PipelineStatus status) { | |
294 if (chunk_demuxer_.get()) | |
295 chunk_demuxer_->EndOfStream(status); | |
296 } | |
297 | |
298 void WebMediaPlayerImpl::Proxy::DemuxerShutdown() { | |
299 if (chunk_demuxer_.get()) | |
300 chunk_demuxer_->Shutdown(); | |
301 } | |
302 | |
303 void WebMediaPlayerImpl::Proxy::DemuxerOpenedTask( | |
304 const scoped_refptr<media::ChunkDemuxer>& demuxer) { | |
305 DCHECK(MessageLoop::current() == render_loop_); | |
306 chunk_demuxer_ = demuxer; | |
307 if (webmediaplayer_) | |
308 webmediaplayer_->OnDemuxerOpened(); | |
309 } | |
310 | |
311 void WebMediaPlayerImpl::Proxy::DemuxerClosedTask() { | |
312 chunk_demuxer_ = NULL; | |
313 } | |
314 | |
315 ///////////////////////////////////////////////////////////////////////////// | |
316 // WebMediaPlayerImpl implementation | |
317 | |
318 WebMediaPlayerImpl::WebMediaPlayerImpl( | 85 WebMediaPlayerImpl::WebMediaPlayerImpl( |
319 WebKit::WebMediaPlayerClient* client, | 86 WebKit::WebMediaPlayerClient* client, |
320 media::FilterCollection* collection, | 87 media::FilterCollection* collection, |
321 media::MessageLoopFactory* message_loop_factory, | 88 media::MessageLoopFactory* message_loop_factory, |
322 MediaStreamClient* media_stream_client) | 89 MediaStreamClient* media_stream_client) |
323 : network_state_(WebKit::WebMediaPlayer::Empty), | 90 : network_state_(WebKit::WebMediaPlayer::Empty), |
324 ready_state_(WebKit::WebMediaPlayer::HaveNothing), | 91 ready_state_(WebKit::WebMediaPlayer::HaveNothing), |
325 main_loop_(NULL), | 92 main_loop_(NULL), |
326 filter_collection_(collection), | 93 filter_collection_(collection), |
327 pipeline_(NULL), | 94 pipeline_(NULL), |
(...skipping 19 matching lines...) Expand all Loading... |
347 NOTREACHED() << "Could not start PipelineThread"; | 114 NOTREACHED() << "Could not start PipelineThread"; |
348 return false; | 115 return false; |
349 } | 116 } |
350 | 117 |
351 pipeline_ = new media::PipelineImpl(pipeline_message_loop); | 118 pipeline_ = new media::PipelineImpl(pipeline_message_loop); |
352 | 119 |
353 // Also we want to be notified of |main_loop_| destruction. | 120 // Also we want to be notified of |main_loop_| destruction. |
354 main_loop_->AddDestructionObserver(this); | 121 main_loop_->AddDestructionObserver(this); |
355 | 122 |
356 // Creates the proxy. | 123 // Creates the proxy. |
357 proxy_ = new Proxy(main_loop_, this); | 124 proxy_ = new WebMediaPlayerProxy(main_loop_, this); |
358 web_video_renderer->SetWebMediaPlayerImplProxy(proxy_); | 125 web_video_renderer->SetWebMediaPlayerProxy(proxy_); |
359 proxy_->SetVideoRenderer(web_video_renderer); | 126 proxy_->SetVideoRenderer(web_video_renderer); |
360 | 127 |
361 // Set our pipeline callbacks. | 128 // Set our pipeline callbacks. |
362 pipeline_->Init( | 129 pipeline_->Init( |
363 NewCallback(proxy_.get(), | 130 NewCallback(proxy_.get(), |
364 &WebMediaPlayerImpl::Proxy::PipelineEndedCallback), | 131 &WebMediaPlayerProxy::PipelineEndedCallback), |
365 NewCallback(proxy_.get(), | 132 NewCallback(proxy_.get(), |
366 &WebMediaPlayerImpl::Proxy::PipelineErrorCallback), | 133 &WebMediaPlayerProxy::PipelineErrorCallback), |
367 NewCallback(proxy_.get(), | 134 NewCallback(proxy_.get(), |
368 &WebMediaPlayerImpl::Proxy::NetworkEventCallback)); | 135 &WebMediaPlayerProxy::NetworkEventCallback)); |
369 | 136 |
370 // A simple data source that keeps all data in memory. | 137 // A simple data source that keeps all data in memory. |
371 scoped_ptr<media::DataSourceFactory> simple_data_source_factory( | 138 scoped_ptr<media::DataSourceFactory> simple_data_source_factory( |
372 SimpleDataSource::CreateFactory(MessageLoop::current(), frame, | 139 SimpleDataSource::CreateFactory(MessageLoop::current(), frame, |
373 proxy_->GetBuildObserver())); | 140 proxy_->GetBuildObserver())); |
374 | 141 |
375 // A sophisticated data source that does memory caching. | 142 // A sophisticated data source that does memory caching. |
376 scoped_ptr<media::DataSourceFactory> buffered_data_source_factory( | 143 scoped_ptr<media::DataSourceFactory> buffered_data_source_factory( |
377 BufferedDataSource::CreateFactory(MessageLoop::current(), frame, | 144 BufferedDataSource::CreateFactory(MessageLoop::current(), frame, |
378 proxy_->GetBuildObserver())); | 145 proxy_->GetBuildObserver())); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
450 // Get the preload value. | 217 // Get the preload value. |
451 setPreload(GetClient()->preload()); | 218 setPreload(GetClient()->preload()); |
452 | 219 |
453 // Initialize the pipeline. | 220 // Initialize the pipeline. |
454 SetNetworkState(WebKit::WebMediaPlayer::Loading); | 221 SetNetworkState(WebKit::WebMediaPlayer::Loading); |
455 SetReadyState(WebKit::WebMediaPlayer::HaveNothing); | 222 SetReadyState(WebKit::WebMediaPlayer::HaveNothing); |
456 pipeline_->Start( | 223 pipeline_->Start( |
457 filter_collection_.release(), | 224 filter_collection_.release(), |
458 url.spec(), | 225 url.spec(), |
459 NewCallback(proxy_.get(), | 226 NewCallback(proxy_.get(), |
460 &WebMediaPlayerImpl::Proxy::PipelineInitializationCallback)); | 227 &WebMediaPlayerProxy::PipelineInitializationCallback)); |
461 } | 228 } |
462 | 229 |
463 void WebMediaPlayerImpl::cancelLoad() { | 230 void WebMediaPlayerImpl::cancelLoad() { |
464 DCHECK(MessageLoop::current() == main_loop_); | 231 DCHECK(MessageLoop::current() == main_loop_); |
465 } | 232 } |
466 | 233 |
467 void WebMediaPlayerImpl::play() { | 234 void WebMediaPlayerImpl::play() { |
468 DCHECK(MessageLoop::current() == main_loop_); | 235 DCHECK(MessageLoop::current() == main_loop_); |
469 | 236 |
470 paused_ = false; | 237 paused_ = false; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
512 } | 279 } |
513 | 280 |
514 seeking_ = true; | 281 seeking_ = true; |
515 | 282 |
516 proxy_->DemuxerFlush(); | 283 proxy_->DemuxerFlush(); |
517 | 284 |
518 // Kick off the asynchronous seek! | 285 // Kick off the asynchronous seek! |
519 pipeline_->Seek( | 286 pipeline_->Seek( |
520 seek_time, | 287 seek_time, |
521 NewCallback(proxy_.get(), | 288 NewCallback(proxy_.get(), |
522 &WebMediaPlayerImpl::Proxy::PipelineSeekCallback)); | 289 &WebMediaPlayerProxy::PipelineSeekCallback)); |
523 } | 290 } |
524 | 291 |
525 void WebMediaPlayerImpl::setEndTime(float seconds) { | 292 void WebMediaPlayerImpl::setEndTime(float seconds) { |
526 DCHECK(MessageLoop::current() == main_loop_); | 293 DCHECK(MessageLoop::current() == main_loop_); |
527 | 294 |
528 // TODO(hclam): add method call when it has been implemented. | 295 // TODO(hclam): add method call when it has been implemented. |
529 return; | 296 return; |
530 } | 297 } |
531 | 298 |
532 void WebMediaPlayerImpl::setRate(float rate) { | 299 void WebMediaPlayerImpl::setRate(float rate) { |
(...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1027 } | 794 } |
1028 } | 795 } |
1029 | 796 |
1030 WebKit::WebMediaPlayerClient* WebMediaPlayerImpl::GetClient() { | 797 WebKit::WebMediaPlayerClient* WebMediaPlayerImpl::GetClient() { |
1031 DCHECK(MessageLoop::current() == main_loop_); | 798 DCHECK(MessageLoop::current() == main_loop_); |
1032 DCHECK(client_); | 799 DCHECK(client_); |
1033 return client_; | 800 return client_; |
1034 } | 801 } |
1035 | 802 |
1036 } // namespace webkit_glue | 803 } // namespace webkit_glue |
OLD | NEW |