Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(554)

Side by Side Diff: webkit/glue/webmediaplayer_impl.cc

Issue 5878007: Fix black video frames when seeking (which also fixes flashing poster issue). (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« webkit/glue/media/video_renderer_impl.cc ('K') | « webkit/glue/webmediaplayer_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698