| 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 |