OLD | NEW |
1 // Copyright (c) 2008-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2008-2009 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" |
| 6 |
5 #include "base/command_line.h" | 7 #include "base/command_line.h" |
6 #include "googleurl/src/gurl.h" | 8 #include "googleurl/src/gurl.h" |
7 #include "media/filters/ffmpeg_audio_decoder.h" | 9 #include "media/filters/ffmpeg_audio_decoder.h" |
8 #include "media/filters/ffmpeg_demuxer.h" | 10 #include "media/filters/ffmpeg_demuxer.h" |
9 #include "media/filters/ffmpeg_video_decoder.h" | 11 #include "media/filters/ffmpeg_video_decoder.h" |
10 #include "media/filters/null_audio_renderer.h" | 12 #include "media/filters/null_audio_renderer.h" |
11 #include "webkit/api/public/WebRect.h" | 13 #include "webkit/api/public/WebRect.h" |
12 #include "webkit/api/public/WebSize.h" | 14 #include "webkit/api/public/WebSize.h" |
13 #include "webkit/api/public/WebURL.h" | 15 #include "webkit/api/public/WebURL.h" |
14 #include "webkit/glue/media/video_renderer_impl.h" | 16 #include "webkit/glue/media/video_renderer_impl.h" |
15 #include "webkit/glue/webmediaplayer_impl.h" | |
16 | 17 |
17 using WebKit::WebCanvas; | 18 using WebKit::WebCanvas; |
18 using WebKit::WebRect; | 19 using WebKit::WebRect; |
19 using WebKit::WebSize; | 20 using WebKit::WebSize; |
20 | 21 |
| 22 namespace { |
| 23 |
| 24 // Limits the maximum outstanding repaints posted on render thread. |
| 25 // This number of 50 is a guess, it does not take too much memory on the task |
| 26 // queue but gives up a pretty good latency on repaint. |
| 27 const int kMaxOutstandingRepaints = 50; |
| 28 |
| 29 } // namespace |
| 30 |
21 namespace webkit_glue { | 31 namespace webkit_glue { |
22 | 32 |
23 ///////////////////////////////////////////////////////////////////////////// | 33 ///////////////////////////////////////////////////////////////////////////// |
24 // Task to be posted on main thread that fire WebMediaPlayerClient methods. | 34 // WebMediaPlayerImpl::Proxy implementation |
25 | 35 |
26 class NotifyWebMediaPlayerClientTask : public CancelableTask { | 36 WebMediaPlayerImpl::Proxy::Proxy(MessageLoop* render_loop, |
27 public: | 37 WebMediaPlayerImpl* webmediaplayer) |
28 NotifyWebMediaPlayerClientTask(WebMediaPlayerImpl* media_player, | 38 : render_loop_(render_loop), |
29 WebMediaPlayerClientMethod method) | 39 webmediaplayer_(webmediaplayer), |
30 : media_player_(media_player), | 40 outstanding_repaints_(0) { |
31 method_(method) {} | 41 DCHECK(render_loop_); |
| 42 DCHECK(webmediaplayer_); |
| 43 } |
32 | 44 |
33 virtual void Run() { | 45 WebMediaPlayerImpl::Proxy::~Proxy() { |
34 if (media_player_) { | 46 Detach(); |
35 (media_player_->client()->*(method_))(); | 47 } |
36 media_player_->DidTask(this); | 48 |
37 } | 49 void WebMediaPlayerImpl::Proxy::Repaint() { |
| 50 AutoLock auto_lock(lock_); |
| 51 if (outstanding_repaints_ < kMaxOutstandingRepaints) { |
| 52 ++outstanding_repaints_; |
| 53 |
| 54 render_loop_->PostTask(FROM_HERE, |
| 55 NewRunnableMethod(this, &WebMediaPlayerImpl::Proxy::RepaintTask)); |
38 } | 56 } |
| 57 } |
39 | 58 |
40 virtual void Cancel() { | 59 void WebMediaPlayerImpl::Proxy::TimeChanged() { |
41 media_player_ = NULL; | 60 render_loop_->PostTask(FROM_HERE, |
| 61 NewRunnableMethod(this, &WebMediaPlayerImpl::Proxy::TimeChangedTask)); |
| 62 } |
| 63 |
| 64 void WebMediaPlayerImpl::Proxy::NetworkStateChanged( |
| 65 WebKit::WebMediaPlayer::NetworkState state) { |
| 66 render_loop_->PostTask(FROM_HERE, |
| 67 NewRunnableMethod(this, |
| 68 &WebMediaPlayerImpl::Proxy::NetworkStateChangedTask, |
| 69 state)); |
| 70 } |
| 71 |
| 72 void WebMediaPlayerImpl::Proxy::ReadyStateChanged( |
| 73 WebKit::WebMediaPlayer::ReadyState state) { |
| 74 render_loop_->PostTask(FROM_HERE, |
| 75 NewRunnableMethod(this, |
| 76 &WebMediaPlayerImpl::Proxy::ReadyStateChangedTask, |
| 77 state)); |
| 78 } |
| 79 |
| 80 void WebMediaPlayerImpl::Proxy::RepaintTask() { |
| 81 DCHECK(MessageLoop::current() == render_loop_); |
| 82 { |
| 83 AutoLock auto_lock(lock_); |
| 84 --outstanding_repaints_; |
| 85 DCHECK_GE(outstanding_repaints_, 0); |
42 } | 86 } |
| 87 if (webmediaplayer_) |
| 88 webmediaplayer_->Repaint(); |
| 89 } |
43 | 90 |
44 private: | 91 void WebMediaPlayerImpl::Proxy::TimeChangedTask() { |
45 WebMediaPlayerImpl* media_player_; | 92 DCHECK(MessageLoop::current() == render_loop_); |
46 WebMediaPlayerClientMethod method_; | 93 if (webmediaplayer_) |
| 94 webmediaplayer_->TimeChanged(); |
| 95 } |
47 | 96 |
48 DISALLOW_COPY_AND_ASSIGN(NotifyWebMediaPlayerClientTask); | 97 void WebMediaPlayerImpl::Proxy::NetworkStateChangedTask( |
49 }; | 98 WebKit::WebMediaPlayer::NetworkState state) { |
| 99 DCHECK(MessageLoop::current() == render_loop_); |
| 100 if (webmediaplayer_) |
| 101 webmediaplayer_->SetNetworkState(state); |
| 102 } |
| 103 |
| 104 void WebMediaPlayerImpl::Proxy::ReadyStateChangedTask( |
| 105 WebKit::WebMediaPlayer::ReadyState state) { |
| 106 DCHECK(MessageLoop::current() == render_loop_); |
| 107 if (webmediaplayer_) |
| 108 webmediaplayer_->SetReadyState(state); |
| 109 } |
| 110 |
| 111 void WebMediaPlayerImpl::Proxy::SetVideoRenderer( |
| 112 VideoRendererImpl* video_renderer) { |
| 113 video_renderer_ = video_renderer; |
| 114 } |
| 115 |
| 116 void WebMediaPlayerImpl::Proxy::Paint(skia::PlatformCanvas* canvas, |
| 117 const gfx::Rect& dest_rect) { |
| 118 DCHECK(MessageLoop::current() == render_loop_); |
| 119 if (video_renderer_) { |
| 120 video_renderer_->Paint(canvas, dest_rect); |
| 121 } |
| 122 } |
| 123 |
| 124 void WebMediaPlayerImpl::Proxy::SetSize(const gfx::Rect& rect) { |
| 125 DCHECK(MessageLoop::current() == render_loop_); |
| 126 if (video_renderer_) { |
| 127 video_renderer_->SetRect(rect); |
| 128 } |
| 129 } |
| 130 |
| 131 void WebMediaPlayerImpl::Proxy::Detach() { |
| 132 DCHECK(MessageLoop::current() == render_loop_); |
| 133 webmediaplayer_ = NULL; |
| 134 video_renderer_ = NULL; |
| 135 } |
| 136 |
| 137 void WebMediaPlayerImpl::Proxy::PipelineInitializationCallback(bool success) { |
| 138 if (success) { |
| 139 // Since we have initialized the pipeline, say we have everything. |
| 140 // TODO(hclam): change this to report the correct status. Should also post |
| 141 // a task to call to |webmediaplayer_|. |
| 142 ReadyStateChanged(WebKit::WebMediaPlayer::HaveMetadata); |
| 143 ReadyStateChanged(WebKit::WebMediaPlayer::HaveEnoughData); |
| 144 NetworkStateChanged(WebKit::WebMediaPlayer::Loaded); |
| 145 } else { |
| 146 // TODO(hclam): should use pipeline_.GetError() to determine the state |
| 147 // properly and reports error using MediaError. |
| 148 // WebKit uses FormatError to indicate an error for bogus URL or bad file. |
| 149 // Since we are at the initialization stage we can safely treat every error |
| 150 // as format error. Should post a task to call to |webmediaplayer_|. |
| 151 NetworkStateChanged(WebKit::WebMediaPlayer::FormatError); |
| 152 } |
| 153 } |
| 154 |
| 155 void WebMediaPlayerImpl::Proxy::PipelineSeekCallback(bool success) { |
| 156 if (success) |
| 157 TimeChanged(); |
| 158 } |
50 | 159 |
51 ///////////////////////////////////////////////////////////////////////////// | 160 ///////////////////////////////////////////////////////////////////////////// |
52 // WebMediaPlayerImpl implementation | 161 // WebMediaPlayerImpl implementation |
53 | 162 |
54 WebMediaPlayerImpl::WebMediaPlayerImpl(WebKit::WebMediaPlayerClient* client, | 163 WebMediaPlayerImpl::WebMediaPlayerImpl(WebKit::WebMediaPlayerClient* client, |
55 media::FilterFactoryCollection* factory) | 164 media::FilterFactoryCollection* factory) |
56 : network_state_(WebKit::WebMediaPlayer::Empty), | 165 : network_state_(WebKit::WebMediaPlayer::Empty), |
57 ready_state_(WebKit::WebMediaPlayer::HaveNothing), | 166 ready_state_(WebKit::WebMediaPlayer::HaveNothing), |
58 main_loop_(NULL), | 167 main_loop_(NULL), |
59 filter_factory_(factory), | 168 filter_factory_(factory), |
60 video_renderer_(NULL), | 169 client_(client) { |
61 client_(client), | |
62 tasks_(kLastTaskIndex) { | |
63 // Add in the default filter factories. | |
64 filter_factory_->AddFactory(media::FFmpegDemuxer::CreateFilterFactory()); | |
65 filter_factory_->AddFactory(media::FFmpegAudioDecoder::CreateFactory()); | |
66 filter_factory_->AddFactory(media::FFmpegVideoDecoder::CreateFactory()); | |
67 filter_factory_->AddFactory(media::NullAudioRenderer::CreateFilterFactory()); | |
68 filter_factory_->AddFactory(VideoRendererImpl::CreateFactory(this)); | |
69 | |
70 DCHECK(client_); | |
71 | |
72 // Saves the current message loop. | 170 // Saves the current message loop. |
73 DCHECK(!main_loop_); | 171 DCHECK(!main_loop_); |
74 main_loop_ = MessageLoop::current(); | 172 main_loop_ = MessageLoop::current(); |
75 | 173 |
76 // Also we want to be notified of |main_loop_| destruction. | 174 // Also we want to be notified of |main_loop_| destruction. |
77 main_loop_->AddDestructionObserver(this); | 175 main_loop_->AddDestructionObserver(this); |
| 176 |
| 177 // Creates the proxy. |
| 178 proxy_ = new Proxy(main_loop_, this); |
| 179 |
| 180 // Add in the default filter factories. |
| 181 filter_factory_->AddFactory(media::FFmpegDemuxer::CreateFilterFactory()); |
| 182 filter_factory_->AddFactory(media::FFmpegAudioDecoder::CreateFactory()); |
| 183 filter_factory_->AddFactory(media::FFmpegVideoDecoder::CreateFactory()); |
| 184 filter_factory_->AddFactory(media::NullAudioRenderer::CreateFilterFactory()); |
| 185 filter_factory_->AddFactory(VideoRendererImpl::CreateFactory(proxy_)); |
78 } | 186 } |
79 | 187 |
80 WebMediaPlayerImpl::~WebMediaPlayerImpl() { | 188 WebMediaPlayerImpl::~WebMediaPlayerImpl() { |
81 pipeline_.Stop(); | 189 Destroy(); |
82 | |
83 // Cancel all tasks posted on the |main_loop_|. | |
84 CancelAllTasks(); | |
85 | 190 |
86 // Finally tell the |main_loop_| we don't want to be notified of destruction | 191 // Finally tell the |main_loop_| we don't want to be notified of destruction |
87 // event. | 192 // event. |
88 if (main_loop_) { | 193 if (main_loop_) { |
89 main_loop_->RemoveDestructionObserver(this); | 194 main_loop_->RemoveDestructionObserver(this); |
90 } | 195 } |
91 } | 196 } |
92 | 197 |
93 void WebMediaPlayerImpl::load(const WebKit::WebURL& url) { | 198 void WebMediaPlayerImpl::load(const WebKit::WebURL& url) { |
94 DCHECK(main_loop_ && MessageLoop::current() == main_loop_); | 199 DCHECK(MessageLoop::current() == main_loop_); |
| 200 DCHECK(proxy_); |
95 | 201 |
96 // Initialize the pipeline. | 202 // Initialize the pipeline. |
97 if (network_state_ != WebKit::WebMediaPlayer::Loading) { | 203 SetNetworkState(WebKit::WebMediaPlayer::Loading); |
98 network_state_ = WebKit::WebMediaPlayer::Loading; | 204 SetReadyState(WebKit::WebMediaPlayer::HaveNothing); |
99 client_->networkStateChanged(); | 205 pipeline_.Start( |
100 } | 206 filter_factory_.get(), |
101 if (ready_state_ != WebKit::WebMediaPlayer::HaveNothing) { | 207 url.spec(), |
102 ready_state_ = WebKit::WebMediaPlayer::HaveNothing; | 208 NewCallback(proxy_.get(), |
103 client_->readyStateChanged(); | 209 &WebMediaPlayerImpl::Proxy::PipelineInitializationCallback)); |
104 } | |
105 pipeline_.Start(filter_factory_.get(), url.spec(), | |
106 NewCallback(this, &WebMediaPlayerImpl::OnPipelineInitialize)); | |
107 } | 210 } |
108 | 211 |
109 void WebMediaPlayerImpl::cancelLoad() { | 212 void WebMediaPlayerImpl::cancelLoad() { |
110 DCHECK(main_loop_ && MessageLoop::current() == main_loop_); | 213 DCHECK(MessageLoop::current() == main_loop_); |
111 | |
112 // TODO(hclam): Calls to render_view_ to stop resource load | |
113 } | 214 } |
114 | 215 |
115 void WebMediaPlayerImpl::play() { | 216 void WebMediaPlayerImpl::play() { |
116 DCHECK(main_loop_ && MessageLoop::current() == main_loop_); | 217 DCHECK(MessageLoop::current() == main_loop_); |
117 | 218 |
118 // TODO(hclam): We should restore the previous playback rate rather than | 219 // TODO(hclam): We should restore the previous playback rate rather than |
119 // having it at 1.0. | 220 // having it at 1.0. |
120 pipeline_.SetPlaybackRate(1.0f); | 221 pipeline_.SetPlaybackRate(1.0f); |
121 } | 222 } |
122 | 223 |
123 void WebMediaPlayerImpl::pause() { | 224 void WebMediaPlayerImpl::pause() { |
124 DCHECK(main_loop_ && MessageLoop::current() == main_loop_); | 225 DCHECK(MessageLoop::current() == main_loop_); |
125 | 226 |
126 pipeline_.SetPlaybackRate(0.0f); | 227 pipeline_.SetPlaybackRate(0.0f); |
127 } | 228 } |
128 | 229 |
129 void WebMediaPlayerImpl::stop() { | |
130 DCHECK(main_loop_ && MessageLoop::current() == main_loop_); | |
131 | |
132 // We can fire Stop() multiple times. | |
133 pipeline_.Stop(); | |
134 } | |
135 | |
136 void WebMediaPlayerImpl::seek(float seconds) { | 230 void WebMediaPlayerImpl::seek(float seconds) { |
137 DCHECK(main_loop_ && MessageLoop::current() == main_loop_); | 231 DCHECK(MessageLoop::current() == main_loop_); |
138 | 232 |
139 // Try to preserve as much accuracy as possible. | 233 // Try to preserve as much accuracy as possible. |
140 float microseconds = seconds * base::Time::kMicrosecondsPerSecond; | 234 float microseconds = seconds * base::Time::kMicrosecondsPerSecond; |
141 if (seconds != 0) | 235 if (seconds != 0) |
142 pipeline_.Seek( | 236 pipeline_.Seek( |
143 base::TimeDelta::FromMicroseconds(static_cast<int64>(microseconds)), | 237 base::TimeDelta::FromMicroseconds(static_cast<int64>(microseconds)), |
144 NewCallback(this, &WebMediaPlayerImpl::OnPipelineSeek)); | 238 NewCallback(proxy_.get(), |
| 239 &WebMediaPlayerImpl::Proxy::PipelineSeekCallback)); |
145 } | 240 } |
146 | 241 |
147 void WebMediaPlayerImpl::setEndTime(float seconds) { | 242 void WebMediaPlayerImpl::setEndTime(float seconds) { |
148 DCHECK(main_loop_ && MessageLoop::current() == main_loop_); | 243 DCHECK(MessageLoop::current() == main_loop_); |
149 | 244 |
150 // TODO(hclam): add method call when it has been implemented. | 245 // TODO(hclam): add method call when it has been implemented. |
151 return; | 246 return; |
152 } | 247 } |
153 | 248 |
154 void WebMediaPlayerImpl::setRate(float rate) { | 249 void WebMediaPlayerImpl::setRate(float rate) { |
155 DCHECK(main_loop_ && MessageLoop::current() == main_loop_); | 250 DCHECK(MessageLoop::current() == main_loop_); |
156 | 251 |
157 pipeline_.SetPlaybackRate(rate); | 252 pipeline_.SetPlaybackRate(rate); |
158 } | 253 } |
159 | 254 |
160 void WebMediaPlayerImpl::setVolume(float volume) { | 255 void WebMediaPlayerImpl::setVolume(float volume) { |
161 DCHECK(main_loop_ && MessageLoop::current() == main_loop_); | 256 DCHECK(MessageLoop::current() == main_loop_); |
162 | 257 |
163 pipeline_.SetVolume(volume); | 258 pipeline_.SetVolume(volume); |
164 } | 259 } |
165 | 260 |
166 void WebMediaPlayerImpl::setVisible(bool visible) { | 261 void WebMediaPlayerImpl::setVisible(bool visible) { |
167 DCHECK(main_loop_ && MessageLoop::current() == main_loop_); | 262 DCHECK(MessageLoop::current() == main_loop_); |
168 | 263 |
169 // TODO(hclam): add appropriate method call when pipeline has it implemented. | 264 // TODO(hclam): add appropriate method call when pipeline has it implemented. |
170 return; | 265 return; |
171 } | 266 } |
172 | 267 |
173 bool WebMediaPlayerImpl::setAutoBuffer(bool autoBuffer) { | 268 bool WebMediaPlayerImpl::setAutoBuffer(bool autoBuffer) { |
174 DCHECK(main_loop_ && MessageLoop::current() == main_loop_); | 269 DCHECK(MessageLoop::current() == main_loop_); |
175 | 270 |
176 return false; | 271 return false; |
177 } | 272 } |
178 | 273 |
179 bool WebMediaPlayerImpl::totalBytesKnown() { | 274 bool WebMediaPlayerImpl::totalBytesKnown() { |
180 DCHECK(main_loop_ && MessageLoop::current() == main_loop_); | 275 DCHECK(MessageLoop::current() == main_loop_); |
181 | 276 |
182 return pipeline_.GetTotalBytes() != 0; | 277 return pipeline_.GetTotalBytes() != 0; |
183 } | 278 } |
184 | 279 |
185 bool WebMediaPlayerImpl::hasVideo() const { | 280 bool WebMediaPlayerImpl::hasVideo() const { |
186 DCHECK(main_loop_ && MessageLoop::current() == main_loop_); | 281 DCHECK(MessageLoop::current() == main_loop_); |
187 | 282 |
188 size_t width, height; | 283 size_t width, height; |
189 pipeline_.GetVideoSize(&width, &height); | 284 pipeline_.GetVideoSize(&width, &height); |
190 return width != 0 && height != 0; | 285 return width != 0 && height != 0; |
191 } | 286 } |
192 | 287 |
193 WebKit::WebSize WebMediaPlayerImpl::naturalSize() const { | 288 WebKit::WebSize WebMediaPlayerImpl::naturalSize() const { |
194 DCHECK(main_loop_ && MessageLoop::current() == main_loop_); | 289 DCHECK(MessageLoop::current() == main_loop_); |
195 | 290 |
196 size_t width, height; | 291 size_t width, height; |
197 pipeline_.GetVideoSize(&width, &height); | 292 pipeline_.GetVideoSize(&width, &height); |
198 return WebKit::WebSize(width, height); | 293 return WebKit::WebSize(width, height); |
199 } | 294 } |
200 | 295 |
201 bool WebMediaPlayerImpl::paused() const { | 296 bool WebMediaPlayerImpl::paused() const { |
202 DCHECK(main_loop_ && MessageLoop::current() == main_loop_); | 297 DCHECK(MessageLoop::current() == main_loop_); |
203 | 298 |
204 return pipeline_.GetPlaybackRate() == 0.0f; | 299 return pipeline_.GetPlaybackRate() == 0.0f; |
205 } | 300 } |
206 | 301 |
207 bool WebMediaPlayerImpl::seeking() const { | 302 bool WebMediaPlayerImpl::seeking() const { |
208 DCHECK(main_loop_ && MessageLoop::current() == main_loop_); | 303 DCHECK(MessageLoop::current() == main_loop_); |
209 | 304 |
210 return tasks_[kTimeChangedTaskIndex] != NULL; | 305 return false; |
211 } | 306 } |
212 | 307 |
213 float WebMediaPlayerImpl::duration() const { | 308 float WebMediaPlayerImpl::duration() const { |
214 DCHECK(main_loop_ && MessageLoop::current() == main_loop_); | 309 DCHECK(MessageLoop::current() == main_loop_); |
215 | 310 |
216 return static_cast<float>(pipeline_.GetDuration().InSecondsF()); | 311 return static_cast<float>(pipeline_.GetDuration().InSecondsF()); |
217 } | 312 } |
218 | 313 |
219 float WebMediaPlayerImpl::currentTime() const { | 314 float WebMediaPlayerImpl::currentTime() const { |
220 DCHECK(main_loop_ && MessageLoop::current() == main_loop_); | 315 DCHECK(MessageLoop::current() == main_loop_); |
221 | 316 |
222 return static_cast<float>(pipeline_.GetTime().InSecondsF()); | 317 return static_cast<float>(pipeline_.GetTime().InSecondsF()); |
223 } | 318 } |
224 | 319 |
225 int WebMediaPlayerImpl::dataRate() const { | 320 int WebMediaPlayerImpl::dataRate() const { |
226 DCHECK(main_loop_ && MessageLoop::current() == main_loop_); | 321 DCHECK(MessageLoop::current() == main_loop_); |
227 | 322 |
228 // TODO(hclam): Add this method call if pipeline has it in the interface. | 323 // TODO(hclam): Add this method call if pipeline has it in the interface. |
229 return 0; | 324 return 0; |
230 } | 325 } |
231 | 326 |
232 float WebMediaPlayerImpl::maxTimeBuffered() const { | 327 float WebMediaPlayerImpl::maxTimeBuffered() const { |
233 DCHECK(main_loop_ && MessageLoop::current() == main_loop_); | 328 DCHECK(MessageLoop::current() == main_loop_); |
234 | 329 |
235 return static_cast<float>(pipeline_.GetBufferedTime().InSecondsF()); | 330 return static_cast<float>(pipeline_.GetBufferedTime().InSecondsF()); |
236 } | 331 } |
237 | 332 |
238 float WebMediaPlayerImpl::maxTimeSeekable() const { | 333 float WebMediaPlayerImpl::maxTimeSeekable() const { |
239 DCHECK(main_loop_ && MessageLoop::current() == main_loop_); | 334 DCHECK(MessageLoop::current() == main_loop_); |
240 | 335 |
241 // TODO(scherkus): move this logic down into the pipeline. | 336 // TODO(scherkus): move this logic down into the pipeline. |
242 if (pipeline_.GetTotalBytes() == 0) { | 337 if (pipeline_.GetTotalBytes() == 0) { |
243 return 0.0f; | 338 return 0.0f; |
244 } | 339 } |
245 double total_bytes = static_cast<double>(pipeline_.GetTotalBytes()); | 340 double total_bytes = static_cast<double>(pipeline_.GetTotalBytes()); |
246 double buffered_bytes = static_cast<double>(pipeline_.GetBufferedBytes()); | 341 double buffered_bytes = static_cast<double>(pipeline_.GetBufferedBytes()); |
247 double duration = static_cast<double>(pipeline_.GetDuration().InSecondsF()); | 342 double duration = static_cast<double>(pipeline_.GetDuration().InSecondsF()); |
248 return static_cast<float>(duration * (buffered_bytes / total_bytes)); | 343 return static_cast<float>(duration * (buffered_bytes / total_bytes)); |
249 } | 344 } |
250 | 345 |
251 unsigned long long WebMediaPlayerImpl::bytesLoaded() const { | 346 unsigned long long WebMediaPlayerImpl::bytesLoaded() const { |
252 DCHECK(main_loop_ && MessageLoop::current() == main_loop_); | 347 DCHECK(MessageLoop::current() == main_loop_); |
253 | 348 |
254 return pipeline_.GetBufferedBytes(); | 349 return pipeline_.GetBufferedBytes(); |
255 } | 350 } |
256 | 351 |
257 unsigned long long WebMediaPlayerImpl::totalBytes() const { | 352 unsigned long long WebMediaPlayerImpl::totalBytes() const { |
258 DCHECK(main_loop_ && MessageLoop::current() == main_loop_); | 353 DCHECK(MessageLoop::current() == main_loop_); |
259 | 354 |
260 return pipeline_.GetTotalBytes(); | 355 return pipeline_.GetTotalBytes(); |
261 } | 356 } |
262 | 357 |
263 void WebMediaPlayerImpl::setSize(const WebSize& size) { | 358 void WebMediaPlayerImpl::setSize(const WebSize& size) { |
264 DCHECK(main_loop_ && MessageLoop::current() == main_loop_); | 359 DCHECK(MessageLoop::current() == main_loop_); |
| 360 DCHECK(proxy_); |
265 | 361 |
266 if (video_renderer_) { | 362 proxy_->SetSize(gfx::Rect(0, 0, size.width, size.height)); |
267 // TODO(scherkus): Change API to use SetSize(). | |
268 video_renderer_->SetRect(gfx::Rect(0, 0, size.width, size.height)); | |
269 } | |
270 } | 363 } |
271 | 364 |
272 void WebMediaPlayerImpl::paint(WebCanvas* canvas, | 365 void WebMediaPlayerImpl::paint(WebCanvas* canvas, |
273 const WebRect& rect) { | 366 const WebRect& rect) { |
274 DCHECK(main_loop_ && MessageLoop::current() == main_loop_); | 367 DCHECK(MessageLoop::current() == main_loop_); |
| 368 DCHECK(proxy_); |
275 | 369 |
276 if (video_renderer_) { | 370 proxy_->Paint(canvas, rect); |
277 video_renderer_->Paint(canvas, rect); | 371 } |
| 372 |
| 373 void WebMediaPlayerImpl::WillDestroyCurrentMessageLoop() { |
| 374 Destroy(); |
| 375 main_loop_ = NULL; |
| 376 } |
| 377 |
| 378 void WebMediaPlayerImpl::Repaint() { |
| 379 DCHECK(MessageLoop::current() == main_loop_); |
| 380 GetClient()->repaint(); |
| 381 } |
| 382 |
| 383 void WebMediaPlayerImpl::TimeChanged() { |
| 384 DCHECK(MessageLoop::current() == main_loop_); |
| 385 GetClient()->timeChanged(); |
| 386 } |
| 387 |
| 388 void WebMediaPlayerImpl::SetNetworkState( |
| 389 WebKit::WebMediaPlayer::NetworkState state) { |
| 390 DCHECK(MessageLoop::current() == main_loop_); |
| 391 if (network_state_ != state) { |
| 392 network_state_ = state; |
| 393 GetClient()->networkStateChanged(); |
278 } | 394 } |
279 } | 395 } |
280 | 396 |
281 void WebMediaPlayerImpl::WillDestroyCurrentMessageLoop() { | 397 void WebMediaPlayerImpl::SetReadyState( |
282 pipeline_.Stop(); | 398 WebKit::WebMediaPlayer::ReadyState state) { |
283 } | 399 DCHECK(MessageLoop::current() == main_loop_); |
284 | 400 if (ready_state_ != state) { |
285 void WebMediaPlayerImpl::OnPipelineInitialize(bool successful) { | 401 ready_state_ = state; |
286 WebKit::WebMediaPlayer::ReadyState old_ready_state = ready_state_; | 402 GetClient()->readyStateChanged(); |
287 WebKit::WebMediaPlayer::NetworkState old_network_state = network_state_; | |
288 if (successful) { | |
289 // Since we have initialized the pipeline, say we have everything. | |
290 // TODO(hclam): change this to report the correct status. | |
291 ready_state_ = WebKit::WebMediaPlayer::HaveEnoughData; | |
292 network_state_ = WebKit::WebMediaPlayer::Loaded; | |
293 } else { | |
294 // TODO(hclam): should use pipeline_.GetError() to determine the state | |
295 // properly and reports error using MediaError. | |
296 // WebKit uses FormatError to indicate an error for bogus URL or bad file. | |
297 // Since we are at the initialization stage we can safely treat every error | |
298 // as format error. | |
299 network_state_ = WebKit::WebMediaPlayer::FormatError; | |
300 } | |
301 | |
302 if (network_state_ != old_network_state) { | |
303 PostTask(kNetworkStateTaskIndex, | |
304 &WebKit::WebMediaPlayerClient::networkStateChanged); | |
305 } | |
306 if (ready_state_ != old_ready_state) { | |
307 PostTask(kReadyStateTaskIndex, | |
308 &WebKit::WebMediaPlayerClient::readyStateChanged); | |
309 } | 403 } |
310 } | 404 } |
311 | 405 |
312 void WebMediaPlayerImpl::OnPipelineSeek(bool successful) { | 406 void WebMediaPlayerImpl::Destroy() { |
313 PostTask(kTimeChangedTaskIndex, | 407 DCHECK(MessageLoop::current() == main_loop_); |
314 &WebKit::WebMediaPlayerClient::timeChanged); | |
315 } | |
316 | 408 |
317 void WebMediaPlayerImpl::SetVideoRenderer(VideoRendererImpl* video_renderer) { | 409 // Make sure to kill the pipeline so there's no more media threads running. |
318 video_renderer_ = video_renderer; | 410 // TODO(hclam): stopping the pipeline is synchronous so it might block |
319 } | 411 // stopping for a long time. |
| 412 pipeline_.Stop(); |
320 | 413 |
321 void WebMediaPlayerImpl::DidTask(CancelableTask* task) { | 414 // And then detach the proxy, it may live on the render thread for a little |
322 AutoLock auto_lock(task_lock_); | 415 // longer until all the tasks are finished. |
323 | 416 if (proxy_) { |
324 for (size_t i = 0; i < tasks_.size(); ++i) { | 417 proxy_->Detach(); |
325 if (tasks_[i] == task) { | 418 proxy_ = NULL; |
326 tasks_[i] = NULL; | |
327 return; | |
328 } | |
329 } | |
330 NOTREACHED(); | |
331 } | |
332 | |
333 void WebMediaPlayerImpl::CancelAllTasks() { | |
334 AutoLock auto_lock(task_lock_); | |
335 // Loop through the list of tasks and cancel tasks that are still alive. | |
336 for (size_t i = 0; i < tasks_.size(); ++i) { | |
337 if (tasks_[i]) | |
338 tasks_[i]->Cancel(); | |
339 } | 419 } |
340 } | 420 } |
341 | 421 |
342 void WebMediaPlayerImpl::PostTask(int index, | 422 WebKit::WebMediaPlayerClient* WebMediaPlayerImpl::GetClient() { |
343 WebMediaPlayerClientMethod method) { | 423 DCHECK(MessageLoop::current() == main_loop_); |
344 DCHECK(main_loop_); | 424 DCHECK(client_); |
345 | 425 return client_; |
346 AutoLock auto_lock(task_lock_); | |
347 if (!tasks_[index]) { | |
348 CancelableTask* task = new NotifyWebMediaPlayerClientTask(this, method); | |
349 tasks_[index] = task; | |
350 main_loop_->PostTask(FROM_HERE, task); | |
351 } | |
352 } | |
353 | |
354 void WebMediaPlayerImpl::PostRepaintTask() { | |
355 PostTask(kRepaintTaskIndex, &WebKit::WebMediaPlayerClient::repaint); | |
356 } | 426 } |
357 | 427 |
358 } // namespace webkit_glue | 428 } // namespace webkit_glue |
OLD | NEW |