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 "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 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
105 DCHECK(!cb.is_null()); | 105 DCHECK(!cb.is_null()); |
106 DCHECK(preroll_cb_.is_null()); | 106 DCHECK(preroll_cb_.is_null()); |
107 | 107 |
108 state_ = kPrerolling; | 108 state_ = kPrerolling; |
109 preroll_cb_ = cb; | 109 preroll_cb_ = cb; |
110 preroll_timestamp_ = time; | 110 preroll_timestamp_ = time; |
111 prerolling_delayed_frame_ = NULL; | 111 prerolling_delayed_frame_ = NULL; |
112 AttemptRead_Locked(); | 112 AttemptRead_Locked(); |
113 } | 113 } |
114 | 114 |
115 void VideoRendererBase::Initialize(const scoped_refptr<VideoDecoder>& decoder, | 115 void VideoRendererBase::Initialize(const scoped_refptr<DemuxerStream>& stream, |
116 const VideoDecoderList& decoders, | |
116 const PipelineStatusCB& init_cb, | 117 const PipelineStatusCB& init_cb, |
117 const StatisticsCB& statistics_cb, | 118 const StatisticsCB& statistics_cb, |
118 const TimeCB& max_time_cb, | 119 const TimeCB& max_time_cb, |
119 const NaturalSizeChangedCB& size_changed_cb, | 120 const NaturalSizeChangedCB& size_changed_cb, |
120 const base::Closure& ended_cb, | 121 const base::Closure& ended_cb, |
121 const PipelineStatusCB& error_cb, | 122 const PipelineStatusCB& error_cb, |
122 const TimeDeltaCB& get_time_cb, | 123 const TimeDeltaCB& get_time_cb, |
123 const TimeDeltaCB& get_duration_cb) { | 124 const TimeDeltaCB& get_duration_cb) { |
124 base::AutoLock auto_lock(lock_); | 125 base::AutoLock auto_lock(lock_); |
125 DCHECK(decoder); | 126 DCHECK(stream); |
127 DCHECK(!decoders.empty()); | |
128 DCHECK_EQ(stream->type(), DemuxerStream::VIDEO); | |
126 DCHECK(!init_cb.is_null()); | 129 DCHECK(!init_cb.is_null()); |
127 DCHECK(!statistics_cb.is_null()); | 130 DCHECK(!statistics_cb.is_null()); |
128 DCHECK(!max_time_cb.is_null()); | 131 DCHECK(!max_time_cb.is_null()); |
129 DCHECK(!size_changed_cb.is_null()); | 132 DCHECK(!size_changed_cb.is_null()); |
130 DCHECK(!ended_cb.is_null()); | 133 DCHECK(!ended_cb.is_null()); |
131 DCHECK(!get_time_cb.is_null()); | 134 DCHECK(!get_time_cb.is_null()); |
132 DCHECK(!get_duration_cb.is_null()); | 135 DCHECK(!get_duration_cb.is_null()); |
133 DCHECK_EQ(kUninitialized, state_); | 136 DCHECK_EQ(kUninitialized, state_); |
134 decoder_ = decoder; | |
135 | 137 |
138 demuxer_stream_ = stream; | |
139 decoders_ = decoders; | |
140 init_cb_ = init_cb; | |
136 statistics_cb_ = statistics_cb; | 141 statistics_cb_ = statistics_cb; |
137 max_time_cb_ = max_time_cb; | 142 max_time_cb_ = max_time_cb; |
138 size_changed_cb_ = size_changed_cb; | 143 size_changed_cb_ = size_changed_cb; |
139 ended_cb_ = ended_cb; | 144 ended_cb_ = ended_cb; |
140 error_cb_ = error_cb; | 145 error_cb_ = error_cb; |
141 get_time_cb_ = get_time_cb; | 146 get_time_cb_ = get_time_cb; |
142 get_duration_cb_ = get_duration_cb; | 147 get_duration_cb_ = get_duration_cb; |
143 | 148 |
149 InitializeNextDecoder(); | |
150 } | |
151 | |
152 void VideoRendererBase::InitializeNextDecoder() { | |
153 lock_.AssertAcquired(); | |
154 DCHECK(!decoders_.empty()); | |
155 | |
156 scoped_refptr<VideoDecoder> decoder = decoders_.front(); | |
157 decoders_.pop_front(); | |
158 | |
159 DCHECK(decoder); | |
160 decoder_ = decoder; | |
161 | |
162 base::AutoUnlock auto_unlock(lock_); | |
163 decoder->Initialize( | |
164 demuxer_stream_, | |
165 base::Bind(&VideoRendererBase::OnDecoderInitDone, this), | |
166 statistics_cb_); | |
167 } | |
168 | |
169 void VideoRendererBase::OnDecoderInitDone(PipelineStatus status) { | |
170 base::AutoLock auto_lock(lock_); | |
171 if (!decoders_.empty() && status == DECODER_ERROR_NOT_SUPPORTED) { | |
172 InitializeNextDecoder(); | |
173 return; | |
174 } | |
175 | |
176 if (state_ == kStopped) | |
xhwang
2012/08/09 21:38:29
Q: if VBR is already stopped, do we want to Initia
acolwell GONE FROM CHROMIUM
2012/08/09 22:23:32
Good point. Moved this to the top.
| |
177 return; | |
178 | |
179 if (status != PIPELINE_OK) { | |
180 state_ = kError; | |
181 base::ResetAndReturn(&init_cb_).Run(status); | |
182 return; | |
183 } | |
184 | |
144 // We're all good! Consider ourselves flushed. (ThreadMain() should never | 185 // We're all good! Consider ourselves flushed. (ThreadMain() should never |
145 // see us in the kUninitialized state). | 186 // see us in the kUninitialized state). |
146 // Since we had an initial Preroll(), we consider ourself flushed, because we | 187 // Since we had an initial Preroll(), we consider ourself flushed, because we |
147 // have not populated any buffers yet. | 188 // have not populated any buffers yet. |
189 | |
190 // Clear out remaining decoders since we don't need them now. | |
191 decoders_.clear(); | |
192 | |
148 state_ = kFlushed; | 193 state_ = kFlushed; |
149 | 194 |
150 set_opaque_cb_.Run(!decoder->HasAlpha()); | 195 set_opaque_cb_.Run(!decoder_->HasAlpha()); |
151 set_opaque_cb_.Reset(); | 196 set_opaque_cb_.Reset(); |
152 | 197 |
153 // Create our video thread. | 198 // Create our video thread. |
154 if (!base::PlatformThread::Create(0, this, &thread_)) { | 199 if (!base::PlatformThread::Create(0, this, &thread_)) { |
155 NOTREACHED() << "Video thread creation failed"; | 200 NOTREACHED() << "Video thread creation failed"; |
156 state_ = kError; | 201 state_ = kError; |
157 init_cb.Run(PIPELINE_ERROR_INITIALIZATION_FAILED); | 202 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); |
158 return; | 203 return; |
159 } | 204 } |
160 | 205 |
161 #if defined(OS_WIN) | 206 #if defined(OS_WIN) |
162 // Bump up our priority so our sleeping is more accurate. | 207 // Bump up our priority so our sleeping is more accurate. |
163 // TODO(scherkus): find out if this is necessary, but it seems to help. | 208 // TODO(scherkus): find out if this is necessary, but it seems to help. |
164 ::SetThreadPriority(thread_, THREAD_PRIORITY_ABOVE_NORMAL); | 209 ::SetThreadPriority(thread_, THREAD_PRIORITY_ABOVE_NORMAL); |
165 #endif // defined(OS_WIN) | 210 #endif // defined(OS_WIN) |
166 init_cb.Run(PIPELINE_OK); | 211 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
167 } | 212 } |
168 | 213 |
169 bool VideoRendererBase::HasEnded() { | 214 bool VideoRendererBase::HasEnded() { |
170 base::AutoLock auto_lock(lock_); | 215 base::AutoLock auto_lock(lock_); |
171 return state_ == kEnded; | 216 return state_ == kEnded; |
172 } | 217 } |
173 | 218 |
219 void VideoRendererBase::PrepareForShutdownHack() { | |
220 base::AutoLock auto_lock(lock_); | |
221 if (decoder_) | |
222 decoder_->PrepareForShutdownHack(); | |
223 } | |
224 | |
174 // PlatformThread::Delegate implementation. | 225 // PlatformThread::Delegate implementation. |
175 void VideoRendererBase::ThreadMain() { | 226 void VideoRendererBase::ThreadMain() { |
176 base::PlatformThread::SetName("CrVideoRenderer"); | 227 base::PlatformThread::SetName("CrVideoRenderer"); |
177 | 228 |
178 // The number of milliseconds to idle when we do not have anything to do. | 229 // The number of milliseconds to idle when we do not have anything to do. |
179 // Nothing special about the value, other than we're being more OS-friendly | 230 // Nothing special about the value, other than we're being more OS-friendly |
180 // than sleeping for 1 millisecond. | 231 // than sleeping for 1 millisecond. |
181 // | 232 // |
182 // TOOD(scherkus): switch to pure event-driven frame timing instead of this | 233 // TOOD(scherkus): switch to pure event-driven frame timing instead of this |
183 // kIdleTimeDelta business http://crbug.com/106874 | 234 // kIdleTimeDelta business http://crbug.com/106874 |
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
578 | 629 |
579 int VideoRendererBase::NumFrames_Locked() const { | 630 int VideoRendererBase::NumFrames_Locked() const { |
580 lock_.AssertAcquired(); | 631 lock_.AssertAcquired(); |
581 int outstanding_frames = | 632 int outstanding_frames = |
582 (current_frame_ ? 1 : 0) + (last_available_frame_ ? 1 : 0) + | 633 (current_frame_ ? 1 : 0) + (last_available_frame_ ? 1 : 0) + |
583 (current_frame_ && (current_frame_ == last_available_frame_) ? -1 : 0); | 634 (current_frame_ && (current_frame_ == last_available_frame_) ? -1 : 0); |
584 return ready_frames_.size() + outstanding_frames; | 635 return ready_frames_.size() + outstanding_frames; |
585 } | 636 } |
586 | 637 |
587 } // namespace media | 638 } // namespace media |
OLD | NEW |