• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "media/filters/decoder_stream.h"
6 
7 #include "base/bind.h"
8 #include "base/callback_helpers.h"
9 #include "base/debug/trace_event.h"
10 #include "base/location.h"
11 #include "base/logging.h"
12 #include "base/single_thread_task_runner.h"
13 #include "media/base/audio_decoder.h"
14 #include "media/base/bind_to_current_loop.h"
15 #include "media/base/decoder_buffer.h"
16 #include "media/base/demuxer_stream.h"
17 #include "media/base/video_decoder.h"
18 #include "media/filters/decrypting_demuxer_stream.h"
19 
20 namespace media {
21 
22 // TODO(rileya): Devise a better way of specifying trace/UMA/etc strings for
23 // templated classes such as this.
24 template <DemuxerStream::Type StreamType>
25 static const char* GetTraceString();
26 
27 #define FUNCTION_DVLOG(level) \
28   DVLOG(level) << __FUNCTION__ << \
29   "<" << DecoderStreamTraits<StreamType>::ToString() << ">"
30 
31 template <>
GetTraceString()32 const char* GetTraceString<DemuxerStream::VIDEO>() {
33   return "DecoderStream<VIDEO>::Decode";
34 }
35 
36 template <>
GetTraceString()37 const char* GetTraceString<DemuxerStream::AUDIO>() {
38   return "DecoderStream<AUDIO>::Decode";
39 }
40 
41 template <DemuxerStream::Type StreamType>
DecoderStream(const scoped_refptr<base::SingleThreadTaskRunner> & task_runner,ScopedVector<Decoder> decoders,const SetDecryptorReadyCB & set_decryptor_ready_cb)42 DecoderStream<StreamType>::DecoderStream(
43     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
44     ScopedVector<Decoder> decoders,
45     const SetDecryptorReadyCB& set_decryptor_ready_cb)
46     : task_runner_(task_runner),
47       state_(STATE_UNINITIALIZED),
48       stream_(NULL),
49       decoder_selector_(
50           new DecoderSelector<StreamType>(task_runner,
51                                           decoders.Pass(),
52                                           set_decryptor_ready_cb)),
53       active_splice_(false),
54       pending_decode_requests_(0),
55       weak_factory_(this) {}
56 
57 template <DemuxerStream::Type StreamType>
~DecoderStream()58 DecoderStream<StreamType>::~DecoderStream() {
59   DCHECK(state_ == STATE_UNINITIALIZED || state_ == STATE_STOPPED) << state_;
60 }
61 
62 template <DemuxerStream::Type StreamType>
Initialize(DemuxerStream * stream,bool low_delay,const StatisticsCB & statistics_cb,const InitCB & init_cb)63 void DecoderStream<StreamType>::Initialize(DemuxerStream* stream,
64                                            bool low_delay,
65                                            const StatisticsCB& statistics_cb,
66                                            const InitCB& init_cb) {
67   FUNCTION_DVLOG(2);
68   DCHECK(task_runner_->BelongsToCurrentThread());
69   DCHECK_EQ(state_, STATE_UNINITIALIZED) << state_;
70   DCHECK(init_cb_.is_null());
71   DCHECK(!init_cb.is_null());
72 
73   statistics_cb_ = statistics_cb;
74   init_cb_ = init_cb;
75   stream_ = stream;
76   low_delay_ = low_delay;
77 
78   state_ = STATE_INITIALIZING;
79   // TODO(xhwang): DecoderSelector only needs a config to select a decoder.
80   decoder_selector_->SelectDecoder(
81       stream, low_delay,
82       base::Bind(&DecoderStream<StreamType>::OnDecoderSelected,
83                  weak_factory_.GetWeakPtr()),
84       base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady,
85                  weak_factory_.GetWeakPtr()));
86 }
87 
88 template <DemuxerStream::Type StreamType>
Read(const ReadCB & read_cb)89 void DecoderStream<StreamType>::Read(const ReadCB& read_cb) {
90   FUNCTION_DVLOG(2);
91   DCHECK(task_runner_->BelongsToCurrentThread());
92   DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_INITIALIZING &&
93          state_ != STATE_STOPPED) << state_;
94   // No two reads in the flight at any time.
95   DCHECK(read_cb_.is_null());
96   // No read during resetting or stopping process.
97   DCHECK(reset_cb_.is_null());
98   DCHECK(stop_cb_.is_null());
99 
100   if (state_ == STATE_ERROR) {
101     task_runner_->PostTask(
102         FROM_HERE, base::Bind(read_cb, DECODE_ERROR, scoped_refptr<Output>()));
103     return;
104   }
105 
106   if (state_ == STATE_END_OF_STREAM && ready_outputs_.empty()) {
107     task_runner_->PostTask(
108         FROM_HERE, base::Bind(read_cb, OK, StreamTraits::CreateEOSOutput()));
109     return;
110   }
111 
112   if (!ready_outputs_.empty()) {
113     task_runner_->PostTask(FROM_HERE,
114                            base::Bind(read_cb, OK, ready_outputs_.front()));
115     ready_outputs_.pop_front();
116   } else {
117     read_cb_ = read_cb;
118   }
119 
120   if (state_ == STATE_NORMAL && CanDecodeMore())
121     ReadFromDemuxerStream();
122 }
123 
124 template <DemuxerStream::Type StreamType>
Reset(const base::Closure & closure)125 void DecoderStream<StreamType>::Reset(const base::Closure& closure) {
126   FUNCTION_DVLOG(2);
127   DCHECK(task_runner_->BelongsToCurrentThread());
128   DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_;
129   DCHECK(reset_cb_.is_null());
130   DCHECK(stop_cb_.is_null());
131 
132   reset_cb_ = closure;
133 
134   if (!read_cb_.is_null()) {
135     task_runner_->PostTask(FROM_HERE, base::Bind(
136         base::ResetAndReturn(&read_cb_), ABORTED, scoped_refptr<Output>()));
137   }
138 
139   ready_outputs_.clear();
140 
141   // During decoder reinitialization, the Decoder does not need to be and
142   // cannot be Reset(). |decrypting_demuxer_stream_| was reset before decoder
143   // reinitialization.
144   if (state_ == STATE_REINITIALIZING_DECODER)
145     return;
146 
147   // During pending demuxer read and when not using DecryptingDemuxerStream,
148   // the Decoder will be reset after demuxer read is returned
149   // (in OnBufferReady()).
150   if (state_ == STATE_PENDING_DEMUXER_READ && !decrypting_demuxer_stream_)
151     return;
152 
153   if (decrypting_demuxer_stream_) {
154     decrypting_demuxer_stream_->Reset(base::Bind(
155         &DecoderStream<StreamType>::ResetDecoder, weak_factory_.GetWeakPtr()));
156     return;
157   }
158 
159   ResetDecoder();
160 }
161 
162 template <DemuxerStream::Type StreamType>
Stop(const base::Closure & closure)163 void DecoderStream<StreamType>::Stop(const base::Closure& closure) {
164   FUNCTION_DVLOG(2);
165   DCHECK(task_runner_->BelongsToCurrentThread());
166   DCHECK_NE(state_, STATE_STOPPED) << state_;
167   DCHECK(stop_cb_.is_null());
168 
169   stop_cb_ = closure;
170 
171   if (state_ == STATE_INITIALIZING) {
172     decoder_selector_->Abort();
173     return;
174   }
175 
176   DCHECK(init_cb_.is_null());
177 
178   // All pending callbacks will be dropped.
179   weak_factory_.InvalidateWeakPtrs();
180 
181   // Post callbacks to prevent reentrance into this object.
182   if (!read_cb_.is_null()) {
183     task_runner_->PostTask(FROM_HERE, base::Bind(
184         base::ResetAndReturn(&read_cb_), ABORTED, scoped_refptr<Output>()));
185   }
186   if (!reset_cb_.is_null())
187     task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&reset_cb_));
188 
189   if (decrypting_demuxer_stream_) {
190     decrypting_demuxer_stream_->Stop(base::Bind(
191         &DecoderStream<StreamType>::StopDecoder, weak_factory_.GetWeakPtr()));
192     return;
193   }
194 
195   // We may not have a |decoder_| if Stop() was called during initialization.
196   if (decoder_) {
197     StopDecoder();
198     return;
199   }
200 
201   state_ = STATE_STOPPED;
202   stream_ = NULL;
203   decoder_.reset();
204   decrypting_demuxer_stream_.reset();
205   task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_));
206 }
207 
208 template <DemuxerStream::Type StreamType>
CanReadWithoutStalling() const209 bool DecoderStream<StreamType>::CanReadWithoutStalling() const {
210   DCHECK(task_runner_->BelongsToCurrentThread());
211   return !ready_outputs_.empty() || decoder_->CanReadWithoutStalling();
212 }
213 
214 template <>
CanReadWithoutStalling() const215 bool DecoderStream<DemuxerStream::AUDIO>::CanReadWithoutStalling() const {
216   DCHECK(task_runner_->BelongsToCurrentThread());
217   return true;
218 }
219 
220 template <DemuxerStream::Type StreamType>
GetMaxDecodeRequests() const221 int DecoderStream<StreamType>::GetMaxDecodeRequests() const {
222   return decoder_->GetMaxDecodeRequests();
223 }
224 
225 template <>
GetMaxDecodeRequests() const226 int DecoderStream<DemuxerStream::AUDIO>::GetMaxDecodeRequests() const {
227   return 1;
228 }
229 
230 template <DemuxerStream::Type StreamType>
CanDecodeMore() const231 bool DecoderStream<StreamType>::CanDecodeMore() const {
232   DCHECK(task_runner_->BelongsToCurrentThread());
233 
234   // Limit total number of outputs stored in |ready_outputs_| and being decoded.
235   // It only makes sense to saturate decoder completely when output queue is
236   // empty.
237   int num_decodes =
238       static_cast<int>(ready_outputs_.size()) + pending_decode_requests_;
239   return num_decodes < GetMaxDecodeRequests();
240 }
241 
242 template <DemuxerStream::Type StreamType>
OnDecoderSelected(scoped_ptr<Decoder> selected_decoder,scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream)243 void DecoderStream<StreamType>::OnDecoderSelected(
244     scoped_ptr<Decoder> selected_decoder,
245     scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) {
246   FUNCTION_DVLOG(2);
247   DCHECK(task_runner_->BelongsToCurrentThread());
248   DCHECK_EQ(state_, STATE_INITIALIZING) << state_;
249   DCHECK(!init_cb_.is_null());
250   DCHECK(read_cb_.is_null());
251   DCHECK(reset_cb_.is_null());
252 
253   decoder_selector_.reset();
254   if (decrypting_demuxer_stream)
255     stream_ = decrypting_demuxer_stream.get();
256 
257   if (!selected_decoder) {
258     state_ = STATE_UNINITIALIZED;
259     StreamTraits::FinishInitialization(
260         base::ResetAndReturn(&init_cb_), selected_decoder.get(), stream_);
261   } else {
262     state_ = STATE_NORMAL;
263     decoder_ = selected_decoder.Pass();
264     decrypting_demuxer_stream_ = decrypting_demuxer_stream.Pass();
265     StreamTraits::FinishInitialization(
266         base::ResetAndReturn(&init_cb_), decoder_.get(), stream_);
267   }
268 
269   // Stop() called during initialization.
270   if (!stop_cb_.is_null()) {
271     Stop(base::ResetAndReturn(&stop_cb_));
272     return;
273   }
274 }
275 
276 template <DemuxerStream::Type StreamType>
SatisfyRead(Status status,const scoped_refptr<Output> & output)277 void DecoderStream<StreamType>::SatisfyRead(
278     Status status,
279     const scoped_refptr<Output>& output) {
280   DCHECK(!read_cb_.is_null());
281   base::ResetAndReturn(&read_cb_).Run(status, output);
282 }
283 
284 template <DemuxerStream::Type StreamType>
Decode(const scoped_refptr<DecoderBuffer> & buffer)285 void DecoderStream<StreamType>::Decode(
286     const scoped_refptr<DecoderBuffer>& buffer) {
287   FUNCTION_DVLOG(2);
288   DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_;
289   DCHECK_LT(pending_decode_requests_, GetMaxDecodeRequests());
290   DCHECK(reset_cb_.is_null());
291   DCHECK(stop_cb_.is_null());
292   DCHECK(buffer);
293 
294   int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size();
295 
296   TRACE_EVENT_ASYNC_BEGIN0("media", GetTraceString<StreamType>(), this);
297   ++pending_decode_requests_;
298   decoder_->Decode(buffer,
299                    base::Bind(&DecoderStream<StreamType>::OnDecodeDone,
300                               weak_factory_.GetWeakPtr(),
301                               buffer_size,
302                               buffer->end_of_stream()));
303 }
304 
305 template <DemuxerStream::Type StreamType>
FlushDecoder()306 void DecoderStream<StreamType>::FlushDecoder() {
307   Decode(DecoderBuffer::CreateEOSBuffer());
308 }
309 
310 template <DemuxerStream::Type StreamType>
OnDecodeDone(int buffer_size,bool end_of_stream,typename Decoder::Status status)311 void DecoderStream<StreamType>::OnDecodeDone(int buffer_size,
312                                              bool end_of_stream,
313                                              typename Decoder::Status status) {
314   FUNCTION_DVLOG(2) << status;
315   DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
316          state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR)
317       << state_;
318   DCHECK(stop_cb_.is_null());
319   DCHECK_GT(pending_decode_requests_, 0);
320 
321   --pending_decode_requests_;
322 
323   TRACE_EVENT_ASYNC_END0("media", GetTraceString<StreamType>(), this);
324 
325   if (state_ == STATE_ERROR) {
326     DCHECK(read_cb_.is_null());
327     return;
328   }
329 
330   // Drop decoding result if Reset() was called during decoding.
331   // The resetting process will be handled when the decoder is reset.
332   if (!reset_cb_.is_null())
333     return;
334 
335   switch (status) {
336     case Decoder::kDecodeError:
337     case Decoder::kDecryptError:
338       state_ = STATE_ERROR;
339       ready_outputs_.clear();
340       if (!read_cb_.is_null())
341         SatisfyRead(DECODE_ERROR, NULL);
342       return;
343 
344     case Decoder::kAborted:
345       // Decoder can return kAborted only when Reset is pending.
346       NOTREACHED();
347       return;
348 
349     case Decoder::kOk:
350       // Any successful decode counts!
351       if (buffer_size > 0)
352         StreamTraits::ReportStatistics(statistics_cb_, buffer_size);
353 
354       if (state_ == STATE_NORMAL) {
355         if (end_of_stream) {
356           state_ = STATE_END_OF_STREAM;
357           if (ready_outputs_.empty() && !read_cb_.is_null())
358             SatisfyRead(OK, StreamTraits::CreateEOSOutput());
359           return;
360         }
361 
362         if (CanDecodeMore())
363           ReadFromDemuxerStream();
364         return;
365       }
366 
367       if (state_ == STATE_FLUSHING_DECODER && !pending_decode_requests_)
368         ReinitializeDecoder();
369       return;
370   }
371 }
372 
373 template <DemuxerStream::Type StreamType>
OnDecodeOutputReady(const scoped_refptr<Output> & output)374 void DecoderStream<StreamType>::OnDecodeOutputReady(
375     const scoped_refptr<Output>& output) {
376   FUNCTION_DVLOG(2) << ": " << output->timestamp().InMilliseconds() << " ms";
377   DCHECK(output);
378   DCHECK(!output->end_of_stream());
379   DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
380          state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR)
381       << state_;
382 
383   if (state_ == STATE_ERROR) {
384     DCHECK(read_cb_.is_null());
385     return;
386   }
387 
388   // Drop decoding result if Reset() was called during decoding.
389   // The resetting process will be handled when the decoder is reset.
390   if (!reset_cb_.is_null())
391     return;
392 
393   // TODO(xhwang): VideoDecoder doesn't need to return EOS after it's flushed.
394   // Fix all decoders and remove this block.
395   // Store decoded output.
396   ready_outputs_.push_back(output);
397 
398   if (read_cb_.is_null())
399     return;
400 
401   // Satisfy outstanding read request, if any.
402   scoped_refptr<Output> read_result = ready_outputs_.front();
403   ready_outputs_.pop_front();
404   SatisfyRead(OK, output);
405 }
406 
407 template <DemuxerStream::Type StreamType>
ReadFromDemuxerStream()408 void DecoderStream<StreamType>::ReadFromDemuxerStream() {
409   FUNCTION_DVLOG(2);
410   DCHECK_EQ(state_, STATE_NORMAL) << state_;
411   DCHECK(CanDecodeMore());
412   DCHECK(reset_cb_.is_null());
413   DCHECK(stop_cb_.is_null());
414 
415   state_ = STATE_PENDING_DEMUXER_READ;
416   stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady,
417                            weak_factory_.GetWeakPtr()));
418 }
419 
420 template <DemuxerStream::Type StreamType>
OnBufferReady(DemuxerStream::Status status,const scoped_refptr<DecoderBuffer> & buffer)421 void DecoderStream<StreamType>::OnBufferReady(
422     DemuxerStream::Status status,
423     const scoped_refptr<DecoderBuffer>& buffer) {
424   FUNCTION_DVLOG(2) << ": " << status << ", "
425                     << buffer->AsHumanReadableString();
426 
427   DCHECK(task_runner_->BelongsToCurrentThread());
428   DCHECK(state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR ||
429          state_ == STATE_STOPPED)
430       << state_;
431   DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status;
432   DCHECK(stop_cb_.is_null());
433 
434   // Decoding has been stopped (e.g due to an error).
435   if (state_ != STATE_PENDING_DEMUXER_READ) {
436     DCHECK(state_ == STATE_ERROR || state_ == STATE_STOPPED);
437     DCHECK(read_cb_.is_null());
438     return;
439   }
440 
441   state_ = STATE_NORMAL;
442 
443   if (status == DemuxerStream::kConfigChanged) {
444     FUNCTION_DVLOG(2) << ": " << "ConfigChanged";
445     DCHECK(stream_->SupportsConfigChanges());
446 
447     if (!config_change_observer_cb_.is_null())
448       config_change_observer_cb_.Run();
449 
450     state_ = STATE_FLUSHING_DECODER;
451     if (!reset_cb_.is_null()) {
452       // If we are using DecryptingDemuxerStream, we already called DDS::Reset()
453       // which will continue the resetting process in it's callback.
454       if (!decrypting_demuxer_stream_)
455         Reset(base::ResetAndReturn(&reset_cb_));
456       // Reinitialization will continue after Reset() is done.
457     } else {
458       FlushDecoder();
459     }
460     return;
461   }
462 
463   if (!reset_cb_.is_null()) {
464     // If we are using DecryptingDemuxerStream, we already called DDS::Reset()
465     // which will continue the resetting process in it's callback.
466     if (!decrypting_demuxer_stream_)
467       Reset(base::ResetAndReturn(&reset_cb_));
468     return;
469   }
470 
471   if (status == DemuxerStream::kAborted) {
472     if (!read_cb_.is_null())
473       SatisfyRead(DEMUXER_READ_ABORTED, NULL);
474     return;
475   }
476 
477   if (!splice_observer_cb_.is_null() && !buffer->end_of_stream()) {
478     const bool has_splice_ts = buffer->splice_timestamp() != kNoTimestamp();
479     if (active_splice_ || has_splice_ts) {
480       splice_observer_cb_.Run(buffer->splice_timestamp());
481       active_splice_ = has_splice_ts;
482     }
483   }
484 
485   DCHECK(status == DemuxerStream::kOk) << status;
486   Decode(buffer);
487 
488   // Read more data if the decoder supports multiple parallel decoding requests.
489   if (CanDecodeMore() && !buffer->end_of_stream())
490     ReadFromDemuxerStream();
491 }
492 
493 template <DemuxerStream::Type StreamType>
ReinitializeDecoder()494 void DecoderStream<StreamType>::ReinitializeDecoder() {
495   FUNCTION_DVLOG(2);
496   DCHECK(task_runner_->BelongsToCurrentThread());
497   DCHECK_EQ(state_, STATE_FLUSHING_DECODER) << state_;
498   DCHECK_EQ(pending_decode_requests_, 0);
499 
500   DCHECK(StreamTraits::GetDecoderConfig(*stream_).IsValidConfig());
501   state_ = STATE_REINITIALIZING_DECODER;
502   DecoderStreamTraits<StreamType>::Initialize(
503       decoder_.get(),
504       StreamTraits::GetDecoderConfig(*stream_),
505       low_delay_,
506       base::Bind(&DecoderStream<StreamType>::OnDecoderReinitialized,
507                  weak_factory_.GetWeakPtr()),
508       base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady,
509                  weak_factory_.GetWeakPtr()));
510 }
511 
512 template <DemuxerStream::Type StreamType>
OnDecoderReinitialized(PipelineStatus status)513 void DecoderStream<StreamType>::OnDecoderReinitialized(PipelineStatus status) {
514   FUNCTION_DVLOG(2);
515   DCHECK(task_runner_->BelongsToCurrentThread());
516   DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER) << state_;
517   DCHECK(stop_cb_.is_null());
518 
519   // ReinitializeDecoder() can be called in two cases:
520   // 1, Flushing decoder finished (see OnDecodeOutputReady()).
521   // 2, Reset() was called during flushing decoder (see OnDecoderReset()).
522   // Also, Reset() can be called during pending ReinitializeDecoder().
523   // This function needs to handle them all!
524 
525   state_ = (status == PIPELINE_OK) ? STATE_NORMAL : STATE_ERROR;
526 
527   if (!reset_cb_.is_null()) {
528     base::ResetAndReturn(&reset_cb_).Run();
529     return;
530   }
531 
532   if (read_cb_.is_null())
533     return;
534 
535   if (state_ == STATE_ERROR) {
536     SatisfyRead(DECODE_ERROR, NULL);
537     return;
538   }
539 
540   ReadFromDemuxerStream();
541 }
542 
543 template <DemuxerStream::Type StreamType>
ResetDecoder()544 void DecoderStream<StreamType>::ResetDecoder() {
545   FUNCTION_DVLOG(2);
546   DCHECK(task_runner_->BelongsToCurrentThread());
547   DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
548          state_ == STATE_ERROR || state_ == STATE_END_OF_STREAM) << state_;
549   DCHECK(!reset_cb_.is_null());
550 
551   decoder_->Reset(base::Bind(&DecoderStream<StreamType>::OnDecoderReset,
552                              weak_factory_.GetWeakPtr()));
553 }
554 
555 template <DemuxerStream::Type StreamType>
OnDecoderReset()556 void DecoderStream<StreamType>::OnDecoderReset() {
557   FUNCTION_DVLOG(2);
558   DCHECK(task_runner_->BelongsToCurrentThread());
559   DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
560          state_ == STATE_ERROR || state_ == STATE_END_OF_STREAM) << state_;
561   // If Reset() was called during pending read, read callback should be fired
562   // before the reset callback is fired.
563   DCHECK(read_cb_.is_null());
564   DCHECK(!reset_cb_.is_null());
565   DCHECK(stop_cb_.is_null());
566 
567   if (state_ != STATE_FLUSHING_DECODER) {
568     state_ = STATE_NORMAL;
569     active_splice_ = false;
570     base::ResetAndReturn(&reset_cb_).Run();
571     return;
572   }
573 
574   // The resetting process will be continued in OnDecoderReinitialized().
575   ReinitializeDecoder();
576 }
577 
578 template <DemuxerStream::Type StreamType>
StopDecoder()579 void DecoderStream<StreamType>::StopDecoder() {
580   FUNCTION_DVLOG(2);
581   DCHECK(task_runner_->BelongsToCurrentThread());
582   DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_;
583   DCHECK(!stop_cb_.is_null());
584 
585   state_ = STATE_STOPPED;
586   decoder_->Stop();
587   stream_ = NULL;
588   decoder_.reset();
589   decrypting_demuxer_stream_.reset();
590   // Post |stop_cb_| because pending |read_cb_| and/or |reset_cb_| are also
591   // posted in Stop().
592   task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_));
593 }
594 
595 template class DecoderStream<DemuxerStream::VIDEO>;
596 template class DecoderStream<DemuxerStream::AUDIO>;
597 
598 }  // namespace media
599