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 |