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

Side by Side Diff: media/filters/video_renderer_base.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: Cache the last available video frame in VideoRendererBase instead of copying a bitmap. 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
« no previous file with comments | « media/filters/video_renderer_base.h ('k') | webkit/glue/webmediaplayer_impl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "base/callback.h" 5 #include "base/callback.h"
6 #include "media/base/buffers.h" 6 #include "media/base/buffers.h"
7 #include "media/base/callback.h" 7 #include "media/base/callback.h"
8 #include "media/base/filter_host.h" 8 #include "media/base/filter_host.h"
9 #include "media/base/limits.h" 9 #include "media/base/limits.h"
10 #include "media/base/video_frame.h" 10 #include "media/base/video_frame.h"
(...skipping 15 matching lines...) Expand all
26 static const int kIdleMilliseconds = 10; 26 static const int kIdleMilliseconds = 10;
27 27
28 VideoRendererBase::VideoRendererBase() 28 VideoRendererBase::VideoRendererBase()
29 : width_(0), 29 : width_(0),
30 height_(0), 30 height_(0),
31 frame_available_(&lock_), 31 frame_available_(&lock_),
32 state_(kUninitialized), 32 state_(kUninitialized),
33 thread_(kNullThreadHandle), 33 thread_(kNullThreadHandle),
34 pending_reads_(0), 34 pending_reads_(0),
35 pending_paint_(false), 35 pending_paint_(false),
36 pending_paint_with_last_available_(false),
36 playback_rate_(0) { 37 playback_rate_(0) {
37 } 38 }
38 39
39 VideoRendererBase::~VideoRendererBase() { 40 VideoRendererBase::~VideoRendererBase() {
40 AutoLock auto_lock(lock_); 41 AutoLock auto_lock(lock_);
41 DCHECK(state_ == kUninitialized || state_ == kStopped); 42 DCHECK(state_ == kUninitialized || state_ == kStopped);
42 } 43 }
43 44
44 // static 45 // static
45 bool VideoRendererBase::ParseMediaFormat( 46 bool VideoRendererBase::ParseMediaFormat(
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 state_ = kPaused; 91 state_ = kPaused;
91 } 92 }
92 93
93 void VideoRendererBase::Flush(FilterCallback* callback) { 94 void VideoRendererBase::Flush(FilterCallback* callback) {
94 DCHECK_EQ(state_, kPaused); 95 DCHECK_EQ(state_, kPaused);
95 96
96 AutoLock auto_lock(lock_); 97 AutoLock auto_lock(lock_);
97 flush_callback_.reset(callback); 98 flush_callback_.reset(callback);
98 state_ = kFlushing; 99 state_ = kFlushing;
99 100
100 if (pending_paint_ == false) 101 if (pending_paint_ == false)
scherkus (not reviewing) 2010/12/20 22:49:55 ditto?
sjl 2010/12/21 22:13:40 Do you mean '&& pending_paint_with_last_available_
101 FlushBuffers(); 102 FlushBuffers();
102 } 103 }
103 104
104 void VideoRendererBase::Stop(FilterCallback* callback) { 105 void VideoRendererBase::Stop(FilterCallback* callback) {
105 DCHECK_EQ(pending_reads_, 0); 106 DCHECK_EQ(pending_reads_, 0);
106 107
107 { 108 {
108 AutoLock auto_lock(lock_); 109 AutoLock auto_lock(lock_);
109 state_ = kStopped; 110 state_ = kStopped;
110 111
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 AutoUnlock auto_unlock(lock_); 319 AutoUnlock auto_unlock(lock_);
319 // Notify subclass that |current_frame_| has been updated. 320 // Notify subclass that |current_frame_| has been updated.
320 OnFrameAvailable(); 321 OnFrameAvailable();
321 } 322 }
322 } 323 }
323 } 324 }
324 } 325 }
325 326
326 void VideoRendererBase::GetCurrentFrame(scoped_refptr<VideoFrame>* frame_out) { 327 void VideoRendererBase::GetCurrentFrame(scoped_refptr<VideoFrame>* frame_out) {
327 AutoLock auto_lock(lock_); 328 AutoLock auto_lock(lock_);
328 DCHECK(!pending_paint_); 329 DCHECK(!pending_paint_ && !pending_paint_with_last_available_);
329 330
330 if (!current_frame_.get() || current_frame_->IsEndOfStream()) { 331 if (!current_frame_.get() || current_frame_->IsEndOfStream()) {
331 *frame_out = NULL; 332 if (!last_available_frame_.get() ||
332 return; 333 last_available_frame_->IsEndOfStream()) {
334 *frame_out = NULL;
335 return;
336 }
333 } 337 }
334 338
335 // We should have initialized and have the current frame. 339 // We should have initialized and have the current frame.
336 DCHECK(state_ != kUninitialized && state_ != kStopped && state_ != kError); 340 DCHECK(state_ != kUninitialized && state_ != kStopped && state_ != kError);
337 *frame_out = current_frame_; 341
338 pending_paint_ = true; 342 if (current_frame_) {
343 *frame_out = current_frame_;
344 last_available_frame_ = current_frame_;
345 pending_paint_ = true;
346 } else {
347 DCHECK(last_available_frame_.get() != NULL);
348 *frame_out = last_available_frame_;
349 pending_paint_with_last_available_ = true;
350 }
339 } 351 }
340 352
341 void VideoRendererBase::PutCurrentFrame(scoped_refptr<VideoFrame> frame) { 353 void VideoRendererBase::PutCurrentFrame(scoped_refptr<VideoFrame> frame) {
342 AutoLock auto_lock(lock_); 354 AutoLock auto_lock(lock_);
343 355
344 // Note that we do not claim |pending_paint_| when we return NULL frame, in 356 // Note that we do not claim |pending_paint_| when we return NULL frame, in
345 // that case, |current_frame_| could be changed before PutCurrentFrame. 357 // that case, |current_frame_| could be changed before PutCurrentFrame.
346 DCHECK(pending_paint_ || frame.get() == NULL); 358 if (pending_paint_) {
347 DCHECK(current_frame_.get() == frame.get() || frame.get() == NULL); 359 DCHECK(current_frame_.get() == frame.get());
360 DCHECK(pending_paint_with_last_available_ == false);
361 pending_paint_ = false;
362 } else if (pending_paint_with_last_available_) {
363 DCHECK(last_available_frame_.get() == frame.get());
364 pending_paint_with_last_available_ = false;
365 } else {
366 DCHECK(frame.get() == NULL);
367 }
348 368
349 pending_paint_ = false;
350 // We had cleared the |pending_paint_| flag, there are chances that current 369 // We had cleared the |pending_paint_| flag, there are chances that current
351 // frame is timed-out. We will wake up our main thread to advance the current 370 // frame is timed-out. We will wake up our main thread to advance the current
352 // frame when this is true. 371 // frame when this is true.
353 frame_available_.Signal(); 372 frame_available_.Signal();
354 if (state_ == kFlushing) 373 if (state_ == kFlushing)
355 FlushBuffers(); 374 FlushBuffers();
356 } 375 }
357 376
358 void VideoRendererBase::ConsumeVideoFrame(scoped_refptr<VideoFrame> frame) { 377 void VideoRendererBase::ConsumeVideoFrame(scoped_refptr<VideoFrame> frame) {
359 AutoLock auto_lock(lock_); 378 AutoLock auto_lock(lock_);
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
449 // provide buffer pools. In the future, we may want to implement real 468 // provide buffer pools. In the future, we may want to implement real
450 // buffer pool to recycle buffers. 469 // buffer pool to recycle buffers.
451 while (!frames_queue_done_.empty()) { 470 while (!frames_queue_done_.empty()) {
452 scoped_refptr<VideoFrame> video_frame = frames_queue_done_.front(); 471 scoped_refptr<VideoFrame> video_frame = frames_queue_done_.front();
453 frames_queue_done_.pop_front(); 472 frames_queue_done_.pop_front();
454 ReadInput(video_frame); 473 ReadInput(video_frame);
455 } 474 }
456 } 475 }
457 476
458 void VideoRendererBase::FlushBuffers() { 477 void VideoRendererBase::FlushBuffers() {
459 DCHECK(!pending_paint_); 478 DCHECK(!pending_paint_);
scherkus (not reviewing) 2010/12/20 22:49:55 add a DCHECK for pending_paint_with_last_available
sjl 2010/12/21 22:13:40 As above, it's ok if we have a pending paint on la
460 479
461 // We should never put EOF frame into "done queue". 480 // We should never put EOF frame into "done queue".
462 while (!frames_queue_ready_.empty()) { 481 while (!frames_queue_ready_.empty()) {
463 scoped_refptr<VideoFrame> video_frame = frames_queue_ready_.front(); 482 scoped_refptr<VideoFrame> video_frame = frames_queue_ready_.front();
464 if (!video_frame->IsEndOfStream()) { 483 if (!video_frame->IsEndOfStream()) {
465 frames_queue_done_.push_back(video_frame); 484 frames_queue_done_.push_back(video_frame);
466 } 485 }
467 frames_queue_ready_.pop_front(); 486 frames_queue_ready_.pop_front();
468 } 487 }
469 if (current_frame_.get() && !current_frame_->IsEndOfStream()) { 488 if (current_frame_.get() && !current_frame_->IsEndOfStream()) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
521 previous_time_ = now; 540 previous_time_ = now;
522 } 541 }
523 542
524 // Scale our sleep based on the playback rate. 543 // Scale our sleep based on the playback rate.
525 // TODO(scherkus): floating point badness and degrade gracefully. 544 // TODO(scherkus): floating point badness and degrade gracefully.
526 return base::TimeDelta::FromMicroseconds( 545 return base::TimeDelta::FromMicroseconds(
527 static_cast<int64>(sleep.InMicroseconds() / playback_rate)); 546 static_cast<int64>(sleep.InMicroseconds() / playback_rate));
528 } 547 }
529 548
530 } // namespace media 549 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/video_renderer_base.h ('k') | webkit/glue/webmediaplayer_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698