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

Side by Side Diff: media/filters/video_renderer_base.cc

Issue 10832087: Remove VideoDecoderConfig.frame_rate_xxx() & VideoFrame:Get/SetDuration() (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address more CR comments. Created 8 years, 4 months 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') | media/filters/video_renderer_base_unittest.cc » ('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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "media/filters/video_renderer_base.h" 5 #include "media/filters/video_renderer_base.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/callback.h" 8 #include "base/callback.h"
9 #include "base/callback_helpers.h" 9 #include "base/callback_helpers.h"
10 #include "base/threading/platform_thread.h" 10 #include "base/threading/platform_thread.h"
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 void VideoRendererBase::Preroll(base::TimeDelta time, 97 void VideoRendererBase::Preroll(base::TimeDelta time,
98 const PipelineStatusCB& cb) { 98 const PipelineStatusCB& cb) {
99 base::AutoLock auto_lock(lock_); 99 base::AutoLock auto_lock(lock_);
100 DCHECK_EQ(state_, kFlushed) << "Must flush prior to prerolling."; 100 DCHECK_EQ(state_, kFlushed) << "Must flush prior to prerolling.";
101 DCHECK(!cb.is_null()); 101 DCHECK(!cb.is_null());
102 DCHECK(preroll_cb_.is_null()); 102 DCHECK(preroll_cb_.is_null());
103 103
104 state_ = kPrerolling; 104 state_ = kPrerolling;
105 preroll_cb_ = cb; 105 preroll_cb_ = cb;
106 preroll_timestamp_ = time; 106 preroll_timestamp_ = time;
107 prerolling_delayed_frame_ = NULL;
107 AttemptRead_Locked(); 108 AttemptRead_Locked();
108 } 109 }
109 110
110 void VideoRendererBase::Initialize(const scoped_refptr<VideoDecoder>& decoder, 111 void VideoRendererBase::Initialize(const scoped_refptr<VideoDecoder>& decoder,
111 const PipelineStatusCB& init_cb, 112 const PipelineStatusCB& init_cb,
112 const StatisticsCB& statistics_cb, 113 const StatisticsCB& statistics_cb,
113 const TimeCB& time_cb, 114 const TimeCB& time_cb,
114 const NaturalSizeChangedCB& size_changed_cb, 115 const NaturalSizeChangedCB& size_changed_cb,
115 const base::Closure& ended_cb, 116 const base::Closure& ended_cb,
116 const PipelineStatusCB& error_cb, 117 const PipelineStatusCB& error_cb,
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 // Abort preroll early for a NULL frame because we won't get more frames. 415 // Abort preroll early for a NULL frame because we won't get more frames.
415 // A new preroll will be requested after this one completes so there is no 416 // A new preroll will be requested after this one completes so there is no
416 // point trying to collect more frames. 417 // point trying to collect more frames.
417 state_ = kPrerolled; 418 state_ = kPrerolled;
418 base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK); 419 base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK);
419 return; 420 return;
420 } 421 }
421 422
422 // Discard frames until we reach our desired preroll timestamp. 423 // Discard frames until we reach our desired preroll timestamp.
423 if (state_ == kPrerolling && !frame->IsEndOfStream() && 424 if (state_ == kPrerolling && !frame->IsEndOfStream() &&
424 (frame->GetTimestamp() + frame->GetDuration()) <= preroll_timestamp_) { 425 frame->GetTimestamp() <= preroll_timestamp_) {
426 prerolling_delayed_frame_ = frame;
425 AttemptRead_Locked(); 427 AttemptRead_Locked();
426 return; 428 return;
427 } 429 }
428 430
429 // Adjust the incoming frame if its rendering stop time is past the duration 431 if (prerolling_delayed_frame_) {
430 // of the video itself. This is typically the last frame of the video and 432 DCHECK_EQ(state_, kPrerolling);
431 // occurs if the container specifies a duration that isn't a multiple of the 433 AddReadyFrame(prerolling_delayed_frame_);
432 // frame rate. Another way for this to happen is for the container to state a 434 prerolling_delayed_frame_ = NULL;
433 // smaller duration than the largest packet timestamp.
434 if (!frame->IsEndOfStream()) {
435 base::TimeDelta duration = get_duration_cb_.Run();
436 if (frame->GetTimestamp() > duration)
437 frame->SetTimestamp(duration);
438 if ((frame->GetTimestamp() + frame->GetDuration()) > duration)
439 frame->SetDuration(duration - frame->GetTimestamp());
440 } 435 }
441 436
442 // This one's a keeper! Place it in the ready queue. 437 AddReadyFrame(frame);
443 ready_frames_.push_back(frame);
444 DCHECK_LE(NumFrames_Locked(), limits::kMaxVideoFrames);
445 if (!frame->IsEndOfStream())
446 time_cb_.Run(frame->GetTimestamp() + frame->GetDuration());
447 frame_available_.Signal();
448
449 PipelineStatistics statistics; 438 PipelineStatistics statistics;
450 statistics.video_frames_decoded = 1; 439 statistics.video_frames_decoded = 1;
451 statistics_cb_.Run(statistics); 440 statistics_cb_.Run(statistics);
452 441
453 // Always request more decoded video if we have capacity. This serves two 442 // Always request more decoded video if we have capacity. This serves two
454 // purposes: 443 // purposes:
455 // 1) Prerolling while paused 444 // 1) Prerolling while paused
456 // 2) Keeps decoding going if video rendering thread starts falling behind 445 // 2) Keeps decoding going if video rendering thread starts falling behind
457 if (NumFrames_Locked() < limits::kMaxVideoFrames && !frame->IsEndOfStream()) { 446 if (NumFrames_Locked() < limits::kMaxVideoFrames && !frame->IsEndOfStream()) {
458 AttemptRead_Locked(); 447 AttemptRead_Locked();
(...skipping 16 matching lines...) Expand all
475 464
476 // ...and we're done prerolling! 465 // ...and we're done prerolling!
477 DCHECK(!preroll_cb_.is_null()); 466 DCHECK(!preroll_cb_.is_null());
478 base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK); 467 base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK);
479 468
480 base::AutoUnlock ul(lock_); 469 base::AutoUnlock ul(lock_);
481 paint_cb_.Run(); 470 paint_cb_.Run();
482 } 471 }
483 } 472 }
484 473
474 void VideoRendererBase::AddReadyFrame(const scoped_refptr<VideoFrame>& frame) {
475 // Adjust the incoming frame if its rendering stop time is past the duration
476 // of the video itself. This is typically the last frame of the video and
477 // occurs if the container specifies a duration that isn't a multiple of the
478 // frame rate. Another way for this to happen is for the container to state a
479 // smaller duration than the largest packet timestamp.
480 base::TimeDelta duration = get_duration_cb_.Run();
481 if (frame->GetTimestamp() > duration || frame->IsEndOfStream()) {
482 frame->SetTimestamp(duration);
483 }
484
485 ready_frames_.push_back(frame);
486 DCHECK_LE(NumFrames_Locked(), limits::kMaxVideoFrames);
487 time_cb_.Run(frame->GetTimestamp());
488 frame_available_.Signal();
489 }
490
485 void VideoRendererBase::AttemptRead_Locked() { 491 void VideoRendererBase::AttemptRead_Locked() {
486 lock_.AssertAcquired(); 492 lock_.AssertAcquired();
487 DCHECK_NE(kEnded, state_); 493 DCHECK_NE(kEnded, state_);
488 494
489 if (pending_read_ || 495 if (pending_read_ ||
490 NumFrames_Locked() == limits::kMaxVideoFrames || 496 NumFrames_Locked() == limits::kMaxVideoFrames ||
491 (!ready_frames_.empty() && ready_frames_.back()->IsEndOfStream()) || 497 (!ready_frames_.empty() && ready_frames_.back()->IsEndOfStream()) ||
492 state_ == kFlushingDecoder || 498 state_ == kFlushingDecoder ||
493 state_ == kFlushing) { 499 state_ == kFlushing) {
494 return; 500 return;
495 } 501 }
496 502
497 pending_read_ = true; 503 pending_read_ = true;
498 decoder_->Read(base::Bind(&VideoRendererBase::FrameReady, this)); 504 decoder_->Read(base::Bind(&VideoRendererBase::FrameReady, this));
499 } 505 }
500 506
501 void VideoRendererBase::OnDecoderFlushDone() { 507 void VideoRendererBase::OnDecoderFlushDone() {
502 base::AutoLock auto_lock(lock_); 508 base::AutoLock auto_lock(lock_);
503 DCHECK_EQ(kFlushingDecoder, state_); 509 DCHECK_EQ(kFlushingDecoder, state_);
504 DCHECK(!pending_read_); 510 DCHECK(!pending_read_);
505 511
506 state_ = kFlushing; 512 state_ = kFlushing;
507 AttemptFlush_Locked(); 513 AttemptFlush_Locked();
508 } 514 }
509 515
510 void VideoRendererBase::AttemptFlush_Locked() { 516 void VideoRendererBase::AttemptFlush_Locked() {
511 lock_.AssertAcquired(); 517 lock_.AssertAcquired();
512 DCHECK_EQ(kFlushing, state_); 518 DCHECK_EQ(kFlushing, state_);
513 519
514 // Get rid of any ready frames. 520 prerolling_delayed_frame_ = NULL;
515 ready_frames_.clear(); 521 ready_frames_.clear();
516 522
517 if (!pending_paint_ && !pending_read_) { 523 if (!pending_paint_ && !pending_read_) {
518 state_ = kFlushed; 524 state_ = kFlushed;
519 current_frame_ = NULL; 525 current_frame_ = NULL;
520 base::ResetAndReturn(&flush_cb_).Run(); 526 base::ResetAndReturn(&flush_cb_).Run();
521 } 527 }
522 } 528 }
523 529
524 base::TimeDelta VideoRendererBase::CalculateSleepDuration( 530 base::TimeDelta VideoRendererBase::CalculateSleepDuration(
525 const scoped_refptr<VideoFrame>& next_frame, 531 const scoped_refptr<VideoFrame>& next_frame,
526 float playback_rate) { 532 float playback_rate) {
527 // Determine the current and next presentation timestamps. 533 // Determine the current and next presentation timestamps.
528 base::TimeDelta now = get_time_cb_.Run(); 534 base::TimeDelta now = get_time_cb_.Run();
529 base::TimeDelta this_pts = current_frame_->GetTimestamp(); 535 base::TimeDelta next_pts = next_frame->GetTimestamp();
530 base::TimeDelta next_pts;
531 if (!next_frame->IsEndOfStream()) {
532 next_pts = next_frame->GetTimestamp();
533 } else {
534 next_pts = this_pts + current_frame_->GetDuration();
535 }
536 536
537 // Scale our sleep based on the playback rate. 537 // Scale our sleep based on the playback rate.
538 base::TimeDelta sleep = next_pts - now; 538 base::TimeDelta sleep = next_pts - now;
539 return base::TimeDelta::FromMicroseconds( 539 return base::TimeDelta::FromMicroseconds(
540 static_cast<int64>(sleep.InMicroseconds() / playback_rate)); 540 static_cast<int64>(sleep.InMicroseconds() / playback_rate));
541 } 541 }
542 542
543 void VideoRendererBase::DoStopOrError_Locked() { 543 void VideoRendererBase::DoStopOrError_Locked() {
544 DCHECK(!pending_paint_); 544 DCHECK(!pending_paint_);
545 DCHECK(!pending_paint_with_last_available_); 545 DCHECK(!pending_paint_with_last_available_);
546 lock_.AssertAcquired(); 546 lock_.AssertAcquired();
547 current_frame_ = NULL; 547 current_frame_ = NULL;
548 last_available_frame_ = NULL; 548 last_available_frame_ = NULL;
549 ready_frames_.clear(); 549 ready_frames_.clear();
550 } 550 }
551 551
552 int VideoRendererBase::NumFrames_Locked() const { 552 int VideoRendererBase::NumFrames_Locked() const {
553 lock_.AssertAcquired(); 553 lock_.AssertAcquired();
554 int outstanding_frames = 554 int outstanding_frames =
555 (current_frame_ ? 1 : 0) + (last_available_frame_ ? 1 : 0) + 555 (current_frame_ ? 1 : 0) + (last_available_frame_ ? 1 : 0) +
556 (current_frame_ && (current_frame_ == last_available_frame_) ? -1 : 0); 556 (current_frame_ && (current_frame_ == last_available_frame_) ? -1 : 0);
557 return ready_frames_.size() + outstanding_frames; 557 return ready_frames_.size() + outstanding_frames;
558 } 558 }
559 559
560 } // namespace media 560 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/video_renderer_base.h ('k') | media/filters/video_renderer_base_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698