Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 | 8 |
| 9 #include "base/callback.h" | 9 #include "base/callback.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 201 } | 201 } |
| 202 } | 202 } |
| 203 | 203 |
| 204 void WebMediaPlayerImpl::Proxy::NetworkEventTask() { | 204 void WebMediaPlayerImpl::Proxy::NetworkEventTask() { |
| 205 DCHECK(MessageLoop::current() == render_loop_); | 205 DCHECK(MessageLoop::current() == render_loop_); |
| 206 if (webmediaplayer_) { | 206 if (webmediaplayer_) { |
| 207 webmediaplayer_->OnNetworkEvent(); | 207 webmediaplayer_->OnNetworkEvent(); |
| 208 } | 208 } |
| 209 } | 209 } |
| 210 | 210 |
| 211 void WebMediaPlayerImpl::Proxy::CopyBitmapToCanvas(const SkBitmap& bitmap, | |
| 212 skia::PlatformCanvas* canvas, | |
| 213 const gfx::Rect& dest_rect) { | |
| 214 DCHECK(MessageLoop::current() == render_loop_); | |
| 215 if (video_renderer_) | |
| 216 video_renderer_->CopyBitmapToCanvas(bitmap, canvas, dest_rect); | |
| 217 } | |
| 218 | |
| 219 void WebMediaPlayerImpl::Proxy::GetCurrentBitmap(SkBitmap* bitmap) { | |
| 220 DCHECK(MessageLoop::current() == render_loop_); | |
| 221 if (video_renderer_) | |
| 222 video_renderer_->GetCurrentBitmap(bitmap); | |
| 223 } | |
| 224 | |
| 211 void WebMediaPlayerImpl::Proxy::GetCurrentFrame( | 225 void WebMediaPlayerImpl::Proxy::GetCurrentFrame( |
| 212 scoped_refptr<media::VideoFrame>* frame_out) { | 226 scoped_refptr<media::VideoFrame>* frame_out) { |
| 213 if (video_renderer_) | 227 if (video_renderer_) |
| 214 video_renderer_->GetCurrentFrame(frame_out); | 228 video_renderer_->GetCurrentFrame(frame_out); |
| 215 } | 229 } |
| 216 | 230 |
| 217 void WebMediaPlayerImpl::Proxy::PutCurrentFrame( | 231 void WebMediaPlayerImpl::Proxy::PutCurrentFrame( |
| 218 scoped_refptr<media::VideoFrame> frame) { | 232 scoped_refptr<media::VideoFrame> frame) { |
| 219 if (video_renderer_) | 233 if (video_renderer_) |
| 220 video_renderer_->PutCurrentFrame(frame); | 234 video_renderer_->PutCurrentFrame(frame); |
| 221 } | 235 } |
| 222 | 236 |
| 223 ///////////////////////////////////////////////////////////////////////////// | 237 ///////////////////////////////////////////////////////////////////////////// |
| 224 // WebMediaPlayerImpl implementation | 238 // WebMediaPlayerImpl implementation |
| 225 | 239 |
| 226 WebMediaPlayerImpl::WebMediaPlayerImpl( | 240 WebMediaPlayerImpl::WebMediaPlayerImpl( |
| 227 WebKit::WebMediaPlayerClient* client, | 241 WebKit::WebMediaPlayerClient* client, |
| 228 media::FilterCollection* collection) | 242 media::FilterCollection* collection) |
| 229 : network_state_(WebKit::WebMediaPlayer::Empty), | 243 : network_state_(WebKit::WebMediaPlayer::Empty), |
| 230 ready_state_(WebKit::WebMediaPlayer::HaveNothing), | 244 ready_state_(WebKit::WebMediaPlayer::HaveNothing), |
| 231 main_loop_(NULL), | 245 main_loop_(NULL), |
| 232 filter_collection_(collection), | 246 filter_collection_(collection), |
| 233 pipeline_(NULL), | 247 pipeline_(NULL), |
| 234 pipeline_thread_("PipelineThread"), | 248 pipeline_thread_("PipelineThread"), |
| 235 paused_(true), | 249 paused_(true), |
| 250 seeking_(false), | |
| 236 playback_rate_(0.0f), | 251 playback_rate_(0.0f), |
| 237 client_(client), | 252 client_(client), |
| 238 proxy_(NULL), | 253 proxy_(NULL), |
| 239 pipeline_stopped_(false, false) { | 254 pipeline_stopped_(false, false) { |
| 240 // Saves the current message loop. | 255 // Saves the current message loop. |
| 241 DCHECK(!main_loop_); | 256 DCHECK(!main_loop_); |
| 242 main_loop_ = MessageLoop::current(); | 257 main_loop_ = MessageLoop::current(); |
| 243 } | 258 } |
| 244 | 259 |
| 245 bool WebMediaPlayerImpl::Initialize( | 260 bool WebMediaPlayerImpl::Initialize( |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 361 // cause extra pre-rolling and will break servers without range request | 376 // cause extra pre-rolling and will break servers without range request |
| 362 // support. | 377 // support. |
| 363 // | 378 // |
| 364 // We still have to notify WebKit that time has changed otherwise | 379 // We still have to notify WebKit that time has changed otherwise |
| 365 // HTMLMediaElement gets into an inconsistent state. | 380 // HTMLMediaElement gets into an inconsistent state. |
| 366 if (pipeline_->GetCurrentTime().ToInternalValue() == 0 && seconds == 0) { | 381 if (pipeline_->GetCurrentTime().ToInternalValue() == 0 && seconds == 0) { |
| 367 GetClient()->timeChanged(); | 382 GetClient()->timeChanged(); |
| 368 return; | 383 return; |
| 369 } | 384 } |
| 370 | 385 |
| 371 // Drop our ready state if the media file isn't fully loaded. | |
| 372 if (!pipeline_->IsLoaded()) { | |
| 373 SetReadyState(WebKit::WebMediaPlayer::HaveMetadata); | |
| 374 } | |
| 375 | |
| 376 // Try to preserve as much accuracy as possible. | 386 // Try to preserve as much accuracy as possible. |
| 377 float microseconds = seconds * base::Time::kMicrosecondsPerSecond; | 387 float microseconds = seconds * base::Time::kMicrosecondsPerSecond; |
| 378 base::TimeDelta seek_time = | 388 base::TimeDelta seek_time = |
| 379 base::TimeDelta::FromMicroseconds(static_cast<int64>(microseconds)); | 389 base::TimeDelta::FromMicroseconds(static_cast<int64>(microseconds)); |
| 380 | 390 |
| 381 // Update our paused time. | 391 // Update our paused time. |
| 382 if (paused_) { | 392 if (paused_) { |
| 383 paused_time_ = seek_time; | 393 paused_time_ = seek_time; |
| 384 } | 394 } |
| 385 | 395 |
| 396 seeking_ = true; | |
| 397 | |
| 398 // If available, take a copy of the current video frame to display while | |
| 399 // seeking. | |
| 400 proxy_->GetCurrentBitmap(&cached_bitmap_); | |
| 401 | |
| 386 // Kick off the asynchronous seek! | 402 // Kick off the asynchronous seek! |
| 387 pipeline_->Seek( | 403 pipeline_->Seek( |
| 388 seek_time, | 404 seek_time, |
| 389 NewCallback(proxy_.get(), | 405 NewCallback(proxy_.get(), |
| 390 &WebMediaPlayerImpl::Proxy::PipelineSeekCallback)); | 406 &WebMediaPlayerImpl::Proxy::PipelineSeekCallback)); |
| 391 } | 407 } |
| 392 | 408 |
| 393 void WebMediaPlayerImpl::setEndTime(float seconds) { | 409 void WebMediaPlayerImpl::setEndTime(float seconds) { |
| 394 DCHECK(MessageLoop::current() == main_loop_); | 410 DCHECK(MessageLoop::current() == main_loop_); |
| 395 | 411 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 469 | 485 |
| 470 return pipeline_->GetPlaybackRate() == 0.0f; | 486 return pipeline_->GetPlaybackRate() == 0.0f; |
| 471 } | 487 } |
| 472 | 488 |
| 473 bool WebMediaPlayerImpl::seeking() const { | 489 bool WebMediaPlayerImpl::seeking() const { |
| 474 DCHECK(MessageLoop::current() == main_loop_); | 490 DCHECK(MessageLoop::current() == main_loop_); |
| 475 | 491 |
| 476 if (ready_state_ == WebKit::WebMediaPlayer::HaveNothing) | 492 if (ready_state_ == WebKit::WebMediaPlayer::HaveNothing) |
| 477 return false; | 493 return false; |
| 478 | 494 |
| 479 return ready_state_ == WebKit::WebMediaPlayer::HaveMetadata; | 495 return seeking_; |
| 480 } | 496 } |
| 481 | 497 |
| 482 float WebMediaPlayerImpl::duration() const { | 498 float WebMediaPlayerImpl::duration() const { |
| 483 DCHECK(MessageLoop::current() == main_loop_); | 499 DCHECK(MessageLoop::current() == main_loop_); |
| 484 | 500 |
| 485 base::TimeDelta duration = pipeline_->GetMediaDuration(); | 501 base::TimeDelta duration = pipeline_->GetMediaDuration(); |
| 486 if (duration.InMicroseconds() == media::Limits::kMaxTimeInMicroseconds) | 502 if (duration.InMicroseconds() == media::Limits::kMaxTimeInMicroseconds) |
| 487 return std::numeric_limits<float>::infinity(); | 503 return std::numeric_limits<float>::infinity(); |
| 488 return static_cast<float>(duration.InSecondsF()); | 504 return static_cast<float>(duration.InSecondsF()); |
| 489 } | 505 } |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 556 | 572 |
| 557 proxy_->SetSize(gfx::Rect(0, 0, size.width, size.height)); | 573 proxy_->SetSize(gfx::Rect(0, 0, size.width, size.height)); |
| 558 } | 574 } |
| 559 | 575 |
| 560 void WebMediaPlayerImpl::paint(WebCanvas* canvas, | 576 void WebMediaPlayerImpl::paint(WebCanvas* canvas, |
| 561 const WebRect& rect) { | 577 const WebRect& rect) { |
| 562 DCHECK(MessageLoop::current() == main_loop_); | 578 DCHECK(MessageLoop::current() == main_loop_); |
| 563 DCHECK(proxy_); | 579 DCHECK(proxy_); |
| 564 | 580 |
| 565 #if WEBKIT_USING_SKIA | 581 #if WEBKIT_USING_SKIA |
| 566 proxy_->Paint(canvas, rect); | 582 if (seeking_ && !cached_bitmap_.empty()) { |
| 583 proxy_->CopyBitmapToCanvas(cached_bitmap_, canvas, rect); | |
| 584 } else { | |
| 585 proxy_->Paint(canvas, rect); | |
| 586 } | |
| 567 #elif WEBKIT_USING_CG | 587 #elif WEBKIT_USING_CG |
| 568 // Get the current scaling in X and Y. | 588 // Get the current scaling in X and Y. |
| 569 CGAffineTransform mat = CGContextGetCTM(canvas); | 589 CGAffineTransform mat = CGContextGetCTM(canvas); |
| 570 float scale_x = sqrt(mat.a * mat.a + mat.b * mat.b); | 590 float scale_x = sqrt(mat.a * mat.a + mat.b * mat.b); |
| 571 float scale_y = sqrt(mat.c * mat.c + mat.d * mat.d); | 591 float scale_y = sqrt(mat.c * mat.c + mat.d * mat.d); |
| 572 float inverse_scale_x = SkScalarNearlyZero(scale_x) ? 0.0f : 1.0f / scale_x; | 592 float inverse_scale_x = SkScalarNearlyZero(scale_x) ? 0.0f : 1.0f / scale_x; |
| 573 float inverse_scale_y = SkScalarNearlyZero(scale_y) ? 0.0f : 1.0f / scale_y; | 593 float inverse_scale_y = SkScalarNearlyZero(scale_y) ? 0.0f : 1.0f / scale_y; |
| 574 int scaled_width = static_cast<int>(rect.width * fabs(scale_x)); | 594 int scaled_width = static_cast<int>(rect.width * fabs(scale_x)); |
| 575 int scaled_height = static_cast<int>(rect.height * fabs(scale_y)); | 595 int scaled_height = static_cast<int>(rect.height * fabs(scale_y)); |
| 576 | 596 |
| 577 // Make sure we don't create a huge canvas. | 597 // Make sure we don't create a huge canvas. |
| 578 // TODO(hclam): Respect the aspect ratio. | 598 // TODO(hclam): Respect the aspect ratio. |
| 579 if (scaled_width > static_cast<int>(media::Limits::kMaxCanvas)) | 599 if (scaled_width > static_cast<int>(media::Limits::kMaxCanvas)) |
| 580 scaled_width = media::Limits::kMaxCanvas; | 600 scaled_width = media::Limits::kMaxCanvas; |
| 581 if (scaled_height > static_cast<int>(media::Limits::kMaxCanvas)) | 601 if (scaled_height > static_cast<int>(media::Limits::kMaxCanvas)) |
| 582 scaled_height = media::Limits::kMaxCanvas; | 602 scaled_height = media::Limits::kMaxCanvas; |
| 583 | 603 |
| 584 // If there is no preexisting platform canvas, or if the size has | 604 // If there is no preexisting platform canvas, or if the size has |
| 585 // changed, recreate the canvas. This is to avoid recreating the bitmap | 605 // changed, recreate the canvas. This is to avoid recreating the bitmap |
| 586 // buffer over and over for each frame of video. | 606 // buffer over and over for each frame of video. |
| 587 if (!skia_canvas_.get() || | 607 if (!skia_canvas_.get() || |
| 588 skia_canvas_->getDevice()->width() != scaled_width || | 608 skia_canvas_->getDevice()->width() != scaled_width || |
| 589 skia_canvas_->getDevice()->height() != scaled_height) { | 609 skia_canvas_->getDevice()->height() != scaled_height) { |
| 590 skia_canvas_.reset( | 610 skia_canvas_.reset( |
| 591 new skia::PlatformCanvas(scaled_width, scaled_height, true)); | 611 new skia::PlatformCanvas(scaled_width, scaled_height, true)); |
| 592 } | 612 } |
| 593 | 613 |
| 594 // Draw to our temporary skia canvas. | 614 // Draw to our temporary skia canvas. |
| 595 gfx::Rect normalized_rect(scaled_width, scaled_height); | 615 gfx::Rect normalized_rect(scaled_width, scaled_height); |
| 596 proxy_->Paint(skia_canvas_.get(), normalized_rect); | 616 if (seeking_ && !cached_bitmap_.empty()) { |
| 617 proxy_->CopyBitmapToCanvas( | |
| 618 cached_bitmap_, skia_canvas_.get(), normalized_rect); | |
| 619 } else { | |
| 620 proxy_->Paint(skia_canvas_.get(), normalized_rect); | |
| 621 } | |
| 597 | 622 |
| 598 // The mac coordinate system is flipped vertical from the normal skia | 623 // The mac coordinate system is flipped vertical from the normal skia |
| 599 // coordinates. During painting of the frame, flip the coordinates | 624 // coordinates. During painting of the frame, flip the coordinates |
| 600 // system and, for simplicity, also translate the clip rectangle to | 625 // system and, for simplicity, also translate the clip rectangle to |
| 601 // start at 0,0. | 626 // start at 0,0. |
| 602 CGContextSaveGState(canvas); | 627 CGContextSaveGState(canvas); |
| 603 CGContextTranslateCTM(canvas, rect.x, rect.height + rect.y); | 628 CGContextTranslateCTM(canvas, rect.x, rect.height + rect.y); |
| 604 CGContextScaleCTM(canvas, inverse_scale_x, -inverse_scale_y); | 629 CGContextScaleCTM(canvas, inverse_scale_x, -inverse_scale_y); |
| 605 | 630 |
| 606 // We need a local variable CGRect version for DrawToContext. | 631 // We need a local variable CGRect version for DrawToContext. |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 630 DCHECK(MessageLoop::current() == main_loop_); | 655 DCHECK(MessageLoop::current() == main_loop_); |
| 631 | 656 |
| 632 // TODO(hclam): If the pipeline is performing streaming, we say that this is | 657 // TODO(hclam): If the pipeline is performing streaming, we say that this is |
| 633 // a live stream. But instead it should be a StoredStream if we have proper | 658 // a live stream. But instead it should be a StoredStream if we have proper |
| 634 // caching. | 659 // caching. |
| 635 if (pipeline_->IsStreaming()) | 660 if (pipeline_->IsStreaming()) |
| 636 return WebKit::WebMediaPlayer::LiveStream; | 661 return WebKit::WebMediaPlayer::LiveStream; |
| 637 return WebKit::WebMediaPlayer::Unknown; | 662 return WebKit::WebMediaPlayer::Unknown; |
| 638 } | 663 } |
| 639 | 664 |
| 640 WebKit::WebVideoFrame* WebMediaPlayerImpl::getCurrentFrame() { | 665 WebKit::WebVideoFrame* WebMediaPlayerImpl::getCurrentFrame() { |
|
scherkus (not reviewing)
2010/12/17 18:50:40
watch out for these two methods.. they're using th
| |
| 641 scoped_refptr<media::VideoFrame> video_frame; | 666 scoped_refptr<media::VideoFrame> video_frame; |
| 642 proxy_->GetCurrentFrame(&video_frame); | 667 proxy_->GetCurrentFrame(&video_frame); |
| 643 if (video_frame.get()) | 668 if (video_frame.get()) |
| 644 return new WebVideoFrameImpl(video_frame); | 669 return new WebVideoFrameImpl(video_frame); |
| 645 return NULL; | 670 return NULL; |
| 646 } | 671 } |
| 647 | 672 |
| 648 void WebMediaPlayerImpl::putCurrentFrame( | 673 void WebMediaPlayerImpl::putCurrentFrame( |
| 649 WebKit::WebVideoFrame* web_video_frame) { | 674 WebKit::WebVideoFrame* web_video_frame) { |
| 650 if (web_video_frame) { | 675 if (web_video_frame) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 698 | 723 |
| 699 void WebMediaPlayerImpl::OnPipelineSeek() { | 724 void WebMediaPlayerImpl::OnPipelineSeek() { |
| 700 DCHECK(MessageLoop::current() == main_loop_); | 725 DCHECK(MessageLoop::current() == main_loop_); |
| 701 if (pipeline_->GetError() == media::PIPELINE_OK) { | 726 if (pipeline_->GetError() == media::PIPELINE_OK) { |
| 702 // Update our paused time. | 727 // Update our paused time. |
| 703 if (paused_) { | 728 if (paused_) { |
| 704 paused_time_ = pipeline_->GetCurrentTime(); | 729 paused_time_ = pipeline_->GetCurrentTime(); |
| 705 } | 730 } |
| 706 | 731 |
| 707 SetReadyState(WebKit::WebMediaPlayer::HaveEnoughData); | 732 SetReadyState(WebKit::WebMediaPlayer::HaveEnoughData); |
| 733 seeking_ = false; | |
| 708 GetClient()->timeChanged(); | 734 GetClient()->timeChanged(); |
| 709 } | 735 } |
| 710 } | 736 } |
| 711 | 737 |
| 712 void WebMediaPlayerImpl::OnPipelineEnded() { | 738 void WebMediaPlayerImpl::OnPipelineEnded() { |
| 713 DCHECK(MessageLoop::current() == main_loop_); | 739 DCHECK(MessageLoop::current() == main_loop_); |
| 714 if (pipeline_->GetError() == media::PIPELINE_OK) { | 740 if (pipeline_->GetError() == media::PIPELINE_OK) { |
| 715 GetClient()->timeChanged(); | 741 GetClient()->timeChanged(); |
| 716 } | 742 } |
| 717 } | 743 } |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 808 pipeline_stopped_.Signal(); | 834 pipeline_stopped_.Signal(); |
| 809 } | 835 } |
| 810 | 836 |
| 811 WebKit::WebMediaPlayerClient* WebMediaPlayerImpl::GetClient() { | 837 WebKit::WebMediaPlayerClient* WebMediaPlayerImpl::GetClient() { |
| 812 DCHECK(MessageLoop::current() == main_loop_); | 838 DCHECK(MessageLoop::current() == main_loop_); |
| 813 DCHECK(client_); | 839 DCHECK(client_); |
| 814 return client_; | 840 return client_; |
| 815 } | 841 } |
| 816 | 842 |
| 817 } // namespace webkit_glue | 843 } // namespace webkit_glue |
| OLD | NEW |