| OLD | NEW |
| 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 "base/bind.h" | 5 #include "base/bind.h" |
| 6 #include "base/callback.h" | 6 #include "base/callback.h" |
| 7 #include "base/threading/platform_thread.h" | 7 #include "base/threading/platform_thread.h" |
| 8 #include "media/base/buffers.h" | 8 #include "media/base/buffers.h" |
| 9 #include "media/base/filter_host.h" | 9 #include "media/base/filter_host.h" |
| 10 #include "media/base/limits.h" | 10 #include "media/base/limits.h" |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 | 57 |
| 58 AttemptFlush_Locked(); | 58 AttemptFlush_Locked(); |
| 59 } | 59 } |
| 60 | 60 |
| 61 void VideoRendererBase::Stop(const base::Closure& callback) { | 61 void VideoRendererBase::Stop(const base::Closure& callback) { |
| 62 base::PlatformThreadHandle thread_to_join = base::kNullThreadHandle; | 62 base::PlatformThreadHandle thread_to_join = base::kNullThreadHandle; |
| 63 { | 63 { |
| 64 base::AutoLock auto_lock(lock_); | 64 base::AutoLock auto_lock(lock_); |
| 65 state_ = kStopped; | 65 state_ = kStopped; |
| 66 | 66 |
| 67 statistics_callback_.Reset(); |
| 68 video_time_cb_.Reset(); |
| 67 if (!pending_paint_ && !pending_paint_with_last_available_) | 69 if (!pending_paint_ && !pending_paint_with_last_available_) |
| 68 DoStopOrError_Locked(); | 70 DoStopOrError_Locked(); |
| 69 | 71 |
| 70 // Clean up our thread if present. | 72 // Clean up our thread if present. |
| 71 if (thread_ != base::kNullThreadHandle) { | 73 if (thread_ != base::kNullThreadHandle) { |
| 72 // Signal the thread since it's possible to get stopped with the video | 74 // Signal the thread since it's possible to get stopped with the video |
| 73 // thread waiting for a read to complete. | 75 // thread waiting for a read to complete. |
| 74 frame_available_.Signal(); | 76 frame_available_.Signal(); |
| 75 thread_to_join = thread_; | 77 thread_to_join = thread_; |
| 76 thread_ = base::kNullThreadHandle; | 78 thread_ = base::kNullThreadHandle; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 93 DCHECK(!cb.is_null()); | 95 DCHECK(!cb.is_null()); |
| 94 DCHECK(seek_cb_.is_null()); | 96 DCHECK(seek_cb_.is_null()); |
| 95 | 97 |
| 96 state_ = kSeeking; | 98 state_ = kSeeking; |
| 97 seek_cb_ = cb; | 99 seek_cb_ = cb; |
| 98 seek_timestamp_ = time; | 100 seek_timestamp_ = time; |
| 99 AttemptRead_Locked(); | 101 AttemptRead_Locked(); |
| 100 } | 102 } |
| 101 | 103 |
| 102 void VideoRendererBase::Initialize(VideoDecoder* decoder, | 104 void VideoRendererBase::Initialize(VideoDecoder* decoder, |
| 103 const base::Closure& callback, | 105 const base::Closure& init_cb, |
| 104 const StatisticsCallback& stats_callback) { | 106 const StatisticsCallback& stats_callback, |
| 107 const VideoTimeCB& video_time_cb) { |
| 105 base::AutoLock auto_lock(lock_); | 108 base::AutoLock auto_lock(lock_); |
| 106 DCHECK(decoder); | 109 DCHECK(decoder); |
| 107 DCHECK(!callback.is_null()); | 110 DCHECK(!init_cb.is_null()); |
| 108 DCHECK(!stats_callback.is_null()); | 111 DCHECK(!stats_callback.is_null()); |
| 112 DCHECK(!video_time_cb.is_null()); |
| 109 DCHECK_EQ(kUninitialized, state_); | 113 DCHECK_EQ(kUninitialized, state_); |
| 110 decoder_ = decoder; | 114 decoder_ = decoder; |
| 111 | 115 |
| 112 statistics_callback_ = stats_callback; | 116 statistics_callback_ = stats_callback; |
| 117 video_time_cb_ = video_time_cb; |
| 113 | 118 |
| 114 // Notify the pipeline of the video dimensions. | 119 // Notify the pipeline of the video dimensions. |
| 115 host()->SetNaturalVideoSize(decoder_->natural_size()); | 120 host()->SetNaturalVideoSize(decoder_->natural_size()); |
| 116 | 121 |
| 117 // We're all good! Consider ourselves flushed. (ThreadMain() should never | 122 // We're all good! Consider ourselves flushed. (ThreadMain() should never |
| 118 // see us in the kUninitialized state). | 123 // see us in the kUninitialized state). |
| 119 // Since we had an initial Seek, we consider ourself flushed, because we | 124 // Since we had an initial Seek, we consider ourself flushed, because we |
| 120 // have not populated any buffers yet. | 125 // have not populated any buffers yet. |
| 121 state_ = kFlushed; | 126 state_ = kFlushed; |
| 122 | 127 |
| 123 set_opaque_cb_.Run(!decoder->HasAlpha()); | 128 set_opaque_cb_.Run(!decoder->HasAlpha()); |
| 124 set_opaque_cb_.Reset(); | 129 set_opaque_cb_.Reset(); |
| 125 | 130 |
| 126 // Create our video thread. | 131 // Create our video thread. |
| 127 if (!base::PlatformThread::Create(0, this, &thread_)) { | 132 if (!base::PlatformThread::Create(0, this, &thread_)) { |
| 128 NOTREACHED() << "Video thread creation failed"; | 133 NOTREACHED() << "Video thread creation failed"; |
| 129 state_ = kError; | 134 state_ = kError; |
| 130 host()->SetError(PIPELINE_ERROR_INITIALIZATION_FAILED); | 135 host()->SetError(PIPELINE_ERROR_INITIALIZATION_FAILED); |
| 131 callback.Run(); | 136 init_cb.Run(); |
| 132 return; | 137 return; |
| 133 } | 138 } |
| 134 | 139 |
| 135 #if defined(OS_WIN) | 140 #if defined(OS_WIN) |
| 136 // Bump up our priority so our sleeping is more accurate. | 141 // Bump up our priority so our sleeping is more accurate. |
| 137 // TODO(scherkus): find out if this is necessary, but it seems to help. | 142 // TODO(scherkus): find out if this is necessary, but it seems to help. |
| 138 ::SetThreadPriority(thread_, THREAD_PRIORITY_ABOVE_NORMAL); | 143 ::SetThreadPriority(thread_, THREAD_PRIORITY_ABOVE_NORMAL); |
| 139 #endif // defined(OS_WIN) | 144 #endif // defined(OS_WIN) |
| 140 callback.Run(); | 145 init_cb.Run(); |
| 141 } | 146 } |
| 142 | 147 |
| 143 bool VideoRendererBase::HasEnded() { | 148 bool VideoRendererBase::HasEnded() { |
| 144 base::AutoLock auto_lock(lock_); | 149 base::AutoLock auto_lock(lock_); |
| 145 return state_ == kEnded; | 150 return state_ == kEnded; |
| 146 } | 151 } |
| 147 | 152 |
| 148 // PlatformThread::Delegate implementation. | 153 // PlatformThread::Delegate implementation. |
| 149 void VideoRendererBase::ThreadMain() { | 154 void VideoRendererBase::ThreadMain() { |
| 150 base::PlatformThread::SetName("CrVideoRenderer"); | 155 base::PlatformThread::SetName("CrVideoRenderer"); |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 if (!frame->IsEndOfStream()) { | 372 if (!frame->IsEndOfStream()) { |
| 368 if (frame->GetTimestamp() > host()->GetDuration()) | 373 if (frame->GetTimestamp() > host()->GetDuration()) |
| 369 frame->SetTimestamp(host()->GetDuration()); | 374 frame->SetTimestamp(host()->GetDuration()); |
| 370 if ((frame->GetTimestamp() + frame->GetDuration()) > host()->GetDuration()) | 375 if ((frame->GetTimestamp() + frame->GetDuration()) > host()->GetDuration()) |
| 371 frame->SetDuration(host()->GetDuration() - frame->GetTimestamp()); | 376 frame->SetDuration(host()->GetDuration() - frame->GetTimestamp()); |
| 372 } | 377 } |
| 373 | 378 |
| 374 // This one's a keeper! Place it in the ready queue. | 379 // This one's a keeper! Place it in the ready queue. |
| 375 ready_frames_.push_back(frame); | 380 ready_frames_.push_back(frame); |
| 376 DCHECK_LE(NumFrames_Locked(), limits::kMaxVideoFrames); | 381 DCHECK_LE(NumFrames_Locked(), limits::kMaxVideoFrames); |
| 382 if (!frame->IsEndOfStream()) |
| 383 video_time_cb_.Run(frame->GetTimestamp() + frame->GetDuration()); |
| 377 frame_available_.Signal(); | 384 frame_available_.Signal(); |
| 378 | 385 |
| 379 PipelineStatistics statistics; | 386 PipelineStatistics statistics; |
| 380 statistics.video_frames_decoded = 1; | 387 statistics.video_frames_decoded = 1; |
| 381 statistics_callback_.Run(statistics); | 388 statistics_callback_.Run(statistics); |
| 382 | 389 |
| 383 // Always request more decoded video if we have capacity. This serves two | 390 // Always request more decoded video if we have capacity. This serves two |
| 384 // purposes: | 391 // purposes: |
| 385 // 1) Prerolling while paused | 392 // 1) Prerolling while paused |
| 386 // 2) Keeps decoding going if video rendering thread starts falling behind | 393 // 2) Keeps decoding going if video rendering thread starts falling behind |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 470 | 477 |
| 471 int VideoRendererBase::NumFrames_Locked() const { | 478 int VideoRendererBase::NumFrames_Locked() const { |
| 472 lock_.AssertAcquired(); | 479 lock_.AssertAcquired(); |
| 473 int outstanding_frames = | 480 int outstanding_frames = |
| 474 (current_frame_ ? 1 : 0) + (last_available_frame_ ? 1 : 0) + | 481 (current_frame_ ? 1 : 0) + (last_available_frame_ ? 1 : 0) + |
| 475 (current_frame_ && (current_frame_ == last_available_frame_) ? -1 : 0); | 482 (current_frame_ && (current_frame_ == last_available_frame_) ? -1 : 0); |
| 476 return ready_frames_.size() + outstanding_frames; | 483 return ready_frames_.size() + outstanding_frames; |
| 477 } | 484 } |
| 478 | 485 |
| 479 } // namespace media | 486 } // namespace media |
| OLD | NEW |