OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/decoder_stream.h" | 5 #include "media/filters/decoder_stream.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
10 #include "base/location.h" | 10 #include "base/location.h" |
(...skipping 27 matching lines...) Expand all Loading... | |
38 return "DecoderStream<AUDIO>::Decode"; | 38 return "DecoderStream<AUDIO>::Decode"; |
39 } | 39 } |
40 | 40 |
41 template <DemuxerStream::Type StreamType> | 41 template <DemuxerStream::Type StreamType> |
42 DecoderStream<StreamType>::DecoderStream( | 42 DecoderStream<StreamType>::DecoderStream( |
43 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, | 43 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
44 ScopedVector<Decoder> decoders, | 44 ScopedVector<Decoder> decoders, |
45 const SetDecryptorReadyCB& set_decryptor_ready_cb) | 45 const SetDecryptorReadyCB& set_decryptor_ready_cb) |
46 : task_runner_(task_runner), | 46 : task_runner_(task_runner), |
47 state_(STATE_UNINITIALIZED), | 47 state_(STATE_UNINITIALIZED), |
48 error_(OK), | |
48 stream_(NULL), | 49 stream_(NULL), |
49 decoder_selector_( | 50 decoder_selector_( |
50 new DecoderSelector<StreamType>(task_runner, | 51 new DecoderSelector<StreamType>(task_runner, |
51 decoders.Pass(), | 52 decoders.Pass(), |
52 set_decryptor_ready_cb)), | 53 set_decryptor_ready_cb)), |
53 active_splice_(false), | 54 active_splice_(false), |
55 pending_decode_requests_(0), | |
54 weak_factory_(this) {} | 56 weak_factory_(this) {} |
55 | 57 |
56 template <DemuxerStream::Type StreamType> | 58 template <DemuxerStream::Type StreamType> |
57 DecoderStream<StreamType>::~DecoderStream() { | 59 DecoderStream<StreamType>::~DecoderStream() { |
58 DCHECK(state_ == STATE_UNINITIALIZED || state_ == STATE_STOPPED) << state_; | 60 DCHECK(state_ == STATE_UNINITIALIZED || state_ == STATE_STOPPED) << state_; |
59 } | 61 } |
60 | 62 |
61 template <DemuxerStream::Type StreamType> | 63 template <DemuxerStream::Type StreamType> |
62 void DecoderStream<StreamType>::Initialize(DemuxerStream* stream, | 64 void DecoderStream<StreamType>::Initialize(DemuxerStream* stream, |
63 const StatisticsCB& statistics_cb, | 65 const StatisticsCB& statistics_cb, |
(...skipping 14 matching lines...) Expand all Loading... | |
78 stream, | 80 stream, |
79 base::Bind(&DecoderStream<StreamType>::OnDecoderSelected, | 81 base::Bind(&DecoderStream<StreamType>::OnDecoderSelected, |
80 weak_factory_.GetWeakPtr())); | 82 weak_factory_.GetWeakPtr())); |
81 } | 83 } |
82 | 84 |
83 template <DemuxerStream::Type StreamType> | 85 template <DemuxerStream::Type StreamType> |
84 void DecoderStream<StreamType>::Read(const ReadCB& read_cb) { | 86 void DecoderStream<StreamType>::Read(const ReadCB& read_cb) { |
85 FUNCTION_DVLOG(2); | 87 FUNCTION_DVLOG(2); |
86 DCHECK(task_runner_->BelongsToCurrentThread()); | 88 DCHECK(task_runner_->BelongsToCurrentThread()); |
87 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || | 89 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || |
88 state_ == STATE_ERROR) << state_; | 90 state_ == STATE_ERROR || state_ == STATE_REINITIALIZING_DECODER || |
91 state_ == STATE_PENDING_DEMUXER_READ) | |
92 << state_; | |
89 // No two reads in the flight at any time. | 93 // No two reads in the flight at any time. |
90 DCHECK(read_cb_.is_null()); | 94 DCHECK(read_cb_.is_null()); |
91 // No read during resetting or stopping process. | 95 // No read during resetting or stopping process. |
92 DCHECK(reset_cb_.is_null()); | 96 DCHECK(reset_cb_.is_null()); |
93 DCHECK(stop_cb_.is_null()); | 97 DCHECK(stop_cb_.is_null()); |
94 | 98 |
99 read_cb_ = read_cb; | |
100 | |
95 if (state_ == STATE_ERROR) { | 101 if (state_ == STATE_ERROR) { |
102 DCHECK_NE(error_, OK); | |
96 task_runner_->PostTask(FROM_HERE, base::Bind( | 103 task_runner_->PostTask(FROM_HERE, base::Bind( |
97 read_cb, DECODE_ERROR, scoped_refptr<Output>())); | 104 base::ResetAndReturn(&read_cb_), error_, scoped_refptr<Output>())); |
98 return; | 105 return; |
99 } | 106 } |
100 | 107 |
101 read_cb_ = read_cb; | 108 if (!ready_outputs_.empty()) { |
109 task_runner_->PostTask(FROM_HERE, base::Bind( | |
110 base::ResetAndReturn(&read_cb_), OK, ready_outputs_.front())); | |
111 ready_outputs_.pop_front(); | |
112 } | |
113 | |
114 // Decoder may be in reinitializing state as result of the previous Read(). | |
115 if (state_ == STATE_REINITIALIZING_DECODER) | |
116 return; | |
117 | |
118 if (!CanDecodeAnotherBuffer()) | |
119 return; | |
102 | 120 |
103 if (state_ == STATE_FLUSHING_DECODER) { | 121 if (state_ == STATE_FLUSHING_DECODER) { |
104 FlushDecoder(); | 122 FlushDecoder(); |
105 return; | 123 return; |
106 } | 124 } |
107 | 125 |
108 scoped_refptr<Output> output = decoder_->GetDecodeOutput(); | 126 if (state_ != STATE_PENDING_DEMUXER_READ) |
109 | 127 ReadFromDemuxerStream(); |
110 // If the decoder has queued output ready to go we don't need a demuxer read. | |
111 if (output) { | |
112 task_runner_->PostTask( | |
113 FROM_HERE, base::Bind(base::ResetAndReturn(&read_cb_), OK, output)); | |
114 return; | |
115 } | |
116 | |
117 ReadFromDemuxerStream(); | |
118 } | 128 } |
119 | 129 |
120 template <DemuxerStream::Type StreamType> | 130 template <DemuxerStream::Type StreamType> |
121 void DecoderStream<StreamType>::Reset(const base::Closure& closure) { | 131 void DecoderStream<StreamType>::Reset(const base::Closure& closure) { |
122 FUNCTION_DVLOG(2); | 132 FUNCTION_DVLOG(2); |
123 DCHECK(task_runner_->BelongsToCurrentThread()); | 133 DCHECK(task_runner_->BelongsToCurrentThread()); |
124 DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_; | 134 DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_; |
125 DCHECK(reset_cb_.is_null()); | 135 DCHECK(reset_cb_.is_null()); |
126 DCHECK(stop_cb_.is_null()); | 136 DCHECK(stop_cb_.is_null()); |
127 | 137 |
128 reset_cb_ = closure; | 138 reset_cb_ = closure; |
129 | 139 |
140 if (!read_cb_.is_null()) { | |
141 task_runner_->PostTask(FROM_HERE, base::Bind( | |
142 base::ResetAndReturn(&read_cb_), ABORTED, scoped_refptr<Output>())); | |
143 } | |
144 | |
145 ready_outputs_.clear(); | |
146 | |
130 // During decoder reinitialization, the Decoder does not need to be and | 147 // During decoder reinitialization, the Decoder does not need to be and |
131 // cannot be Reset(). |decrypting_demuxer_stream_| was reset before decoder | 148 // cannot be Reset(). |decrypting_demuxer_stream_| was reset before decoder |
132 // reinitialization. | 149 // reinitialization. |
133 if (state_ == STATE_REINITIALIZING_DECODER) | 150 if (state_ == STATE_REINITIALIZING_DECODER) |
134 return; | 151 return; |
135 | 152 |
136 // During pending demuxer read and when not using DecryptingDemuxerStream, | 153 // During pending demuxer read and when not using DecryptingDemuxerStream, |
137 // the Decoder will be reset after demuxer read is returned | 154 // the Decoder will be reset after demuxer read is returned |
138 // (in OnBufferReady()). | 155 // (in OnBufferReady()). |
139 if (state_ == STATE_PENDING_DEMUXER_READ && !decrypting_demuxer_stream_) | 156 if (state_ == STATE_PENDING_DEMUXER_READ && !decrypting_demuxer_stream_) |
140 return; | 157 return; |
141 | 158 |
142 // The Decoder API guarantees that if Decoder::Reset() is called during | |
143 // a pending decode, the decode callback must be fired before the reset | |
144 // callback is fired. Therefore, we can call Decoder::Reset() regardless | |
145 // of if we have a pending decode and always satisfy the reset callback when | |
146 // the decoder reset is finished. | |
147 if (decrypting_demuxer_stream_) { | 159 if (decrypting_demuxer_stream_) { |
148 decrypting_demuxer_stream_->Reset(base::Bind( | 160 decrypting_demuxer_stream_->Reset(base::Bind( |
149 &DecoderStream<StreamType>::ResetDecoder, weak_factory_.GetWeakPtr())); | 161 &DecoderStream<StreamType>::ResetDecoder, weak_factory_.GetWeakPtr())); |
150 return; | 162 return; |
151 } | 163 } |
152 | 164 |
153 ResetDecoder(); | 165 ResetDecoder(); |
154 } | 166 } |
155 | 167 |
156 template <DemuxerStream::Type StreamType> | 168 template <DemuxerStream::Type StreamType> |
157 void DecoderStream<StreamType>::Stop(const base::Closure& closure) { | 169 void DecoderStream<StreamType>::Stop(const base::Closure& closure) { |
158 FUNCTION_DVLOG(2); | 170 FUNCTION_DVLOG(2); |
159 DCHECK(task_runner_->BelongsToCurrentThread()); | 171 DCHECK(task_runner_->BelongsToCurrentThread()); |
160 DCHECK_NE(state_, STATE_STOPPED) << state_; | 172 DCHECK_NE(state_, STATE_STOPPED) << state_; |
161 DCHECK(stop_cb_.is_null()); | 173 DCHECK(stop_cb_.is_null()); |
162 | 174 |
163 stop_cb_ = closure; | 175 stop_cb_ = closure; |
164 | 176 |
165 if (state_ == STATE_INITIALIZING) { | 177 if (state_ == STATE_INITIALIZING) { |
166 decoder_selector_->Abort(); | 178 decoder_selector_->Abort(); |
167 return; | 179 return; |
168 } | 180 } |
169 | 181 |
170 DCHECK(init_cb_.is_null()); | 182 DCHECK(init_cb_.is_null()); |
171 | 183 |
172 // All pending callbacks will be dropped. | 184 // All pending callbacks will be dropped. |
173 weak_factory_.InvalidateWeakPtrs(); | 185 weak_factory_.InvalidateWeakPtrs(); |
174 | 186 |
175 // Post callbacks to prevent reentrance into this object. | 187 // Post callbacks to prevent reentrance into this object. |
176 if (!read_cb_.is_null()) | 188 if (!read_cb_.is_null()) { |
177 task_runner_->PostTask(FROM_HERE, base::Bind( | 189 task_runner_->PostTask(FROM_HERE, base::Bind( |
178 base::ResetAndReturn(&read_cb_), ABORTED, scoped_refptr<Output>())); | 190 base::ResetAndReturn(&read_cb_), ABORTED, scoped_refptr<Output>())); |
191 } | |
179 if (!reset_cb_.is_null()) | 192 if (!reset_cb_.is_null()) |
180 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&reset_cb_)); | 193 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&reset_cb_)); |
181 | 194 |
182 if (decrypting_demuxer_stream_) { | 195 if (decrypting_demuxer_stream_) { |
183 decrypting_demuxer_stream_->Stop(base::Bind( | 196 decrypting_demuxer_stream_->Stop(base::Bind( |
184 &DecoderStream<StreamType>::StopDecoder, weak_factory_.GetWeakPtr())); | 197 &DecoderStream<StreamType>::StopDecoder, weak_factory_.GetWeakPtr())); |
185 return; | 198 return; |
186 } | 199 } |
187 | 200 |
188 // We may not have a |decoder_| if Stop() was called during initialization. | 201 // We may not have a |decoder_| if Stop() was called during initialization. |
(...skipping 15 matching lines...) Expand all Loading... | |
204 return decoder_->CanReadWithoutStalling(); | 217 return decoder_->CanReadWithoutStalling(); |
205 } | 218 } |
206 | 219 |
207 template <> | 220 template <> |
208 bool DecoderStream<DemuxerStream::AUDIO>::CanReadWithoutStalling() const { | 221 bool DecoderStream<DemuxerStream::AUDIO>::CanReadWithoutStalling() const { |
209 DCHECK(task_runner_->BelongsToCurrentThread()); | 222 DCHECK(task_runner_->BelongsToCurrentThread()); |
210 return true; | 223 return true; |
211 } | 224 } |
212 | 225 |
213 template <DemuxerStream::Type StreamType> | 226 template <DemuxerStream::Type StreamType> |
227 bool DecoderStream<StreamType>::CanDecodeAnotherBuffer() const { | |
228 DCHECK(task_runner_->BelongsToCurrentThread()); | |
229 | |
230 // Limit total number of outputs stored in |ready_outputs_| and being decoded. | |
231 // It only makes sense to saturate decoder completely when output queue is | |
232 // empty. | |
233 // TODO(sergeyu): Is that the best way to throttle decoding requests? | |
xhwang
2014/04/25 00:36:03
I don't see a better way to do that. The current a
Sergey Ulanov
2014/04/26 00:59:29
removed TODO
| |
234 int num_decodes = | |
235 static_cast<int>(ready_outputs_.size()) + pending_decode_requests_; | |
236 return num_decodes < decoder_->GetMaxDecodeRequests(); | |
237 } | |
238 | |
239 template <> | |
240 bool DecoderStream<DemuxerStream::AUDIO>::CanDecodeAnotherBuffer() const { | |
241 DCHECK(task_runner_->BelongsToCurrentThread()); | |
242 return !pending_decode_requests_ && ready_outputs_.empty(); | |
243 } | |
244 | |
245 template <DemuxerStream::Type StreamType> | |
214 void DecoderStream<StreamType>::OnDecoderSelected( | 246 void DecoderStream<StreamType>::OnDecoderSelected( |
215 scoped_ptr<Decoder> selected_decoder, | 247 scoped_ptr<Decoder> selected_decoder, |
216 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { | 248 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { |
217 FUNCTION_DVLOG(2); | 249 FUNCTION_DVLOG(2); |
218 DCHECK(task_runner_->BelongsToCurrentThread()); | 250 DCHECK(task_runner_->BelongsToCurrentThread()); |
219 DCHECK_EQ(state_, STATE_INITIALIZING) << state_; | 251 DCHECK_EQ(state_, STATE_INITIALIZING) << state_; |
220 DCHECK(!init_cb_.is_null()); | 252 DCHECK(!init_cb_.is_null()); |
221 DCHECK(read_cb_.is_null()); | 253 DCHECK(read_cb_.is_null()); |
222 DCHECK(reset_cb_.is_null()); | 254 DCHECK(reset_cb_.is_null()); |
223 | 255 |
(...skipping 22 matching lines...) Expand all Loading... | |
246 | 278 |
247 template <DemuxerStream::Type StreamType> | 279 template <DemuxerStream::Type StreamType> |
248 void DecoderStream<StreamType>::SatisfyRead( | 280 void DecoderStream<StreamType>::SatisfyRead( |
249 Status status, | 281 Status status, |
250 const scoped_refptr<Output>& output) { | 282 const scoped_refptr<Output>& output) { |
251 DCHECK(!read_cb_.is_null()); | 283 DCHECK(!read_cb_.is_null()); |
252 base::ResetAndReturn(&read_cb_).Run(status, output); | 284 base::ResetAndReturn(&read_cb_).Run(status, output); |
253 } | 285 } |
254 | 286 |
255 template <DemuxerStream::Type StreamType> | 287 template <DemuxerStream::Type StreamType> |
256 void DecoderStream<StreamType>::AbortRead() { | |
257 // Abort read during pending reset. It is safe to fire the |read_cb_| directly | |
258 // instead of posting it because the renderer won't call into this class | |
259 // again when it's in kFlushing state. | |
260 // TODO(xhwang): Improve the resetting process to avoid this dependency on the | |
261 // caller. | |
262 DCHECK(!reset_cb_.is_null()); | |
263 SatisfyRead(ABORTED, NULL); | |
264 } | |
265 | |
266 template <DemuxerStream::Type StreamType> | |
267 void DecoderStream<StreamType>::Decode( | 288 void DecoderStream<StreamType>::Decode( |
268 const scoped_refptr<DecoderBuffer>& buffer) { | 289 const scoped_refptr<DecoderBuffer>& buffer) { |
269 FUNCTION_DVLOG(2); | 290 FUNCTION_DVLOG(2); |
270 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; | 291 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; |
271 DCHECK(!read_cb_.is_null()); | 292 DCHECK(CanDecodeAnotherBuffer()); |
272 DCHECK(reset_cb_.is_null()); | 293 DCHECK(reset_cb_.is_null()); |
273 DCHECK(stop_cb_.is_null()); | 294 DCHECK(stop_cb_.is_null()); |
274 DCHECK(buffer); | 295 DCHECK(buffer); |
275 | 296 |
276 int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size(); | 297 int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size(); |
277 | 298 |
278 TRACE_EVENT_ASYNC_BEGIN0("media", GetTraceString<StreamType>(), this); | 299 TRACE_EVENT_ASYNC_BEGIN0("media", GetTraceString<StreamType>(), this); |
300 ++pending_decode_requests_; | |
279 decoder_->Decode(buffer, | 301 decoder_->Decode(buffer, |
280 base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady, | 302 base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady, |
281 weak_factory_.GetWeakPtr(), | 303 weak_factory_.GetWeakPtr(), |
282 buffer_size)); | 304 buffer_size)); |
283 } | 305 } |
284 | 306 |
285 template <DemuxerStream::Type StreamType> | 307 template <DemuxerStream::Type StreamType> |
286 void DecoderStream<StreamType>::FlushDecoder() { | 308 void DecoderStream<StreamType>::FlushDecoder() { |
287 Decode(DecoderBuffer::CreateEOSBuffer()); | 309 if (pending_decode_requests_ == 0) |
xhwang
2014/04/25 00:36:03
This also depends on the fact that GVD doesn't hav
Sergey Ulanov
2014/04/26 00:59:29
Added condition in VideoDecoder comment requiring
xhwang
2014/04/29 20:01:26
By "decoding delay", I mean the case where VideoDe
Sergey Ulanov
2014/04/30 18:56:51
Ah, I see your point. Yes, decoders must never wai
| |
310 Decode(DecoderBuffer::CreateEOSBuffer()); | |
288 } | 311 } |
289 | 312 |
290 template <DemuxerStream::Type StreamType> | 313 template <DemuxerStream::Type StreamType> |
291 void DecoderStream<StreamType>::OnDecodeOutputReady( | 314 void DecoderStream<StreamType>::OnDecodeOutputReady( |
292 int buffer_size, | 315 int buffer_size, |
293 typename Decoder::Status status, | 316 typename Decoder::Status status, |
294 const scoped_refptr<Output>& output) { | 317 const scoped_refptr<Output>& output) { |
295 FUNCTION_DVLOG(2); | 318 FUNCTION_DVLOG(2) << status << " " << output; |
296 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; | 319 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || |
297 DCHECK(!read_cb_.is_null()); | 320 state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR) |
321 << state_; | |
298 DCHECK(stop_cb_.is_null()); | 322 DCHECK(stop_cb_.is_null()); |
299 DCHECK_EQ(status == Decoder::kOk, output != NULL); | 323 DCHECK_EQ(status == Decoder::kOk, output != NULL); |
324 DCHECK_GT(pending_decode_requests_, 0); | |
325 | |
326 --pending_decode_requests_; | |
300 | 327 |
301 TRACE_EVENT_ASYNC_END0("media", GetTraceString<StreamType>(), this); | 328 TRACE_EVENT_ASYNC_END0("media", GetTraceString<StreamType>(), this); |
302 | 329 |
330 if (state_ == STATE_ERROR) | |
xhwang
2014/04/25 00:36:03
DCHECK(!read_cb_.is_null())?
Sergey Ulanov
2014/04/26 00:59:29
I think you meant "DCHECK(read_cb_.is_null())"
Do
| |
331 return; | |
332 | |
303 if (status == Decoder::kDecodeError) { | 333 if (status == Decoder::kDecodeError) { |
304 state_ = STATE_ERROR; | 334 state_ = STATE_ERROR; |
305 SatisfyRead(DECODE_ERROR, NULL); | 335 error_ = DECODE_ERROR; |
xhwang
2014/04/25 00:36:03
Shall we clear the ready_outputs_ in case of error
Sergey Ulanov
2014/04/26 00:59:29
Done.
| |
336 if (!read_cb_.is_null()) | |
337 SatisfyRead(DECODE_ERROR, NULL); | |
306 return; | 338 return; |
307 } | 339 } |
308 | 340 |
309 if (status == Decoder::kDecryptError) { | 341 if (status == Decoder::kDecryptError) { |
310 state_ = STATE_ERROR; | 342 state_ = STATE_ERROR; |
311 SatisfyRead(DECRYPT_ERROR, NULL); | 343 error_ = DECRYPT_ERROR; |
xhwang
2014/04/25 00:36:03
ditto
Sergey Ulanov
2014/04/26 00:59:29
Done.
| |
344 if (!read_cb_.is_null()) | |
345 SatisfyRead(DECRYPT_ERROR, NULL); | |
312 return; | 346 return; |
313 } | 347 } |
314 | 348 |
315 if (status == Decoder::kAborted) { | 349 if (status == Decoder::kAborted) { |
316 SatisfyRead(ABORTED, NULL); | 350 if (!read_cb_.is_null()) |
xhwang
2014/04/25 00:36:03
kAborted must be a result of Reset(). In Reset() c
Sergey Ulanov
2014/04/26 00:59:29
There are some tests that return kAborted from dec
xhwang
2014/04/29 20:01:26
You are right. kAborted can also be a result of De
| |
351 SatisfyRead(ABORTED, NULL); | |
317 return; | 352 return; |
318 } | 353 } |
319 | 354 |
320 // Any successful decode counts! | 355 // Any successful decode counts! |
321 if (buffer_size > 0) { | 356 if (buffer_size > 0) { |
322 StreamTraits::ReportStatistics(statistics_cb_, buffer_size); | 357 StreamTraits::ReportStatistics(statistics_cb_, buffer_size); |
323 } | 358 } |
324 | 359 |
325 // Drop decoding result if Reset() was called during decoding. | 360 // Drop decoding result if Reset() was called during decoding. |
326 // The resetting process will be handled when the decoder is reset. | 361 // The resetting process will be handled when the decoder is reset. |
327 if (!reset_cb_.is_null()) { | 362 if (!reset_cb_.is_null()) |
328 AbortRead(); | |
329 return; | 363 return; |
330 } | |
331 | 364 |
332 // Decoder flushed. Reinitialize the decoder. | 365 // Decoder flushed. Reinitialize the decoder. |
333 if (state_ == STATE_FLUSHING_DECODER && | 366 if (state_ == STATE_FLUSHING_DECODER && |
334 status == Decoder::kOk && output->end_of_stream()) { | 367 status == Decoder::kOk && output->end_of_stream()) { |
335 ReinitializeDecoder(); | 368 ReinitializeDecoder(); |
336 return; | 369 return; |
337 } | 370 } |
338 | 371 |
339 if (status == Decoder::kNotEnoughData) { | 372 if (status == Decoder::kNotEnoughData) { |
340 if (state_ == STATE_NORMAL) | 373 if (state_ == STATE_NORMAL) |
341 ReadFromDemuxerStream(); | 374 ReadFromDemuxerStream(); |
342 else if (state_ == STATE_FLUSHING_DECODER) | 375 else if (state_ == STATE_FLUSHING_DECODER) |
343 FlushDecoder(); | 376 FlushDecoder(); |
344 return; | 377 return; |
345 } | 378 } |
346 | 379 |
347 DCHECK(output); | 380 DCHECK(output); |
348 SatisfyRead(OK, output); | 381 |
382 // Store decoded output. | |
383 ready_outputs_.push_back(output); | |
384 scoped_refptr<Output> extra_output; | |
385 while ((extra_output = decoder_->GetDecodeOutput()) != NULL) { | |
386 ready_outputs_.push_back(extra_output); | |
387 } | |
388 | |
389 // Satisfy outstanding read request, if any. | |
390 if (!read_cb_.is_null()) { | |
391 scoped_refptr<Output> read_result = ready_outputs_.front(); | |
392 ready_outputs_.pop_front(); | |
393 SatisfyRead(OK, output); | |
394 } | |
349 } | 395 } |
350 | 396 |
351 template <DemuxerStream::Type StreamType> | 397 template <DemuxerStream::Type StreamType> |
352 void DecoderStream<StreamType>::ReadFromDemuxerStream() { | 398 void DecoderStream<StreamType>::ReadFromDemuxerStream() { |
353 FUNCTION_DVLOG(2); | 399 FUNCTION_DVLOG(2); |
354 DCHECK_EQ(state_, STATE_NORMAL) << state_; | 400 DCHECK_EQ(state_, STATE_NORMAL) << state_; |
355 DCHECK(!read_cb_.is_null()); | 401 DCHECK(CanDecodeAnotherBuffer()); |
356 DCHECK(reset_cb_.is_null()); | 402 DCHECK(reset_cb_.is_null()); |
357 DCHECK(stop_cb_.is_null()); | 403 DCHECK(stop_cb_.is_null()); |
358 | 404 |
359 state_ = STATE_PENDING_DEMUXER_READ; | 405 state_ = STATE_PENDING_DEMUXER_READ; |
360 stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady, | 406 stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady, |
361 weak_factory_.GetWeakPtr())); | 407 weak_factory_.GetWeakPtr())); |
362 } | 408 } |
363 | 409 |
364 template <DemuxerStream::Type StreamType> | 410 template <DemuxerStream::Type StreamType> |
365 void DecoderStream<StreamType>::OnBufferReady( | 411 void DecoderStream<StreamType>::OnBufferReady( |
366 DemuxerStream::Status status, | 412 DemuxerStream::Status status, |
367 const scoped_refptr<DecoderBuffer>& buffer) { | 413 const scoped_refptr<DecoderBuffer>& buffer) { |
368 FUNCTION_DVLOG(2) << ": " << status; | 414 FUNCTION_DVLOG(2) << ": " << status; |
369 DCHECK(task_runner_->BelongsToCurrentThread()); | 415 DCHECK(task_runner_->BelongsToCurrentThread()); |
370 DCHECK_EQ(state_, STATE_PENDING_DEMUXER_READ) << state_; | 416 DCHECK(state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR || |
417 state_ == STATE_STOPPED) | |
418 << state_; | |
371 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status; | 419 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status; |
372 DCHECK(!read_cb_.is_null()); | |
373 DCHECK(stop_cb_.is_null()); | 420 DCHECK(stop_cb_.is_null()); |
374 | 421 |
422 // Decoding has been stopped (e.g due to an error). | |
423 if (state_ != STATE_PENDING_DEMUXER_READ) | |
xhwang
2014/04/25 00:36:03
Can we
DCHECK_EQ(state_, STATE_ERROR);
DCHECK(rea
Sergey Ulanov
2014/04/26 00:59:29
Done. state_ can be either STATE_ERROR or STATE_ST
| |
424 return; | |
425 | |
375 state_ = STATE_NORMAL; | 426 state_ = STATE_NORMAL; |
376 | 427 |
377 if (status == DemuxerStream::kConfigChanged) { | 428 if (status == DemuxerStream::kConfigChanged) { |
378 FUNCTION_DVLOG(2) << ": " << "ConfigChanged"; | 429 FUNCTION_DVLOG(2) << ": " << "ConfigChanged"; |
379 DCHECK(stream_->SupportsConfigChanges()); | 430 DCHECK(stream_->SupportsConfigChanges()); |
380 | 431 |
381 if (!config_change_observer_cb_.is_null()) | 432 if (!config_change_observer_cb_.is_null()) |
382 config_change_observer_cb_.Run(); | 433 config_change_observer_cb_.Run(); |
383 | 434 |
384 state_ = STATE_FLUSHING_DECODER; | 435 state_ = STATE_FLUSHING_DECODER; |
385 if (!reset_cb_.is_null()) { | 436 if (!reset_cb_.is_null()) { |
386 AbortRead(); | |
387 // If we are using DecryptingDemuxerStream, we already called DDS::Reset() | 437 // If we are using DecryptingDemuxerStream, we already called DDS::Reset() |
388 // which will continue the resetting process in it's callback. | 438 // which will continue the resetting process in it's callback. |
389 if (!decrypting_demuxer_stream_) | 439 if (!decrypting_demuxer_stream_) |
390 Reset(base::ResetAndReturn(&reset_cb_)); | 440 Reset(base::ResetAndReturn(&reset_cb_)); |
391 // Reinitialization will continue after Reset() is done. | 441 // Reinitialization will continue after Reset() is done. |
392 } else { | 442 } else { |
393 FlushDecoder(); | 443 FlushDecoder(); |
394 } | 444 } |
395 return; | 445 return; |
396 } | 446 } |
397 | 447 |
398 if (!reset_cb_.is_null()) { | 448 if (!reset_cb_.is_null()) { |
399 AbortRead(); | |
400 // If we are using DecryptingDemuxerStream, we already called DDS::Reset() | 449 // If we are using DecryptingDemuxerStream, we already called DDS::Reset() |
401 // which will continue the resetting process in it's callback. | 450 // which will continue the resetting process in it's callback. |
402 if (!decrypting_demuxer_stream_) | 451 if (!decrypting_demuxer_stream_) |
403 Reset(base::ResetAndReturn(&reset_cb_)); | 452 Reset(base::ResetAndReturn(&reset_cb_)); |
404 return; | 453 return; |
405 } | 454 } |
406 | 455 |
407 if (status == DemuxerStream::kAborted) { | 456 if (status == DemuxerStream::kAborted) { |
408 SatisfyRead(DEMUXER_READ_ABORTED, NULL); | 457 SatisfyRead(DEMUXER_READ_ABORTED, NULL); |
409 return; | 458 return; |
410 } | 459 } |
411 | 460 |
412 if (!splice_observer_cb_.is_null() && !buffer->end_of_stream()) { | 461 if (!splice_observer_cb_.is_null() && !buffer->end_of_stream()) { |
413 const bool has_splice_ts = buffer->splice_timestamp() != kNoTimestamp(); | 462 const bool has_splice_ts = buffer->splice_timestamp() != kNoTimestamp(); |
414 if (active_splice_ || has_splice_ts) { | 463 if (active_splice_ || has_splice_ts) { |
415 splice_observer_cb_.Run(buffer->splice_timestamp()); | 464 splice_observer_cb_.Run(buffer->splice_timestamp()); |
416 active_splice_ = has_splice_ts; | 465 active_splice_ = has_splice_ts; |
417 } | 466 } |
418 } | 467 } |
419 | 468 |
420 DCHECK(status == DemuxerStream::kOk) << status; | 469 DCHECK(status == DemuxerStream::kOk) << status; |
421 Decode(buffer); | 470 Decode(buffer); |
471 | |
472 // Read more data if the decoder supports multiple parallel decoding requests. | |
473 if (CanDecodeAnotherBuffer() && !buffer->end_of_stream()) | |
474 ReadFromDemuxerStream(); | |
422 } | 475 } |
423 | 476 |
424 template <DemuxerStream::Type StreamType> | 477 template <DemuxerStream::Type StreamType> |
425 void DecoderStream<StreamType>::ReinitializeDecoder() { | 478 void DecoderStream<StreamType>::ReinitializeDecoder() { |
426 FUNCTION_DVLOG(2); | 479 FUNCTION_DVLOG(2); |
427 DCHECK(task_runner_->BelongsToCurrentThread()); | 480 DCHECK(task_runner_->BelongsToCurrentThread()); |
428 DCHECK_EQ(state_, STATE_FLUSHING_DECODER) << state_; | 481 DCHECK_EQ(state_, STATE_FLUSHING_DECODER) << state_; |
482 DCHECK_EQ(pending_decode_requests_, 0); | |
429 | 483 |
430 DCHECK(StreamTraits::GetDecoderConfig(*stream_).IsValidConfig()); | 484 DCHECK(StreamTraits::GetDecoderConfig(*stream_).IsValidConfig()); |
431 state_ = STATE_REINITIALIZING_DECODER; | 485 state_ = STATE_REINITIALIZING_DECODER; |
432 decoder_->Initialize( | 486 decoder_->Initialize( |
433 StreamTraits::GetDecoderConfig(*stream_), | 487 StreamTraits::GetDecoderConfig(*stream_), |
434 base::Bind(&DecoderStream<StreamType>::OnDecoderReinitialized, | 488 base::Bind(&DecoderStream<StreamType>::OnDecoderReinitialized, |
435 weak_factory_.GetWeakPtr())); | 489 weak_factory_.GetWeakPtr())); |
436 } | 490 } |
437 | 491 |
438 template <DemuxerStream::Type StreamType> | 492 template <DemuxerStream::Type StreamType> |
439 void DecoderStream<StreamType>::OnDecoderReinitialized(PipelineStatus status) { | 493 void DecoderStream<StreamType>::OnDecoderReinitialized(PipelineStatus status) { |
440 FUNCTION_DVLOG(2); | 494 FUNCTION_DVLOG(2); |
441 DCHECK(task_runner_->BelongsToCurrentThread()); | 495 DCHECK(task_runner_->BelongsToCurrentThread()); |
442 DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER) << state_; | 496 DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER) << state_; |
443 DCHECK(stop_cb_.is_null()); | 497 DCHECK(stop_cb_.is_null()); |
444 | 498 |
445 // ReinitializeDecoder() can be called in two cases: | 499 // ReinitializeDecoder() can be called in two cases: |
446 // 1, Flushing decoder finished (see OnDecodeOutputReady()). | 500 // 1, Flushing decoder finished (see OnDecodeOutputReady()). |
447 // 2, Reset() was called during flushing decoder (see OnDecoderReset()). | 501 // 2, Reset() was called during flushing decoder (see OnDecoderReset()). |
448 // Also, Reset() can be called during pending ReinitializeDecoder(). | 502 // Also, Reset() can be called during pending ReinitializeDecoder(). |
449 // This function needs to handle them all! | 503 // This function needs to handle them all! |
450 | 504 |
451 state_ = (status == PIPELINE_OK) ? STATE_NORMAL : STATE_ERROR; | 505 state_ = (status == PIPELINE_OK) ? STATE_NORMAL : STATE_ERROR; |
452 | 506 |
453 if (!reset_cb_.is_null()) { | 507 if (!reset_cb_.is_null()) { |
454 if (!read_cb_.is_null()) | |
455 AbortRead(); | |
456 base::ResetAndReturn(&reset_cb_).Run(); | 508 base::ResetAndReturn(&reset_cb_).Run(); |
509 return; | |
457 } | 510 } |
458 | 511 |
459 if (read_cb_.is_null()) | 512 if (read_cb_.is_null()) |
460 return; | 513 return; |
461 | 514 |
462 if (state_ == STATE_ERROR) { | 515 if (state_ == STATE_ERROR) { |
463 SatisfyRead(DECODE_ERROR, NULL); | 516 SatisfyRead(DECODE_ERROR, NULL); |
464 return; | 517 return; |
465 } | 518 } |
466 | 519 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
514 decrypting_demuxer_stream_.reset(); | 567 decrypting_demuxer_stream_.reset(); |
515 // Post |stop_cb_| because pending |read_cb_| and/or |reset_cb_| are also | 568 // Post |stop_cb_| because pending |read_cb_| and/or |reset_cb_| are also |
516 // posted in Stop(). | 569 // posted in Stop(). |
517 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); | 570 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); |
518 } | 571 } |
519 | 572 |
520 template class DecoderStream<DemuxerStream::VIDEO>; | 573 template class DecoderStream<DemuxerStream::VIDEO>; |
521 template class DecoderStream<DemuxerStream::AUDIO>; | 574 template class DecoderStream<DemuxerStream::AUDIO>; |
522 | 575 |
523 } // namespace media | 576 } // namespace media |
OLD | NEW |