Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(897)

Side by Side Diff: media/filters/decoder_stream.cc

Issue 239893002: Allow multiple concurrent Decode() requests in VideoDecoder interface. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698