| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this |
| 2 // source code is governed by a BSD-style license that can be found in the | 2 // source code is governed by a BSD-style license that can be found in the |
| 3 // LICENSE file. | 3 // LICENSE file. |
| 4 | 4 |
| 5 #include "media/base/buffers.h" | 5 #include "media/base/buffers.h" |
| 6 #include "media/base/filter_host.h" | 6 #include "media/base/filter_host.h" |
| 7 #include "media/filters/video_renderer_base.h" | 7 #include "media/filters/video_renderer_base.h" |
| 8 | 8 |
| 9 namespace media { | 9 namespace media { |
| 10 | 10 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 } | 74 } |
| 75 thread_ = NULL; | 75 thread_ = NULL; |
| 76 } | 76 } |
| 77 } | 77 } |
| 78 | 78 |
| 79 void VideoRendererBase::SetPlaybackRate(float playback_rate) { | 79 void VideoRendererBase::SetPlaybackRate(float playback_rate) { |
| 80 AutoLock auto_lock(lock_); | 80 AutoLock auto_lock(lock_); |
| 81 playback_rate_ = playback_rate; | 81 playback_rate_ = playback_rate; |
| 82 } | 82 } |
| 83 | 83 |
| 84 void VideoRendererBase::Seek(base::TimeDelta time) { | 84 void VideoRendererBase::Seek(base::TimeDelta time, FilterCallback* callback) { |
| 85 AutoLock auto_lock(lock_); | 85 AutoLock auto_lock(lock_); |
| 86 // We need the first frame in |frames_| to run the VideoRendererBase main | 86 // We need the first frame in |frames_| to run the VideoRendererBase main |
| 87 // loop, but we don't need decoded frames after the first frame since we are | 87 // loop, but we don't need decoded frames after the first frame since we are |
| 88 // at a new time. We should get some new frames so issue reads to compensate | 88 // at a new time. We should get some new frames so issue reads to compensate |
| 89 // for those discarded. | 89 // for those discarded. |
| 90 while (frames_.size() > 1) { | 90 while (frames_.size() > 1) { |
| 91 frames_.pop_back(); | 91 frames_.pop_back(); |
| 92 ScheduleRead(); | 92 ScheduleRead(); |
| 93 } | 93 } |
| 94 } | 94 } |
| 95 | 95 |
| 96 bool VideoRendererBase::Initialize(VideoDecoder* decoder) { | 96 void VideoRendererBase::Initialize(VideoDecoder* decoder, |
| 97 FilterCallback* callback) { |
| 97 AutoLock auto_lock(lock_); | 98 AutoLock auto_lock(lock_); |
| 99 DCHECK(decoder); |
| 100 DCHECK(callback); |
| 98 DCHECK_EQ(state_, UNINITIALIZED); | 101 DCHECK_EQ(state_, UNINITIALIZED); |
| 99 state_ = INITIALIZING; | 102 state_ = INITIALIZING; |
| 100 decoder_ = decoder; | 103 decoder_ = decoder; |
| 104 initialize_callback_.reset(callback); |
| 101 | 105 |
| 102 // Notify the pipeline of the video dimensions. | 106 // Notify the pipeline of the video dimensions. |
| 103 int width = 0; | 107 int width = 0; |
| 104 int height = 0; | 108 int height = 0; |
| 105 if (!ParseMediaFormat(decoder->media_format(), &width, &height)) | 109 if (!ParseMediaFormat(decoder->media_format(), &width, &height)) { |
| 106 return false; | 110 host()->Error(PIPELINE_ERROR_INITIALIZATION_FAILED); |
| 111 initialize_callback_->Run(); |
| 112 initialize_callback_.reset(); |
| 113 return; |
| 114 } |
| 107 host()->SetVideoSize(width, height); | 115 host()->SetVideoSize(width, height); |
| 108 | 116 |
| 109 // Initialize the subclass. | 117 // Initialize the subclass. |
| 110 // TODO(scherkus): do we trust subclasses not to do something silly while | 118 // TODO(scherkus): do we trust subclasses not to do something silly while |
| 111 // we're holding the lock? | 119 // we're holding the lock? |
| 112 if (!OnInitialize(decoder)) | 120 if (!OnInitialize(decoder)) { |
| 113 return false; | 121 host()->Error(PIPELINE_ERROR_INITIALIZATION_FAILED); |
| 122 initialize_callback_->Run(); |
| 123 initialize_callback_.reset(); |
| 124 return; |
| 125 } |
| 114 | 126 |
| 115 // Create our video thread. | 127 // Create our video thread. |
| 116 if (!PlatformThread::Create(0, this, &thread_)) { | 128 if (!PlatformThread::Create(0, this, &thread_)) { |
| 117 NOTREACHED() << "Video thread creation failed"; | 129 NOTREACHED() << "Video thread creation failed"; |
| 118 return false; | 130 host()->Error(PIPELINE_ERROR_INITIALIZATION_FAILED); |
| 131 initialize_callback_->Run(); |
| 132 initialize_callback_.reset(); |
| 133 return; |
| 119 } | 134 } |
| 120 | 135 |
| 121 #if defined(OS_WIN) | 136 #if defined(OS_WIN) |
| 122 // Bump up our priority so our sleeping is more accurate. | 137 // Bump up our priority so our sleeping is more accurate. |
| 123 // TODO(scherkus): find out if this is necessary, but it seems to help. | 138 // TODO(scherkus): find out if this is necessary, but it seems to help. |
| 124 ::SetThreadPriority(thread_, THREAD_PRIORITY_ABOVE_NORMAL); | 139 ::SetThreadPriority(thread_, THREAD_PRIORITY_ABOVE_NORMAL); |
| 125 #endif // defined(OS_WIN) | 140 #endif // defined(OS_WIN) |
| 126 | 141 |
| 127 // Queue initial reads. | 142 // Queue initial reads. |
| 128 for (size_t i = 0; i < kMaxFrames; ++i) { | 143 for (size_t i = 0; i < kMaxFrames; ++i) { |
| 129 ScheduleRead(); | 144 ScheduleRead(); |
| 130 } | 145 } |
| 131 | |
| 132 return true; | |
| 133 } | 146 } |
| 134 | 147 |
| 135 // PlatformThread::Delegate implementation. | 148 // PlatformThread::Delegate implementation. |
| 136 void VideoRendererBase::ThreadMain() { | 149 void VideoRendererBase::ThreadMain() { |
| 137 PlatformThread::SetName("VideoThread"); | 150 PlatformThread::SetName("VideoThread"); |
| 138 | 151 |
| 139 // Wait to be initialized so we can notify the first frame is available. | 152 // Wait to be initialized so we can notify the first frame is available. |
| 140 if (!WaitForInitialized()) | 153 if (!WaitForInitialized()) |
| 141 return; | 154 return; |
| 142 OnFrameAvailable(); | 155 OnFrameAvailable(); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 DCHECK_LE(frames_.size(), kMaxFrames); | 254 DCHECK_LE(frames_.size(), kMaxFrames); |
| 242 frame_available_.Signal(); | 255 frame_available_.Signal(); |
| 243 } | 256 } |
| 244 | 257 |
| 245 // Check for our initialization condition. | 258 // Check for our initialization condition. |
| 246 if (state_ == INITIALIZING && | 259 if (state_ == INITIALIZING && |
| 247 (frames_.size() == kMaxFrames || frame->IsEndOfStream())) { | 260 (frames_.size() == kMaxFrames || frame->IsEndOfStream())) { |
| 248 if (frames_.empty()) { | 261 if (frames_.empty()) { |
| 249 // We should have initialized but there's no decoded frames in the queue. | 262 // We should have initialized but there's no decoded frames in the queue. |
| 250 // Raise an error. | 263 // Raise an error. |
| 264 state_ = ERRORED; |
| 251 host()->Error(PIPELINE_ERROR_NO_DATA); | 265 host()->Error(PIPELINE_ERROR_NO_DATA); |
| 266 initialize_callback_->Run(); |
| 267 initialize_callback_.reset(); |
| 252 } else { | 268 } else { |
| 253 state_ = INITIALIZED; | 269 state_ = INITIALIZED; |
| 254 current_frame_ = frames_.front(); | 270 current_frame_ = frames_.front(); |
| 255 host()->InitializationComplete(); | 271 initialize_callback_->Run(); |
| 272 initialize_callback_.reset(); |
| 256 } | 273 } |
| 257 } | 274 } |
| 258 } | 275 } |
| 259 | 276 |
| 260 void VideoRendererBase::ScheduleRead() { | 277 void VideoRendererBase::ScheduleRead() { |
| 261 decoder_->Read(NewCallback(this, &VideoRendererBase::OnReadComplete)); | 278 decoder_->Read(NewCallback(this, &VideoRendererBase::OnReadComplete)); |
| 262 } | 279 } |
| 263 | 280 |
| 264 bool VideoRendererBase::WaitForInitialized() { | 281 bool VideoRendererBase::WaitForInitialized() { |
| 265 // This loop essentially handles preroll. We wait until we've been fully | 282 // This loop essentially handles preroll. We wait until we've been fully |
| 266 // initialized so we can call OnFrameAvailable() to provide subclasses with | 283 // initialized so we can call OnFrameAvailable() to provide subclasses with |
| 267 // the first frame. | 284 // the first frame. |
| 268 AutoLock auto_lock(lock_); | 285 AutoLock auto_lock(lock_); |
| 269 DCHECK_EQ(state_, INITIALIZING); | |
| 270 while (state_ == INITIALIZING) { | 286 while (state_ == INITIALIZING) { |
| 271 frame_available_.Wait(); | 287 frame_available_.Wait(); |
| 272 if (state_ == STOPPED) { | 288 } |
| 273 return false; | 289 if (state_ == STOPPED || state_ == ERRORED) { |
| 274 } | 290 return false; |
| 275 } | 291 } |
| 276 DCHECK_EQ(state_, INITIALIZED); | 292 DCHECK_EQ(state_, INITIALIZED); |
| 277 DCHECK(current_frame_); | 293 DCHECK(current_frame_); |
| 278 return true; | 294 return true; |
| 279 } | 295 } |
| 280 | 296 |
| 281 } // namespace media | 297 } // namespace media |
| OLD | NEW |