| 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" | 5 #include "webkit/glue/webmediaplayer_impl.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "googleurl/src/gurl.h" | 8 #include "googleurl/src/gurl.h" |
| 9 #include "media/filters/ffmpeg_audio_decoder.h" | 9 #include "media/filters/ffmpeg_audio_decoder.h" |
| 10 #include "media/filters/ffmpeg_demuxer.h" | 10 #include "media/filters/ffmpeg_demuxer.h" |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 | 136 |
| 137 void WebMediaPlayerImpl::Proxy::PipelineInitializationCallback(bool success) { | 137 void WebMediaPlayerImpl::Proxy::PipelineInitializationCallback(bool success) { |
| 138 if (success) { | 138 if (success) { |
| 139 // Since we have initialized the pipeline, say we have everything. | 139 // Since we have initialized the pipeline, say we have everything. |
| 140 // TODO(hclam): change this to report the correct status. Should also post | 140 // TODO(hclam): change this to report the correct status. Should also post |
| 141 // a task to call to |webmediaplayer_|. | 141 // a task to call to |webmediaplayer_|. |
| 142 ReadyStateChanged(WebKit::WebMediaPlayer::HaveMetadata); | 142 ReadyStateChanged(WebKit::WebMediaPlayer::HaveMetadata); |
| 143 ReadyStateChanged(WebKit::WebMediaPlayer::HaveEnoughData); | 143 ReadyStateChanged(WebKit::WebMediaPlayer::HaveEnoughData); |
| 144 NetworkStateChanged(WebKit::WebMediaPlayer::Loaded); | 144 NetworkStateChanged(WebKit::WebMediaPlayer::Loaded); |
| 145 } else { | 145 } else { |
| 146 // TODO(hclam): should use pipeline_.GetError() to determine the state | 146 // TODO(hclam): should use pipeline_->GetError() to determine the state |
| 147 // properly and reports error using MediaError. | 147 // properly and reports error using MediaError. |
| 148 // WebKit uses FormatError to indicate an error for bogus URL or bad file. | 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 | 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_|. | 150 // as format error. Should post a task to call to |webmediaplayer_|. |
| 151 NetworkStateChanged(WebKit::WebMediaPlayer::FormatError); | 151 NetworkStateChanged(WebKit::WebMediaPlayer::FormatError); |
| 152 } | 152 } |
| 153 } | 153 } |
| 154 | 154 |
| 155 void WebMediaPlayerImpl::Proxy::PipelineSeekCallback(bool success) { | 155 void WebMediaPlayerImpl::Proxy::PipelineSeekCallback(bool success) { |
| 156 if (success) | 156 if (success) |
| 157 TimeChanged(); | 157 TimeChanged(); |
| 158 } | 158 } |
| 159 | 159 |
| 160 ///////////////////////////////////////////////////////////////////////////// | 160 ///////////////////////////////////////////////////////////////////////////// |
| 161 // WebMediaPlayerImpl implementation | 161 // WebMediaPlayerImpl implementation |
| 162 | 162 |
| 163 WebMediaPlayerImpl::WebMediaPlayerImpl(WebKit::WebMediaPlayerClient* client, | 163 WebMediaPlayerImpl::WebMediaPlayerImpl(WebKit::WebMediaPlayerClient* client, |
| 164 media::FilterFactoryCollection* factory) | 164 media::FilterFactoryCollection* factory) |
| 165 : network_state_(WebKit::WebMediaPlayer::Empty), | 165 : network_state_(WebKit::WebMediaPlayer::Empty), |
| 166 ready_state_(WebKit::WebMediaPlayer::HaveNothing), | 166 ready_state_(WebKit::WebMediaPlayer::HaveNothing), |
| 167 main_loop_(NULL), | 167 main_loop_(NULL), |
| 168 filter_factory_(factory), | 168 filter_factory_(factory), |
| 169 pipeline_thread_("PipelineThread"), |
| 169 client_(client) { | 170 client_(client) { |
| 170 // Saves the current message loop. | 171 // Saves the current message loop. |
| 171 DCHECK(!main_loop_); | 172 DCHECK(!main_loop_); |
| 172 main_loop_ = MessageLoop::current(); | 173 main_loop_ = MessageLoop::current(); |
| 173 | 174 |
| 175 // Create the pipeline and its thread. |
| 176 if (!pipeline_thread_.Start()) { |
| 177 NOTREACHED() << "Could not start PipelineThread"; |
| 178 } else { |
| 179 pipeline_.reset(new media::PipelineImpl(pipeline_thread_.message_loop())); |
| 180 } |
| 181 |
| 174 // Also we want to be notified of |main_loop_| destruction. | 182 // Also we want to be notified of |main_loop_| destruction. |
| 175 main_loop_->AddDestructionObserver(this); | 183 main_loop_->AddDestructionObserver(this); |
| 176 | 184 |
| 177 // Creates the proxy. | 185 // Creates the proxy. |
| 178 proxy_ = new Proxy(main_loop_, this); | 186 proxy_ = new Proxy(main_loop_, this); |
| 179 | 187 |
| 180 // Add in the default filter factories. | 188 // Add in the default filter factories. |
| 181 filter_factory_->AddFactory(media::FFmpegDemuxer::CreateFilterFactory()); | 189 filter_factory_->AddFactory(media::FFmpegDemuxer::CreateFilterFactory()); |
| 182 filter_factory_->AddFactory(media::FFmpegAudioDecoder::CreateFactory()); | 190 filter_factory_->AddFactory(media::FFmpegAudioDecoder::CreateFactory()); |
| 183 filter_factory_->AddFactory(media::FFmpegVideoDecoder::CreateFactory()); | 191 filter_factory_->AddFactory(media::FFmpegVideoDecoder::CreateFactory()); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 195 } | 203 } |
| 196 } | 204 } |
| 197 | 205 |
| 198 void WebMediaPlayerImpl::load(const WebKit::WebURL& url) { | 206 void WebMediaPlayerImpl::load(const WebKit::WebURL& url) { |
| 199 DCHECK(MessageLoop::current() == main_loop_); | 207 DCHECK(MessageLoop::current() == main_loop_); |
| 200 DCHECK(proxy_); | 208 DCHECK(proxy_); |
| 201 | 209 |
| 202 // Initialize the pipeline. | 210 // Initialize the pipeline. |
| 203 SetNetworkState(WebKit::WebMediaPlayer::Loading); | 211 SetNetworkState(WebKit::WebMediaPlayer::Loading); |
| 204 SetReadyState(WebKit::WebMediaPlayer::HaveNothing); | 212 SetReadyState(WebKit::WebMediaPlayer::HaveNothing); |
| 205 pipeline_.Start( | 213 pipeline_->Start( |
| 206 filter_factory_.get(), | 214 filter_factory_.get(), |
| 207 url.spec(), | 215 url.spec(), |
| 208 NewCallback(proxy_.get(), | 216 NewCallback(proxy_.get(), |
| 209 &WebMediaPlayerImpl::Proxy::PipelineInitializationCallback)); | 217 &WebMediaPlayerImpl::Proxy::PipelineInitializationCallback)); |
| 210 } | 218 } |
| 211 | 219 |
| 212 void WebMediaPlayerImpl::cancelLoad() { | 220 void WebMediaPlayerImpl::cancelLoad() { |
| 213 DCHECK(MessageLoop::current() == main_loop_); | 221 DCHECK(MessageLoop::current() == main_loop_); |
| 214 } | 222 } |
| 215 | 223 |
| 216 void WebMediaPlayerImpl::play() { | 224 void WebMediaPlayerImpl::play() { |
| 217 DCHECK(MessageLoop::current() == main_loop_); | 225 DCHECK(MessageLoop::current() == main_loop_); |
| 218 | 226 |
| 219 // TODO(hclam): We should restore the previous playback rate rather than | 227 // TODO(hclam): We should restore the previous playback rate rather than |
| 220 // having it at 1.0. | 228 // having it at 1.0. |
| 221 pipeline_.SetPlaybackRate(1.0f); | 229 pipeline_->SetPlaybackRate(1.0f); |
| 222 } | 230 } |
| 223 | 231 |
| 224 void WebMediaPlayerImpl::pause() { | 232 void WebMediaPlayerImpl::pause() { |
| 225 DCHECK(MessageLoop::current() == main_loop_); | 233 DCHECK(MessageLoop::current() == main_loop_); |
| 226 | 234 |
| 227 pipeline_.SetPlaybackRate(0.0f); | 235 pipeline_->SetPlaybackRate(0.0f); |
| 228 } | 236 } |
| 229 | 237 |
| 230 void WebMediaPlayerImpl::seek(float seconds) { | 238 void WebMediaPlayerImpl::seek(float seconds) { |
| 231 DCHECK(MessageLoop::current() == main_loop_); | 239 DCHECK(MessageLoop::current() == main_loop_); |
| 232 | 240 |
| 233 // Try to preserve as much accuracy as possible. | 241 // Try to preserve as much accuracy as possible. |
| 234 float microseconds = seconds * base::Time::kMicrosecondsPerSecond; | 242 float microseconds = seconds * base::Time::kMicrosecondsPerSecond; |
| 235 if (seconds != 0) | 243 if (seconds != 0) |
| 236 pipeline_.Seek( | 244 pipeline_->Seek( |
| 237 base::TimeDelta::FromMicroseconds(static_cast<int64>(microseconds)), | 245 base::TimeDelta::FromMicroseconds(static_cast<int64>(microseconds)), |
| 238 NewCallback(proxy_.get(), | 246 NewCallback(proxy_.get(), |
| 239 &WebMediaPlayerImpl::Proxy::PipelineSeekCallback)); | 247 &WebMediaPlayerImpl::Proxy::PipelineSeekCallback)); |
| 240 } | 248 } |
| 241 | 249 |
| 242 void WebMediaPlayerImpl::setEndTime(float seconds) { | 250 void WebMediaPlayerImpl::setEndTime(float seconds) { |
| 243 DCHECK(MessageLoop::current() == main_loop_); | 251 DCHECK(MessageLoop::current() == main_loop_); |
| 244 | 252 |
| 245 // TODO(hclam): add method call when it has been implemented. | 253 // TODO(hclam): add method call when it has been implemented. |
| 246 return; | 254 return; |
| 247 } | 255 } |
| 248 | 256 |
| 249 void WebMediaPlayerImpl::setRate(float rate) { | 257 void WebMediaPlayerImpl::setRate(float rate) { |
| 250 DCHECK(MessageLoop::current() == main_loop_); | 258 DCHECK(MessageLoop::current() == main_loop_); |
| 251 | 259 |
| 252 pipeline_.SetPlaybackRate(rate); | 260 pipeline_->SetPlaybackRate(rate); |
| 253 } | 261 } |
| 254 | 262 |
| 255 void WebMediaPlayerImpl::setVolume(float volume) { | 263 void WebMediaPlayerImpl::setVolume(float volume) { |
| 256 DCHECK(MessageLoop::current() == main_loop_); | 264 DCHECK(MessageLoop::current() == main_loop_); |
| 257 | 265 |
| 258 pipeline_.SetVolume(volume); | 266 pipeline_->SetVolume(volume); |
| 259 } | 267 } |
| 260 | 268 |
| 261 void WebMediaPlayerImpl::setVisible(bool visible) { | 269 void WebMediaPlayerImpl::setVisible(bool visible) { |
| 262 DCHECK(MessageLoop::current() == main_loop_); | 270 DCHECK(MessageLoop::current() == main_loop_); |
| 263 | 271 |
| 264 // TODO(hclam): add appropriate method call when pipeline has it implemented. | 272 // TODO(hclam): add appropriate method call when pipeline has it implemented. |
| 265 return; | 273 return; |
| 266 } | 274 } |
| 267 | 275 |
| 268 bool WebMediaPlayerImpl::setAutoBuffer(bool autoBuffer) { | 276 bool WebMediaPlayerImpl::setAutoBuffer(bool autoBuffer) { |
| 269 DCHECK(MessageLoop::current() == main_loop_); | 277 DCHECK(MessageLoop::current() == main_loop_); |
| 270 | 278 |
| 271 return false; | 279 return false; |
| 272 } | 280 } |
| 273 | 281 |
| 274 bool WebMediaPlayerImpl::totalBytesKnown() { | 282 bool WebMediaPlayerImpl::totalBytesKnown() { |
| 275 DCHECK(MessageLoop::current() == main_loop_); | 283 DCHECK(MessageLoop::current() == main_loop_); |
| 276 | 284 |
| 277 return pipeline_.GetTotalBytes() != 0; | 285 return pipeline_->GetTotalBytes() != 0; |
| 278 } | 286 } |
| 279 | 287 |
| 280 bool WebMediaPlayerImpl::hasVideo() const { | 288 bool WebMediaPlayerImpl::hasVideo() const { |
| 281 DCHECK(MessageLoop::current() == main_loop_); | 289 DCHECK(MessageLoop::current() == main_loop_); |
| 282 | 290 |
| 283 size_t width, height; | 291 size_t width, height; |
| 284 pipeline_.GetVideoSize(&width, &height); | 292 pipeline_->GetVideoSize(&width, &height); |
| 285 return width != 0 && height != 0; | 293 return width != 0 && height != 0; |
| 286 } | 294 } |
| 287 | 295 |
| 288 WebKit::WebSize WebMediaPlayerImpl::naturalSize() const { | 296 WebKit::WebSize WebMediaPlayerImpl::naturalSize() const { |
| 289 DCHECK(MessageLoop::current() == main_loop_); | 297 DCHECK(MessageLoop::current() == main_loop_); |
| 290 | 298 |
| 291 size_t width, height; | 299 size_t width, height; |
| 292 pipeline_.GetVideoSize(&width, &height); | 300 pipeline_->GetVideoSize(&width, &height); |
| 293 return WebKit::WebSize(width, height); | 301 return WebKit::WebSize(width, height); |
| 294 } | 302 } |
| 295 | 303 |
| 296 bool WebMediaPlayerImpl::paused() const { | 304 bool WebMediaPlayerImpl::paused() const { |
| 297 DCHECK(MessageLoop::current() == main_loop_); | 305 DCHECK(MessageLoop::current() == main_loop_); |
| 298 | 306 |
| 299 return pipeline_.GetPlaybackRate() == 0.0f; | 307 return pipeline_->GetPlaybackRate() == 0.0f; |
| 300 } | 308 } |
| 301 | 309 |
| 302 bool WebMediaPlayerImpl::seeking() const { | 310 bool WebMediaPlayerImpl::seeking() const { |
| 303 DCHECK(MessageLoop::current() == main_loop_); | 311 DCHECK(MessageLoop::current() == main_loop_); |
| 304 | 312 |
| 305 return false; | 313 return false; |
| 306 } | 314 } |
| 307 | 315 |
| 308 float WebMediaPlayerImpl::duration() const { | 316 float WebMediaPlayerImpl::duration() const { |
| 309 DCHECK(MessageLoop::current() == main_loop_); | 317 DCHECK(MessageLoop::current() == main_loop_); |
| 310 | 318 |
| 311 return static_cast<float>(pipeline_.GetDuration().InSecondsF()); | 319 return static_cast<float>(pipeline_->GetDuration().InSecondsF()); |
| 312 } | 320 } |
| 313 | 321 |
| 314 float WebMediaPlayerImpl::currentTime() const { | 322 float WebMediaPlayerImpl::currentTime() const { |
| 315 DCHECK(MessageLoop::current() == main_loop_); | 323 DCHECK(MessageLoop::current() == main_loop_); |
| 316 | 324 |
| 317 return static_cast<float>(pipeline_.GetTime().InSecondsF()); | 325 return static_cast<float>(pipeline_->GetTime().InSecondsF()); |
| 318 } | 326 } |
| 319 | 327 |
| 320 int WebMediaPlayerImpl::dataRate() const { | 328 int WebMediaPlayerImpl::dataRate() const { |
| 321 DCHECK(MessageLoop::current() == main_loop_); | 329 DCHECK(MessageLoop::current() == main_loop_); |
| 322 | 330 |
| 323 // TODO(hclam): Add this method call if pipeline has it in the interface. | 331 // TODO(hclam): Add this method call if pipeline has it in the interface. |
| 324 return 0; | 332 return 0; |
| 325 } | 333 } |
| 326 | 334 |
| 327 float WebMediaPlayerImpl::maxTimeBuffered() const { | 335 float WebMediaPlayerImpl::maxTimeBuffered() const { |
| 328 DCHECK(MessageLoop::current() == main_loop_); | 336 DCHECK(MessageLoop::current() == main_loop_); |
| 329 | 337 |
| 330 return static_cast<float>(pipeline_.GetBufferedTime().InSecondsF()); | 338 return static_cast<float>(pipeline_->GetBufferedTime().InSecondsF()); |
| 331 } | 339 } |
| 332 | 340 |
| 333 float WebMediaPlayerImpl::maxTimeSeekable() const { | 341 float WebMediaPlayerImpl::maxTimeSeekable() const { |
| 334 DCHECK(MessageLoop::current() == main_loop_); | 342 DCHECK(MessageLoop::current() == main_loop_); |
| 335 | 343 |
| 336 // TODO(scherkus): move this logic down into the pipeline. | 344 // TODO(scherkus): move this logic down into the pipeline. |
| 337 if (pipeline_.GetTotalBytes() == 0) { | 345 if (pipeline_->GetTotalBytes() == 0) { |
| 338 return 0.0f; | 346 return 0.0f; |
| 339 } | 347 } |
| 340 double total_bytes = static_cast<double>(pipeline_.GetTotalBytes()); | 348 double total_bytes = static_cast<double>(pipeline_->GetTotalBytes()); |
| 341 double buffered_bytes = static_cast<double>(pipeline_.GetBufferedBytes()); | 349 double buffered_bytes = static_cast<double>(pipeline_->GetBufferedBytes()); |
| 342 double duration = static_cast<double>(pipeline_.GetDuration().InSecondsF()); | 350 double duration = static_cast<double>(pipeline_->GetDuration().InSecondsF()); |
| 343 return static_cast<float>(duration * (buffered_bytes / total_bytes)); | 351 return static_cast<float>(duration * (buffered_bytes / total_bytes)); |
| 344 } | 352 } |
| 345 | 353 |
| 346 unsigned long long WebMediaPlayerImpl::bytesLoaded() const { | 354 unsigned long long WebMediaPlayerImpl::bytesLoaded() const { |
| 347 DCHECK(MessageLoop::current() == main_loop_); | 355 DCHECK(MessageLoop::current() == main_loop_); |
| 348 | 356 |
| 349 return pipeline_.GetBufferedBytes(); | 357 return pipeline_->GetBufferedBytes(); |
| 350 } | 358 } |
| 351 | 359 |
| 352 unsigned long long WebMediaPlayerImpl::totalBytes() const { | 360 unsigned long long WebMediaPlayerImpl::totalBytes() const { |
| 353 DCHECK(MessageLoop::current() == main_loop_); | 361 DCHECK(MessageLoop::current() == main_loop_); |
| 354 | 362 |
| 355 return pipeline_.GetTotalBytes(); | 363 return pipeline_->GetTotalBytes(); |
| 356 } | 364 } |
| 357 | 365 |
| 358 void WebMediaPlayerImpl::setSize(const WebSize& size) { | 366 void WebMediaPlayerImpl::setSize(const WebSize& size) { |
| 359 DCHECK(MessageLoop::current() == main_loop_); | 367 DCHECK(MessageLoop::current() == main_loop_); |
| 360 DCHECK(proxy_); | 368 DCHECK(proxy_); |
| 361 | 369 |
| 362 proxy_->SetSize(gfx::Rect(0, 0, size.width, size.height)); | 370 proxy_->SetSize(gfx::Rect(0, 0, size.width, size.height)); |
| 363 } | 371 } |
| 364 | 372 |
| 365 void WebMediaPlayerImpl::paint(WebCanvas* canvas, | 373 void WebMediaPlayerImpl::paint(WebCanvas* canvas, |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 400 if (ready_state_ != state) { | 408 if (ready_state_ != state) { |
| 401 ready_state_ = state; | 409 ready_state_ = state; |
| 402 GetClient()->readyStateChanged(); | 410 GetClient()->readyStateChanged(); |
| 403 } | 411 } |
| 404 } | 412 } |
| 405 | 413 |
| 406 void WebMediaPlayerImpl::Destroy() { | 414 void WebMediaPlayerImpl::Destroy() { |
| 407 DCHECK(MessageLoop::current() == main_loop_); | 415 DCHECK(MessageLoop::current() == main_loop_); |
| 408 | 416 |
| 409 // Make sure to kill the pipeline so there's no more media threads running. | 417 // Make sure to kill the pipeline so there's no more media threads running. |
| 410 // TODO(hclam): stopping the pipeline is synchronous so it might block | 418 // TODO(hclam): stopping the pipeline might block for a long time. |
| 411 // stopping for a long time. | 419 pipeline_->Stop(NULL); |
| 412 pipeline_.Stop(); | 420 pipeline_thread_.Stop(); |
| 413 | 421 |
| 414 // And then detach the proxy, it may live on the render thread for a little | 422 // And then detach the proxy, it may live on the render thread for a little |
| 415 // longer until all the tasks are finished. | 423 // longer until all the tasks are finished. |
| 416 if (proxy_) { | 424 if (proxy_) { |
| 417 proxy_->Detach(); | 425 proxy_->Detach(); |
| 418 proxy_ = NULL; | 426 proxy_ = NULL; |
| 419 } | 427 } |
| 420 } | 428 } |
| 421 | 429 |
| 422 WebKit::WebMediaPlayerClient* WebMediaPlayerImpl::GetClient() { | 430 WebKit::WebMediaPlayerClient* WebMediaPlayerImpl::GetClient() { |
| 423 DCHECK(MessageLoop::current() == main_loop_); | 431 DCHECK(MessageLoop::current() == main_loop_); |
| 424 DCHECK(client_); | 432 DCHECK(client_); |
| 425 return client_; | 433 return client_; |
| 426 } | 434 } |
| 427 | 435 |
| 428 } // namespace webkit_glue | 436 } // namespace webkit_glue |
| OLD | NEW |