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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 stream_(NULL), | 48 stream_(NULL), |
49 decoder_selector_( | 49 decoder_selector_( |
50 new DecoderSelector<StreamType>(task_runner, | 50 new DecoderSelector<StreamType>(task_runner, |
51 decoders.Pass(), | 51 decoders.Pass(), |
52 set_decryptor_ready_cb)), | 52 set_decryptor_ready_cb)), |
53 active_splice_(false), | 53 active_splice_(false), |
| 54 pending_decode_requests_(0), |
54 weak_factory_(this) {} | 55 weak_factory_(this) {} |
55 | 56 |
56 template <DemuxerStream::Type StreamType> | 57 template <DemuxerStream::Type StreamType> |
57 DecoderStream<StreamType>::~DecoderStream() { | 58 DecoderStream<StreamType>::~DecoderStream() { |
58 DCHECK(state_ == STATE_UNINITIALIZED || state_ == STATE_STOPPED) << state_; | 59 DCHECK(state_ == STATE_UNINITIALIZED || state_ == STATE_STOPPED) << state_; |
59 } | 60 } |
60 | 61 |
61 template <DemuxerStream::Type StreamType> | 62 template <DemuxerStream::Type StreamType> |
62 void DecoderStream<StreamType>::Initialize(DemuxerStream* stream, | 63 void DecoderStream<StreamType>::Initialize(DemuxerStream* stream, |
63 const StatisticsCB& statistics_cb, | 64 const StatisticsCB& statistics_cb, |
(...skipping 14 matching lines...) Expand all Loading... |
78 stream, | 79 stream, |
79 base::Bind(&DecoderStream<StreamType>::OnDecoderSelected, | 80 base::Bind(&DecoderStream<StreamType>::OnDecoderSelected, |
80 weak_factory_.GetWeakPtr())); | 81 weak_factory_.GetWeakPtr())); |
81 } | 82 } |
82 | 83 |
83 template <DemuxerStream::Type StreamType> | 84 template <DemuxerStream::Type StreamType> |
84 void DecoderStream<StreamType>::Read(const ReadCB& read_cb) { | 85 void DecoderStream<StreamType>::Read(const ReadCB& read_cb) { |
85 FUNCTION_DVLOG(2); | 86 FUNCTION_DVLOG(2); |
86 DCHECK(task_runner_->BelongsToCurrentThread()); | 87 DCHECK(task_runner_->BelongsToCurrentThread()); |
87 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || | 88 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || |
88 state_ == STATE_ERROR) << state_; | 89 state_ == STATE_ERROR || state_ == STATE_REINITIALIZING_DECODER || |
| 90 state_ == STATE_PENDING_DEMUXER_READ) |
| 91 << state_; |
89 // No two reads in the flight at any time. | 92 // No two reads in the flight at any time. |
90 DCHECK(read_cb_.is_null()); | 93 DCHECK(read_cb_.is_null()); |
91 // No read during resetting or stopping process. | 94 // No read during resetting or stopping process. |
92 DCHECK(reset_cb_.is_null()); | 95 DCHECK(reset_cb_.is_null()); |
93 DCHECK(stop_cb_.is_null()); | 96 DCHECK(stop_cb_.is_null()); |
94 | 97 |
| 98 read_cb_ = read_cb; |
| 99 |
95 if (state_ == STATE_ERROR) { | 100 if (state_ == STATE_ERROR) { |
96 task_runner_->PostTask(FROM_HERE, base::Bind( | 101 task_runner_->PostTask(FROM_HERE, |
97 read_cb, DECODE_ERROR, scoped_refptr<Output>())); | 102 base::Bind(base::ResetAndReturn(&read_cb_), |
| 103 DECODE_ERROR, |
| 104 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 (!CanDecodeMore()) |
| 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>::CanDecodeMore() 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 int num_decodes = |
| 234 static_cast<int>(ready_outputs_.size()) + pending_decode_requests_; |
| 235 return num_decodes < decoder_->GetMaxDecodeRequests(); |
| 236 } |
| 237 |
| 238 template <> |
| 239 bool DecoderStream<DemuxerStream::AUDIO>::CanDecodeMore() const { |
| 240 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 241 return !pending_decode_requests_ && ready_outputs_.empty(); |
| 242 } |
| 243 |
| 244 template <DemuxerStream::Type StreamType> |
214 void DecoderStream<StreamType>::OnDecoderSelected( | 245 void DecoderStream<StreamType>::OnDecoderSelected( |
215 scoped_ptr<Decoder> selected_decoder, | 246 scoped_ptr<Decoder> selected_decoder, |
216 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { | 247 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { |
217 FUNCTION_DVLOG(2); | 248 FUNCTION_DVLOG(2); |
218 DCHECK(task_runner_->BelongsToCurrentThread()); | 249 DCHECK(task_runner_->BelongsToCurrentThread()); |
219 DCHECK_EQ(state_, STATE_INITIALIZING) << state_; | 250 DCHECK_EQ(state_, STATE_INITIALIZING) << state_; |
220 DCHECK(!init_cb_.is_null()); | 251 DCHECK(!init_cb_.is_null()); |
221 DCHECK(read_cb_.is_null()); | 252 DCHECK(read_cb_.is_null()); |
222 DCHECK(reset_cb_.is_null()); | 253 DCHECK(reset_cb_.is_null()); |
223 | 254 |
(...skipping 22 matching lines...) Expand all Loading... |
246 | 277 |
247 template <DemuxerStream::Type StreamType> | 278 template <DemuxerStream::Type StreamType> |
248 void DecoderStream<StreamType>::SatisfyRead( | 279 void DecoderStream<StreamType>::SatisfyRead( |
249 Status status, | 280 Status status, |
250 const scoped_refptr<Output>& output) { | 281 const scoped_refptr<Output>& output) { |
251 DCHECK(!read_cb_.is_null()); | 282 DCHECK(!read_cb_.is_null()); |
252 base::ResetAndReturn(&read_cb_).Run(status, output); | 283 base::ResetAndReturn(&read_cb_).Run(status, output); |
253 } | 284 } |
254 | 285 |
255 template <DemuxerStream::Type StreamType> | 286 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( | 287 void DecoderStream<StreamType>::Decode( |
268 const scoped_refptr<DecoderBuffer>& buffer) { | 288 const scoped_refptr<DecoderBuffer>& buffer) { |
269 FUNCTION_DVLOG(2); | 289 FUNCTION_DVLOG(2); |
270 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; | 290 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; |
271 DCHECK(!read_cb_.is_null()); | 291 DCHECK(CanDecodeMore()); |
272 DCHECK(reset_cb_.is_null()); | 292 DCHECK(reset_cb_.is_null()); |
273 DCHECK(stop_cb_.is_null()); | 293 DCHECK(stop_cb_.is_null()); |
274 DCHECK(buffer); | 294 DCHECK(buffer); |
275 | 295 |
276 int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size(); | 296 int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size(); |
277 | 297 |
278 TRACE_EVENT_ASYNC_BEGIN0("media", GetTraceString<StreamType>(), this); | 298 TRACE_EVENT_ASYNC_BEGIN0("media", GetTraceString<StreamType>(), this); |
| 299 ++pending_decode_requests_; |
279 decoder_->Decode(buffer, | 300 decoder_->Decode(buffer, |
280 base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady, | 301 base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady, |
281 weak_factory_.GetWeakPtr(), | 302 weak_factory_.GetWeakPtr(), |
282 buffer_size)); | 303 buffer_size)); |
283 } | 304 } |
284 | 305 |
285 template <DemuxerStream::Type StreamType> | 306 template <DemuxerStream::Type StreamType> |
286 void DecoderStream<StreamType>::FlushDecoder() { | 307 void DecoderStream<StreamType>::FlushDecoder() { |
287 Decode(DecoderBuffer::CreateEOSBuffer()); | 308 if (pending_decode_requests_ == 0) |
| 309 Decode(DecoderBuffer::CreateEOSBuffer()); |
288 } | 310 } |
289 | 311 |
290 template <DemuxerStream::Type StreamType> | 312 template <DemuxerStream::Type StreamType> |
291 void DecoderStream<StreamType>::OnDecodeOutputReady( | 313 void DecoderStream<StreamType>::OnDecodeOutputReady( |
292 int buffer_size, | 314 int buffer_size, |
293 typename Decoder::Status status, | 315 typename Decoder::Status status, |
294 const scoped_refptr<Output>& output) { | 316 const scoped_refptr<Output>& output) { |
295 FUNCTION_DVLOG(2); | 317 FUNCTION_DVLOG(2) << status << " " << output; |
296 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; | 318 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || |
297 DCHECK(!read_cb_.is_null()); | 319 state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR) |
| 320 << state_; |
298 DCHECK(stop_cb_.is_null()); | 321 DCHECK(stop_cb_.is_null()); |
299 DCHECK_EQ(status == Decoder::kOk, output != NULL); | 322 DCHECK_EQ(status == Decoder::kOk, output != NULL); |
| 323 DCHECK_GT(pending_decode_requests_, 0); |
| 324 |
| 325 --pending_decode_requests_; |
300 | 326 |
301 TRACE_EVENT_ASYNC_END0("media", GetTraceString<StreamType>(), this); | 327 TRACE_EVENT_ASYNC_END0("media", GetTraceString<StreamType>(), this); |
302 | 328 |
| 329 if (state_ == STATE_ERROR) { |
| 330 DCHECK(read_cb_.is_null()); |
| 331 return; |
| 332 } |
| 333 |
303 if (status == Decoder::kDecodeError) { | 334 if (status == Decoder::kDecodeError) { |
304 state_ = STATE_ERROR; | 335 state_ = STATE_ERROR; |
305 SatisfyRead(DECODE_ERROR, NULL); | 336 ready_outputs_.clear(); |
| 337 if (!read_cb_.is_null()) |
| 338 SatisfyRead(DECODE_ERROR, NULL); |
306 return; | 339 return; |
307 } | 340 } |
308 | 341 |
309 if (status == Decoder::kDecryptError) { | 342 if (status == Decoder::kDecryptError) { |
310 state_ = STATE_ERROR; | 343 state_ = STATE_ERROR; |
311 SatisfyRead(DECRYPT_ERROR, NULL); | 344 ready_outputs_.clear(); |
| 345 if (!read_cb_.is_null()) |
| 346 SatisfyRead(DECRYPT_ERROR, NULL); |
312 return; | 347 return; |
313 } | 348 } |
314 | 349 |
315 if (status == Decoder::kAborted) { | 350 if (status == Decoder::kAborted) { |
316 SatisfyRead(ABORTED, NULL); | 351 if (!read_cb_.is_null()) |
| 352 SatisfyRead(ABORTED, NULL); |
317 return; | 353 return; |
318 } | 354 } |
319 | 355 |
320 // Any successful decode counts! | 356 // Any successful decode counts! |
321 if (buffer_size > 0) { | 357 if (buffer_size > 0) { |
322 StreamTraits::ReportStatistics(statistics_cb_, buffer_size); | 358 StreamTraits::ReportStatistics(statistics_cb_, buffer_size); |
323 } | 359 } |
324 | 360 |
325 // Drop decoding result if Reset() was called during decoding. | 361 // Drop decoding result if Reset() was called during decoding. |
326 // The resetting process will be handled when the decoder is reset. | 362 // The resetting process will be handled when the decoder is reset. |
327 if (!reset_cb_.is_null()) { | 363 if (!reset_cb_.is_null()) |
328 AbortRead(); | |
329 return; | 364 return; |
330 } | |
331 | 365 |
332 // Decoder flushed. Reinitialize the decoder. | 366 // Decoder flushed. Reinitialize the decoder. |
333 if (state_ == STATE_FLUSHING_DECODER && | 367 if (state_ == STATE_FLUSHING_DECODER && |
334 status == Decoder::kOk && output->end_of_stream()) { | 368 status == Decoder::kOk && output->end_of_stream()) { |
335 ReinitializeDecoder(); | 369 ReinitializeDecoder(); |
336 return; | 370 return; |
337 } | 371 } |
338 | 372 |
339 if (status == Decoder::kNotEnoughData) { | 373 if (status == Decoder::kNotEnoughData) { |
340 if (state_ == STATE_NORMAL) | 374 if (state_ == STATE_NORMAL) |
341 ReadFromDemuxerStream(); | 375 ReadFromDemuxerStream(); |
342 else if (state_ == STATE_FLUSHING_DECODER) | 376 else if (state_ == STATE_FLUSHING_DECODER) |
343 FlushDecoder(); | 377 FlushDecoder(); |
344 return; | 378 return; |
345 } | 379 } |
346 | 380 |
347 DCHECK(output); | 381 DCHECK(output); |
348 SatisfyRead(OK, output); | 382 |
| 383 // Store decoded output. |
| 384 ready_outputs_.push_back(output); |
| 385 scoped_refptr<Output> extra_output; |
| 386 while ((extra_output = decoder_->GetDecodeOutput()) != NULL) { |
| 387 ready_outputs_.push_back(extra_output); |
| 388 } |
| 389 |
| 390 // Satisfy outstanding read request, if any. |
| 391 if (!read_cb_.is_null()) { |
| 392 scoped_refptr<Output> read_result = ready_outputs_.front(); |
| 393 ready_outputs_.pop_front(); |
| 394 SatisfyRead(OK, output); |
| 395 } |
349 } | 396 } |
350 | 397 |
351 template <DemuxerStream::Type StreamType> | 398 template <DemuxerStream::Type StreamType> |
352 void DecoderStream<StreamType>::ReadFromDemuxerStream() { | 399 void DecoderStream<StreamType>::ReadFromDemuxerStream() { |
353 FUNCTION_DVLOG(2); | 400 FUNCTION_DVLOG(2); |
354 DCHECK_EQ(state_, STATE_NORMAL) << state_; | 401 DCHECK_EQ(state_, STATE_NORMAL) << state_; |
355 DCHECK(!read_cb_.is_null()); | 402 DCHECK(CanDecodeMore()); |
356 DCHECK(reset_cb_.is_null()); | 403 DCHECK(reset_cb_.is_null()); |
357 DCHECK(stop_cb_.is_null()); | 404 DCHECK(stop_cb_.is_null()); |
358 | 405 |
359 state_ = STATE_PENDING_DEMUXER_READ; | 406 state_ = STATE_PENDING_DEMUXER_READ; |
360 stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady, | 407 stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady, |
361 weak_factory_.GetWeakPtr())); | 408 weak_factory_.GetWeakPtr())); |
362 } | 409 } |
363 | 410 |
364 template <DemuxerStream::Type StreamType> | 411 template <DemuxerStream::Type StreamType> |
365 void DecoderStream<StreamType>::OnBufferReady( | 412 void DecoderStream<StreamType>::OnBufferReady( |
366 DemuxerStream::Status status, | 413 DemuxerStream::Status status, |
367 const scoped_refptr<DecoderBuffer>& buffer) { | 414 const scoped_refptr<DecoderBuffer>& buffer) { |
368 FUNCTION_DVLOG(2) << ": " << status; | 415 FUNCTION_DVLOG(2) << ": " << status; |
369 DCHECK(task_runner_->BelongsToCurrentThread()); | 416 DCHECK(task_runner_->BelongsToCurrentThread()); |
370 DCHECK_EQ(state_, STATE_PENDING_DEMUXER_READ) << state_; | 417 DCHECK(state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR || |
| 418 state_ == STATE_STOPPED) |
| 419 << state_; |
371 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status; | 420 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status; |
372 DCHECK(!read_cb_.is_null()); | |
373 DCHECK(stop_cb_.is_null()); | 421 DCHECK(stop_cb_.is_null()); |
374 | 422 |
| 423 // Decoding has been stopped (e.g due to an error). |
| 424 if (state_ != STATE_PENDING_DEMUXER_READ) { |
| 425 DCHECK(state_ == STATE_ERROR || state_ == STATE_STOPPED); |
| 426 DCHECK(read_cb_.is_null()); |
| 427 return; |
| 428 } |
| 429 |
375 state_ = STATE_NORMAL; | 430 state_ = STATE_NORMAL; |
376 | 431 |
377 if (status == DemuxerStream::kConfigChanged) { | 432 if (status == DemuxerStream::kConfigChanged) { |
378 FUNCTION_DVLOG(2) << ": " << "ConfigChanged"; | 433 FUNCTION_DVLOG(2) << ": " << "ConfigChanged"; |
379 DCHECK(stream_->SupportsConfigChanges()); | 434 DCHECK(stream_->SupportsConfigChanges()); |
380 | 435 |
381 if (!config_change_observer_cb_.is_null()) | 436 if (!config_change_observer_cb_.is_null()) |
382 config_change_observer_cb_.Run(); | 437 config_change_observer_cb_.Run(); |
383 | 438 |
384 state_ = STATE_FLUSHING_DECODER; | 439 state_ = STATE_FLUSHING_DECODER; |
385 if (!reset_cb_.is_null()) { | 440 if (!reset_cb_.is_null()) { |
386 AbortRead(); | |
387 // If we are using DecryptingDemuxerStream, we already called DDS::Reset() | 441 // If we are using DecryptingDemuxerStream, we already called DDS::Reset() |
388 // which will continue the resetting process in it's callback. | 442 // which will continue the resetting process in it's callback. |
389 if (!decrypting_demuxer_stream_) | 443 if (!decrypting_demuxer_stream_) |
390 Reset(base::ResetAndReturn(&reset_cb_)); | 444 Reset(base::ResetAndReturn(&reset_cb_)); |
391 // Reinitialization will continue after Reset() is done. | 445 // Reinitialization will continue after Reset() is done. |
392 } else { | 446 } else { |
393 FlushDecoder(); | 447 FlushDecoder(); |
394 } | 448 } |
395 return; | 449 return; |
396 } | 450 } |
397 | 451 |
398 if (!reset_cb_.is_null()) { | 452 if (!reset_cb_.is_null()) { |
399 AbortRead(); | |
400 // If we are using DecryptingDemuxerStream, we already called DDS::Reset() | 453 // If we are using DecryptingDemuxerStream, we already called DDS::Reset() |
401 // which will continue the resetting process in it's callback. | 454 // which will continue the resetting process in it's callback. |
402 if (!decrypting_demuxer_stream_) | 455 if (!decrypting_demuxer_stream_) |
403 Reset(base::ResetAndReturn(&reset_cb_)); | 456 Reset(base::ResetAndReturn(&reset_cb_)); |
404 return; | 457 return; |
405 } | 458 } |
406 | 459 |
407 if (status == DemuxerStream::kAborted) { | 460 if (status == DemuxerStream::kAborted) { |
408 SatisfyRead(DEMUXER_READ_ABORTED, NULL); | 461 SatisfyRead(DEMUXER_READ_ABORTED, NULL); |
409 return; | 462 return; |
410 } | 463 } |
411 | 464 |
412 if (!splice_observer_cb_.is_null() && !buffer->end_of_stream()) { | 465 if (!splice_observer_cb_.is_null() && !buffer->end_of_stream()) { |
413 const bool has_splice_ts = buffer->splice_timestamp() != kNoTimestamp(); | 466 const bool has_splice_ts = buffer->splice_timestamp() != kNoTimestamp(); |
414 if (active_splice_ || has_splice_ts) { | 467 if (active_splice_ || has_splice_ts) { |
415 splice_observer_cb_.Run(buffer->splice_timestamp()); | 468 splice_observer_cb_.Run(buffer->splice_timestamp()); |
416 active_splice_ = has_splice_ts; | 469 active_splice_ = has_splice_ts; |
417 } | 470 } |
418 } | 471 } |
419 | 472 |
420 DCHECK(status == DemuxerStream::kOk) << status; | 473 DCHECK(status == DemuxerStream::kOk) << status; |
421 Decode(buffer); | 474 Decode(buffer); |
| 475 |
| 476 // Read more data if the decoder supports multiple parallel decoding requests. |
| 477 if (CanDecodeMore() && !buffer->end_of_stream()) |
| 478 ReadFromDemuxerStream(); |
422 } | 479 } |
423 | 480 |
424 template <DemuxerStream::Type StreamType> | 481 template <DemuxerStream::Type StreamType> |
425 void DecoderStream<StreamType>::ReinitializeDecoder() { | 482 void DecoderStream<StreamType>::ReinitializeDecoder() { |
426 FUNCTION_DVLOG(2); | 483 FUNCTION_DVLOG(2); |
427 DCHECK(task_runner_->BelongsToCurrentThread()); | 484 DCHECK(task_runner_->BelongsToCurrentThread()); |
428 DCHECK_EQ(state_, STATE_FLUSHING_DECODER) << state_; | 485 DCHECK_EQ(state_, STATE_FLUSHING_DECODER) << state_; |
| 486 DCHECK_EQ(pending_decode_requests_, 0); |
429 | 487 |
430 DCHECK(StreamTraits::GetDecoderConfig(*stream_).IsValidConfig()); | 488 DCHECK(StreamTraits::GetDecoderConfig(*stream_).IsValidConfig()); |
431 state_ = STATE_REINITIALIZING_DECODER; | 489 state_ = STATE_REINITIALIZING_DECODER; |
432 decoder_->Initialize( | 490 decoder_->Initialize( |
433 StreamTraits::GetDecoderConfig(*stream_), | 491 StreamTraits::GetDecoderConfig(*stream_), |
434 base::Bind(&DecoderStream<StreamType>::OnDecoderReinitialized, | 492 base::Bind(&DecoderStream<StreamType>::OnDecoderReinitialized, |
435 weak_factory_.GetWeakPtr())); | 493 weak_factory_.GetWeakPtr())); |
436 } | 494 } |
437 | 495 |
438 template <DemuxerStream::Type StreamType> | 496 template <DemuxerStream::Type StreamType> |
439 void DecoderStream<StreamType>::OnDecoderReinitialized(PipelineStatus status) { | 497 void DecoderStream<StreamType>::OnDecoderReinitialized(PipelineStatus status) { |
440 FUNCTION_DVLOG(2); | 498 FUNCTION_DVLOG(2); |
441 DCHECK(task_runner_->BelongsToCurrentThread()); | 499 DCHECK(task_runner_->BelongsToCurrentThread()); |
442 DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER) << state_; | 500 DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER) << state_; |
443 DCHECK(stop_cb_.is_null()); | 501 DCHECK(stop_cb_.is_null()); |
444 | 502 |
445 // ReinitializeDecoder() can be called in two cases: | 503 // ReinitializeDecoder() can be called in two cases: |
446 // 1, Flushing decoder finished (see OnDecodeOutputReady()). | 504 // 1, Flushing decoder finished (see OnDecodeOutputReady()). |
447 // 2, Reset() was called during flushing decoder (see OnDecoderReset()). | 505 // 2, Reset() was called during flushing decoder (see OnDecoderReset()). |
448 // Also, Reset() can be called during pending ReinitializeDecoder(). | 506 // Also, Reset() can be called during pending ReinitializeDecoder(). |
449 // This function needs to handle them all! | 507 // This function needs to handle them all! |
450 | 508 |
451 state_ = (status == PIPELINE_OK) ? STATE_NORMAL : STATE_ERROR; | 509 state_ = (status == PIPELINE_OK) ? STATE_NORMAL : STATE_ERROR; |
452 | 510 |
453 if (!reset_cb_.is_null()) { | 511 if (!reset_cb_.is_null()) { |
454 if (!read_cb_.is_null()) | |
455 AbortRead(); | |
456 base::ResetAndReturn(&reset_cb_).Run(); | 512 base::ResetAndReturn(&reset_cb_).Run(); |
| 513 return; |
457 } | 514 } |
458 | 515 |
459 if (read_cb_.is_null()) | 516 if (read_cb_.is_null()) |
460 return; | 517 return; |
461 | 518 |
462 if (state_ == STATE_ERROR) { | 519 if (state_ == STATE_ERROR) { |
463 SatisfyRead(DECODE_ERROR, NULL); | 520 SatisfyRead(DECODE_ERROR, NULL); |
464 return; | 521 return; |
465 } | 522 } |
466 | 523 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
514 decrypting_demuxer_stream_.reset(); | 571 decrypting_demuxer_stream_.reset(); |
515 // Post |stop_cb_| because pending |read_cb_| and/or |reset_cb_| are also | 572 // Post |stop_cb_| because pending |read_cb_| and/or |reset_cb_| are also |
516 // posted in Stop(). | 573 // posted in Stop(). |
517 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); | 574 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); |
518 } | 575 } |
519 | 576 |
520 template class DecoderStream<DemuxerStream::VIDEO>; | 577 template class DecoderStream<DemuxerStream::VIDEO>; |
521 template class DecoderStream<DemuxerStream::AUDIO>; | 578 template class DecoderStream<DemuxerStream::AUDIO>; |
522 | 579 |
523 } // namespace media | 580 } // namespace media |
OLD | NEW |