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