Cast: Skip receiver log messages with time delta that can't be encoded.
[chromium-blink-merge.git] / media / filters / decoder_stream.cc
blob5c02547a2309e2b163ac242da56b7638b160c8d1
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.
5 #include "media/filters/decoder_stream.h"
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/bind_to_current_loop.h"
14 #include "media/base/decoder_buffer.h"
15 #include "media/base/demuxer_stream.h"
16 #include "media/base/video_decoder.h"
17 #include "media/filters/decrypting_demuxer_stream.h"
19 namespace media {
21 // TODO(rileya): Devise a better way of specifying trace/UMA/etc strings for
22 // templated classes such as this.
23 template <DemuxerStream::Type StreamType>
24 static const char* GetTraceString();
26 template <>
27 const char* GetTraceString<DemuxerStream::VIDEO>() {
28 return "DecoderStream<VIDEO>::Decode";
31 template <DemuxerStream::Type StreamType>
32 DecoderStream<StreamType>::DecoderStream(
33 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
34 ScopedVector<Decoder> decoders,
35 const SetDecryptorReadyCB& set_decryptor_ready_cb)
36 : task_runner_(task_runner),
37 weak_factory_(this),
38 state_(STATE_UNINITIALIZED),
39 stream_(NULL),
40 decoder_selector_(
41 new DecoderSelector<StreamType>(task_runner,
42 decoders.Pass(),
43 set_decryptor_ready_cb)) {}
45 template <DemuxerStream::Type StreamType>
46 DecoderStream<StreamType>::~DecoderStream() {
47 DCHECK(state_ == STATE_UNINITIALIZED || state_ == STATE_STOPPED) << state_;
50 template <DemuxerStream::Type StreamType>
51 void DecoderStream<StreamType>::Initialize(DemuxerStream* stream,
52 const StatisticsCB& statistics_cb,
53 const InitCB& init_cb) {
54 DVLOG(2) << __FUNCTION__;
55 DCHECK(task_runner_->BelongsToCurrentThread());
56 DCHECK_EQ(state_, STATE_UNINITIALIZED) << state_;
57 DCHECK(init_cb_.is_null());
58 DCHECK(!init_cb.is_null());
60 statistics_cb_ = statistics_cb;
61 init_cb_ = init_cb;
62 stream_ = stream;
64 state_ = STATE_INITIALIZING;
65 // TODO(xhwang): DecoderSelector only needs a config to select a decoder.
66 decoder_selector_->SelectDecoder(
67 stream,
68 StatisticsCB(),
69 base::Bind(&DecoderStream<StreamType>::OnDecoderSelected,
70 weak_factory_.GetWeakPtr()));
73 template <DemuxerStream::Type StreamType>
74 void DecoderStream<StreamType>::Read(const ReadCB& read_cb) {
75 DVLOG(2) << __FUNCTION__;
76 DCHECK(task_runner_->BelongsToCurrentThread());
77 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
78 state_ == STATE_ERROR) << state_;
79 // No two reads in the flight at any time.
80 DCHECK(read_cb_.is_null());
81 // No read during resetting or stopping process.
82 DCHECK(reset_cb_.is_null());
83 DCHECK(stop_cb_.is_null());
85 if (state_ == STATE_ERROR) {
86 task_runner_->PostTask(FROM_HERE, base::Bind(
87 read_cb, DECODE_ERROR, scoped_refptr<Output>()));
88 return;
91 read_cb_ = read_cb;
93 if (state_ == STATE_FLUSHING_DECODER) {
94 FlushDecoder();
95 return;
98 ReadFromDemuxerStream();
101 template <DemuxerStream::Type StreamType>
102 void DecoderStream<StreamType>::Reset(const base::Closure& closure) {
103 DVLOG(2) << __FUNCTION__;
104 DCHECK(task_runner_->BelongsToCurrentThread());
105 DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_;
106 DCHECK(reset_cb_.is_null());
107 DCHECK(stop_cb_.is_null());
109 reset_cb_ = closure;
111 // During decoder reinitialization, the Decoder does not need to be and
112 // cannot be Reset(). |decrypting_demuxer_stream_| was reset before decoder
113 // reinitialization.
114 if (state_ == STATE_REINITIALIZING_DECODER)
115 return;
117 // During pending demuxer read and when not using DecryptingDemuxerStream,
118 // the Decoder will be reset after demuxer read is returned
119 // (in OnBufferReady()).
120 if (state_ == STATE_PENDING_DEMUXER_READ && !decrypting_demuxer_stream_)
121 return;
123 // The Decoder API guarantees that if Decoder::Reset() is called during
124 // a pending decode, the decode callback must be fired before the reset
125 // callback is fired. Therefore, we can call Decoder::Reset() regardless
126 // of if we have a pending decode and always satisfy the reset callback when
127 // the decoder reset is finished.
128 if (decrypting_demuxer_stream_) {
129 decrypting_demuxer_stream_->Reset(base::Bind(
130 &DecoderStream<StreamType>::ResetDecoder, weak_factory_.GetWeakPtr()));
131 return;
134 ResetDecoder();
137 template <DemuxerStream::Type StreamType>
138 void DecoderStream<StreamType>::Stop(const base::Closure& closure) {
139 DVLOG(2) << __FUNCTION__;
140 DCHECK(task_runner_->BelongsToCurrentThread());
141 DCHECK_NE(state_, STATE_STOPPED) << state_;
142 DCHECK(stop_cb_.is_null());
144 stop_cb_ = closure;
146 if (state_ == STATE_INITIALIZING) {
147 decoder_selector_->Abort();
148 return;
151 DCHECK(init_cb_.is_null());
153 // All pending callbacks will be dropped.
154 weak_factory_.InvalidateWeakPtrs();
156 // Post callbacks to prevent reentrance into this object.
157 if (!read_cb_.is_null())
158 task_runner_->PostTask(FROM_HERE, base::Bind(
159 base::ResetAndReturn(&read_cb_), ABORTED, scoped_refptr<Output>()));
160 if (!reset_cb_.is_null())
161 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&reset_cb_));
163 if (decrypting_demuxer_stream_) {
164 decrypting_demuxer_stream_->Stop(base::Bind(
165 &DecoderStream<StreamType>::StopDecoder, weak_factory_.GetWeakPtr()));
166 return;
169 // We may not have a |decoder_| if Stop() was called during initialization.
170 if (decoder_) {
171 StopDecoder();
172 return;
175 state_ = STATE_STOPPED;
176 stream_ = NULL;
177 decoder_.reset();
178 decrypting_demuxer_stream_.reset();
179 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_));
182 template <DemuxerStream::Type StreamType>
183 bool DecoderStream<StreamType>::CanReadWithoutStalling() const {
184 DCHECK(task_runner_->BelongsToCurrentThread());
185 return decoder_->CanReadWithoutStalling();
188 template <DemuxerStream::Type StreamType>
189 void DecoderStream<StreamType>::OnDecoderSelected(
190 scoped_ptr<Decoder> selected_decoder,
191 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) {
192 DVLOG(2) << __FUNCTION__;
193 DCHECK(task_runner_->BelongsToCurrentThread());
194 DCHECK_EQ(state_, STATE_INITIALIZING) << state_;
195 DCHECK(!init_cb_.is_null());
196 DCHECK(read_cb_.is_null());
197 DCHECK(reset_cb_.is_null());
199 decoder_selector_.reset();
200 if (decrypting_demuxer_stream)
201 stream_ = decrypting_demuxer_stream.get();
203 if (!selected_decoder) {
204 state_ = STATE_UNINITIALIZED;
205 StreamTraits::FinishInitialization(
206 base::ResetAndReturn(&init_cb_), selected_decoder.get(), stream_);
207 } else {
208 state_ = STATE_NORMAL;
209 decoder_ = selected_decoder.Pass();
210 decrypting_demuxer_stream_ = decrypting_demuxer_stream.Pass();
211 StreamTraits::FinishInitialization(
212 base::ResetAndReturn(&init_cb_), decoder_.get(), stream_);
215 // Stop() called during initialization.
216 if (!stop_cb_.is_null()) {
217 Stop(base::ResetAndReturn(&stop_cb_));
218 return;
222 template <DemuxerStream::Type StreamType>
223 void DecoderStream<StreamType>::SatisfyRead(
224 Status status,
225 const scoped_refptr<Output>& output) {
226 DCHECK(!read_cb_.is_null());
227 base::ResetAndReturn(&read_cb_).Run(status, output);
230 template <DemuxerStream::Type StreamType>
231 void DecoderStream<StreamType>::AbortRead() {
232 // Abort read during pending reset. It is safe to fire the |read_cb_| directly
233 // instead of posting it because the renderer won't call into this class
234 // again when it's in kFlushing state.
235 // TODO(xhwang): Improve the resetting process to avoid this dependency on the
236 // caller.
237 DCHECK(!reset_cb_.is_null());
238 SatisfyRead(ABORTED, NULL);
241 template <DemuxerStream::Type StreamType>
242 void DecoderStream<StreamType>::Decode(
243 const scoped_refptr<DecoderBuffer>& buffer) {
244 DVLOG(2) << __FUNCTION__;
245 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_;
246 DCHECK(!read_cb_.is_null());
247 DCHECK(reset_cb_.is_null());
248 DCHECK(stop_cb_.is_null());
249 DCHECK(buffer);
251 int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size();
253 TRACE_EVENT_ASYNC_BEGIN0("media", GetTraceString<StreamType>(), this);
254 decoder_->Decode(buffer,
255 base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady,
256 weak_factory_.GetWeakPtr(),
257 buffer_size));
260 template <DemuxerStream::Type StreamType>
261 void DecoderStream<StreamType>::FlushDecoder() {
262 Decode(DecoderBuffer::CreateEOSBuffer());
265 template <DemuxerStream::Type StreamType>
266 void DecoderStream<StreamType>::OnDecodeOutputReady(
267 int buffer_size,
268 typename Decoder::Status status,
269 const scoped_refptr<Output>& output) {
270 DVLOG(2) << __FUNCTION__;
271 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_;
272 DCHECK(!read_cb_.is_null());
273 DCHECK(stop_cb_.is_null());
274 DCHECK_EQ(status == Decoder::kOk, output != NULL);
276 TRACE_EVENT_ASYNC_END0("media", GetTraceString<StreamType>(), this);
278 if (status == Decoder::kDecodeError) {
279 state_ = STATE_ERROR;
280 SatisfyRead(DECODE_ERROR, NULL);
281 return;
284 if (status == Decoder::kDecryptError) {
285 state_ = STATE_ERROR;
286 SatisfyRead(DECRYPT_ERROR, NULL);
287 return;
290 if (status == Decoder::kAborted) {
291 SatisfyRead(ABORTED, NULL);
292 return;
295 // Any successful decode counts!
296 if (buffer_size > 0) {
297 StreamTraits::ReportStatistics(statistics_cb_, buffer_size);
300 // Drop decoding result if Reset() was called during decoding.
301 // The resetting process will be handled when the decoder is reset.
302 if (!reset_cb_.is_null()) {
303 AbortRead();
304 return;
307 // Decoder flushed. Reinitialize the decoder.
308 if (state_ == STATE_FLUSHING_DECODER &&
309 status == Decoder::kOk && output->end_of_stream()) {
310 ReinitializeDecoder();
311 return;
314 if (status == Decoder::kNotEnoughData) {
315 if (state_ == STATE_NORMAL)
316 ReadFromDemuxerStream();
317 else if (state_ == STATE_FLUSHING_DECODER)
318 FlushDecoder();
319 return;
322 SatisfyRead(OK, output);
325 template <DemuxerStream::Type StreamType>
326 void DecoderStream<StreamType>::ReadFromDemuxerStream() {
327 DVLOG(2) << __FUNCTION__;
328 DCHECK_EQ(state_, STATE_NORMAL) << state_;
329 DCHECK(!read_cb_.is_null());
330 DCHECK(reset_cb_.is_null());
331 DCHECK(stop_cb_.is_null());
333 state_ = STATE_PENDING_DEMUXER_READ;
334 stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady,
335 weak_factory_.GetWeakPtr()));
338 template <DemuxerStream::Type StreamType>
339 void DecoderStream<StreamType>::OnBufferReady(
340 DemuxerStream::Status status,
341 const scoped_refptr<DecoderBuffer>& buffer) {
342 DVLOG(2) << __FUNCTION__;
343 DCHECK(task_runner_->BelongsToCurrentThread());
344 DCHECK_EQ(state_, STATE_PENDING_DEMUXER_READ) << state_;
345 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status;
346 DCHECK(!read_cb_.is_null());
347 DCHECK(stop_cb_.is_null());
349 state_ = STATE_NORMAL;
351 if (status == DemuxerStream::kConfigChanged) {
352 state_ = STATE_FLUSHING_DECODER;
353 if (!reset_cb_.is_null()) {
354 AbortRead();
355 // If we are using DecryptingDemuxerStream, we already called DDS::Reset()
356 // which will continue the resetting process in it's callback.
357 if (!decrypting_demuxer_stream_)
358 Reset(base::ResetAndReturn(&reset_cb_));
359 // Reinitialization will continue after Reset() is done.
360 } else {
361 FlushDecoder();
363 return;
366 if (!reset_cb_.is_null()) {
367 AbortRead();
368 // If we are using DecryptingDemuxerStream, we already called DDS::Reset()
369 // which will continue the resetting process in it's callback.
370 if (!decrypting_demuxer_stream_)
371 Reset(base::ResetAndReturn(&reset_cb_));
372 return;
375 if (status == DemuxerStream::kAborted) {
376 SatisfyRead(DEMUXER_READ_ABORTED, NULL);
377 return;
380 DCHECK(status == DemuxerStream::kOk) << status;
381 Decode(buffer);
384 template <DemuxerStream::Type StreamType>
385 void DecoderStream<StreamType>::ReinitializeDecoder() {
386 DVLOG(2) << __FUNCTION__;
387 DCHECK(task_runner_->BelongsToCurrentThread());
388 DCHECK_EQ(state_, STATE_FLUSHING_DECODER) << state_;
390 // TODO(rileya): Specialize this for audio, or, better yet, change
391 // DemuxerStream config getters to be templated.
392 DCHECK(stream_->video_decoder_config().IsValidConfig());
393 state_ = STATE_REINITIALIZING_DECODER;
394 decoder_->Initialize(
395 stream_->video_decoder_config(),
396 base::Bind(&DecoderStream<StreamType>::OnDecoderReinitialized,
397 weak_factory_.GetWeakPtr()));
400 template <DemuxerStream::Type StreamType>
401 void DecoderStream<StreamType>::OnDecoderReinitialized(PipelineStatus status) {
402 DVLOG(2) << __FUNCTION__;
403 DCHECK(task_runner_->BelongsToCurrentThread());
404 DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER) << state_;
405 DCHECK(stop_cb_.is_null());
407 // ReinitializeDecoder() can be called in two cases:
408 // 1, Flushing decoder finished (see OnDecodeOutputReady()).
409 // 2, Reset() was called during flushing decoder (see OnDecoderReset()).
410 // Also, Reset() can be called during pending ReinitializeDecoder().
411 // This function needs to handle them all!
413 state_ = (status == PIPELINE_OK) ? STATE_NORMAL : STATE_ERROR;
415 if (!reset_cb_.is_null()) {
416 if (!read_cb_.is_null())
417 AbortRead();
418 base::ResetAndReturn(&reset_cb_).Run();
421 if (read_cb_.is_null())
422 return;
424 if (state_ == STATE_ERROR) {
425 SatisfyRead(DECODE_ERROR, NULL);
426 return;
429 ReadFromDemuxerStream();
432 template <DemuxerStream::Type StreamType>
433 void DecoderStream<StreamType>::ResetDecoder() {
434 DVLOG(2) << __FUNCTION__;
435 DCHECK(task_runner_->BelongsToCurrentThread());
436 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
437 state_ == STATE_ERROR) << state_;
438 DCHECK(!reset_cb_.is_null());
440 decoder_->Reset(base::Bind(&DecoderStream<StreamType>::OnDecoderReset,
441 weak_factory_.GetWeakPtr()));
444 template <DemuxerStream::Type StreamType>
445 void DecoderStream<StreamType>::OnDecoderReset() {
446 DVLOG(2) << __FUNCTION__;
447 DCHECK(task_runner_->BelongsToCurrentThread());
448 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
449 state_ == STATE_ERROR) << state_;
450 // If Reset() was called during pending read, read callback should be fired
451 // before the reset callback is fired.
452 DCHECK(read_cb_.is_null());
453 DCHECK(!reset_cb_.is_null());
454 DCHECK(stop_cb_.is_null());
456 if (state_ != STATE_FLUSHING_DECODER) {
457 base::ResetAndReturn(&reset_cb_).Run();
458 return;
461 // The resetting process will be continued in OnDecoderReinitialized().
462 ReinitializeDecoder();
465 template <DemuxerStream::Type StreamType>
466 void DecoderStream<StreamType>::StopDecoder() {
467 DVLOG(2) << __FUNCTION__;
468 DCHECK(task_runner_->BelongsToCurrentThread());
469 DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_;
470 DCHECK(!stop_cb_.is_null());
472 decoder_->Stop(base::Bind(&DecoderStream<StreamType>::OnDecoderStopped,
473 weak_factory_.GetWeakPtr()));
476 template <DemuxerStream::Type StreamType>
477 void DecoderStream<StreamType>::OnDecoderStopped() {
478 DVLOG(2) << __FUNCTION__;
479 DCHECK(task_runner_->BelongsToCurrentThread());
480 DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_;
481 // If Stop() was called during pending read/reset, read/reset callback should
482 // be fired before the stop callback is fired.
483 DCHECK(read_cb_.is_null());
484 DCHECK(reset_cb_.is_null());
485 DCHECK(!stop_cb_.is_null());
487 state_ = STATE_STOPPED;
488 stream_ = NULL;
489 decoder_.reset();
490 decrypting_demuxer_stream_.reset();
491 base::ResetAndReturn(&stop_cb_).Run();
494 template class DecoderStream<DemuxerStream::VIDEO>;
496 } // namespace media