Allow supervised users to delete profiles in about:settings.
[chromium-blink-merge.git] / media / filters / decoder_stream.cc
blobf9fa8b2d8d7f2354a625412ff4e92b2edbdb2e38
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/location.h"
10 #include "base/logging.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/trace_event/trace_event.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"
20 namespace media {
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();
27 #define FUNCTION_DVLOG(level) \
28 DVLOG(level) << __FUNCTION__ << \
29 "<" << DecoderStreamTraits<StreamType>::ToString() << ">"
31 template <>
32 const char* GetTraceString<DemuxerStream::VIDEO>() {
33 return "DecoderStream<VIDEO>::Decode";
36 template <>
37 const char* GetTraceString<DemuxerStream::AUDIO>() {
38 return "DecoderStream<AUDIO>::Decode";
41 template <DemuxerStream::Type StreamType>
42 DecoderStream<StreamType>::DecoderStream(
43 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
44 ScopedVector<Decoder> decoders,
45 const scoped_refptr<MediaLog>& media_log)
46 : task_runner_(task_runner),
47 media_log_(media_log),
48 state_(STATE_UNINITIALIZED),
49 stream_(NULL),
50 decoder_selector_(
51 new DecoderSelector<StreamType>(task_runner, decoders.Pass())),
52 active_splice_(false),
53 decoding_eos_(false),
54 pending_decode_requests_(0),
55 weak_factory_(this) {
58 template <DemuxerStream::Type StreamType>
59 DecoderStream<StreamType>::~DecoderStream() {
60 FUNCTION_DVLOG(2);
61 DCHECK(task_runner_->BelongsToCurrentThread());
63 decoder_selector_.reset();
65 if (!init_cb_.is_null()) {
66 task_runner_->PostTask(FROM_HERE,
67 base::Bind(base::ResetAndReturn(&init_cb_), false));
69 if (!read_cb_.is_null()) {
70 task_runner_->PostTask(FROM_HERE, base::Bind(
71 base::ResetAndReturn(&read_cb_), ABORTED, scoped_refptr<Output>()));
73 if (!reset_cb_.is_null())
74 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&reset_cb_));
76 stream_ = NULL;
77 decoder_.reset();
78 decrypting_demuxer_stream_.reset();
81 template <DemuxerStream::Type StreamType>
82 void DecoderStream<StreamType>::Initialize(
83 DemuxerStream* stream,
84 const InitCB& init_cb,
85 const SetDecryptorReadyCB& set_decryptor_ready_cb,
86 const StatisticsCB& statistics_cb) {
87 FUNCTION_DVLOG(2);
88 DCHECK(task_runner_->BelongsToCurrentThread());
89 DCHECK_EQ(state_, STATE_UNINITIALIZED);
90 DCHECK(init_cb_.is_null());
91 DCHECK(!init_cb.is_null());
93 statistics_cb_ = statistics_cb;
94 init_cb_ = init_cb;
95 stream_ = stream;
97 state_ = STATE_INITIALIZING;
98 SelectDecoder(set_decryptor_ready_cb);
101 template <DemuxerStream::Type StreamType>
102 void DecoderStream<StreamType>::Read(const ReadCB& read_cb) {
103 FUNCTION_DVLOG(2);
104 DCHECK(task_runner_->BelongsToCurrentThread());
105 DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_INITIALIZING)
106 << state_;
107 // No two reads in the flight at any time.
108 DCHECK(read_cb_.is_null());
109 // No read during resetting or stopping process.
110 DCHECK(reset_cb_.is_null());
112 if (state_ == STATE_ERROR) {
113 task_runner_->PostTask(
114 FROM_HERE, base::Bind(read_cb, DECODE_ERROR, scoped_refptr<Output>()));
115 return;
118 if (state_ == STATE_END_OF_STREAM && ready_outputs_.empty()) {
119 task_runner_->PostTask(
120 FROM_HERE, base::Bind(read_cb, OK, StreamTraits::CreateEOSOutput()));
121 return;
124 if (!ready_outputs_.empty()) {
125 task_runner_->PostTask(FROM_HERE,
126 base::Bind(read_cb, OK, ready_outputs_.front()));
127 ready_outputs_.pop_front();
128 } else {
129 read_cb_ = read_cb;
132 if (state_ == STATE_NORMAL && CanDecodeMore())
133 ReadFromDemuxerStream();
136 template <DemuxerStream::Type StreamType>
137 void DecoderStream<StreamType>::Reset(const base::Closure& closure) {
138 FUNCTION_DVLOG(2);
139 DCHECK(task_runner_->BelongsToCurrentThread());
140 DCHECK_NE(state_, STATE_UNINITIALIZED);
141 DCHECK(reset_cb_.is_null());
143 reset_cb_ = closure;
145 if (!read_cb_.is_null()) {
146 task_runner_->PostTask(FROM_HERE, base::Bind(
147 base::ResetAndReturn(&read_cb_), ABORTED, scoped_refptr<Output>()));
150 ready_outputs_.clear();
152 // During decoder reinitialization, the Decoder does not need to be and
153 // cannot be Reset(). |decrypting_demuxer_stream_| was reset before decoder
154 // reinitialization.
155 if (state_ == STATE_REINITIALIZING_DECODER)
156 return;
158 // During pending demuxer read and when not using DecryptingDemuxerStream,
159 // the Decoder will be reset after demuxer read is returned
160 // (in OnBufferReady()).
161 if (state_ == STATE_PENDING_DEMUXER_READ && !decrypting_demuxer_stream_)
162 return;
164 if (decrypting_demuxer_stream_) {
165 decrypting_demuxer_stream_->Reset(base::Bind(
166 &DecoderStream<StreamType>::ResetDecoder, weak_factory_.GetWeakPtr()));
167 return;
170 ResetDecoder();
173 template <DemuxerStream::Type StreamType>
174 bool DecoderStream<StreamType>::CanReadWithoutStalling() const {
175 DCHECK(task_runner_->BelongsToCurrentThread());
176 return !ready_outputs_.empty() || decoder_->CanReadWithoutStalling();
179 template <>
180 bool DecoderStream<DemuxerStream::AUDIO>::CanReadWithoutStalling() const {
181 DCHECK(task_runner_->BelongsToCurrentThread());
182 return true;
185 template <DemuxerStream::Type StreamType>
186 int DecoderStream<StreamType>::GetMaxDecodeRequests() const {
187 return decoder_->GetMaxDecodeRequests();
190 template <>
191 int DecoderStream<DemuxerStream::AUDIO>::GetMaxDecodeRequests() const {
192 return 1;
195 template <DemuxerStream::Type StreamType>
196 bool DecoderStream<StreamType>::CanDecodeMore() const {
197 DCHECK(task_runner_->BelongsToCurrentThread());
199 // Limit total number of outputs stored in |ready_outputs_| and being decoded.
200 // It only makes sense to saturate decoder completely when output queue is
201 // empty.
202 int num_decodes =
203 static_cast<int>(ready_outputs_.size()) + pending_decode_requests_;
204 return !decoding_eos_ && num_decodes < GetMaxDecodeRequests();
207 template <DemuxerStream::Type StreamType>
208 void DecoderStream<StreamType>::SelectDecoder(
209 const SetDecryptorReadyCB& set_decryptor_ready_cb) {
210 decoder_selector_->SelectDecoder(
211 stream_, set_decryptor_ready_cb,
212 base::Bind(&DecoderStream<StreamType>::OnDecoderSelected,
213 weak_factory_.GetWeakPtr()),
214 base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady,
215 weak_factory_.GetWeakPtr()));
218 template <DemuxerStream::Type StreamType>
219 void DecoderStream<StreamType>::OnDecoderSelected(
220 scoped_ptr<Decoder> selected_decoder,
221 scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) {
222 FUNCTION_DVLOG(2) << ": "
223 << (selected_decoder ? selected_decoder->GetDisplayName()
224 : "No decoder selected.");
225 DCHECK(task_runner_->BelongsToCurrentThread());
226 DCHECK(state_ == STATE_INITIALIZING || state_ == STATE_REINITIALIZING_DECODER)
227 << state_;
228 if (state_ == STATE_INITIALIZING) {
229 DCHECK(!init_cb_.is_null());
230 DCHECK(read_cb_.is_null());
231 DCHECK(reset_cb_.is_null());
232 } else {
233 DCHECK(decoder_);
236 previous_decoder_ = decoder_.Pass();
237 decoder_ = selected_decoder.Pass();
238 if (decrypting_demuxer_stream) {
239 decrypting_demuxer_stream_ = decrypting_demuxer_stream.Pass();
240 stream_ = decrypting_demuxer_stream_.get();
243 if (!decoder_) {
244 if (state_ == STATE_INITIALIZING) {
245 state_ = STATE_UNINITIALIZED;
246 base::ResetAndReturn(&init_cb_).Run(false);
247 } else {
248 CompleteDecoderReinitialization(false);
250 return;
253 const std::string stream_type = DecoderStreamTraits<StreamType>::ToString();
254 media_log_->SetBooleanProperty(stream_type + "_dds",
255 decrypting_demuxer_stream_);
256 media_log_->SetStringProperty(stream_type + "_decoder",
257 decoder_->GetDisplayName());
259 if (state_ == STATE_REINITIALIZING_DECODER) {
260 CompleteDecoderReinitialization(true);
261 return;
264 // Initialization succeeded.
265 state_ = STATE_NORMAL;
266 if (StreamTraits::NeedsBitstreamConversion(decoder_.get()))
267 stream_->EnableBitstreamConverter();
268 base::ResetAndReturn(&init_cb_).Run(true);
271 template <DemuxerStream::Type StreamType>
272 void DecoderStream<StreamType>::SatisfyRead(
273 Status status,
274 const scoped_refptr<Output>& output) {
275 DCHECK(!read_cb_.is_null());
276 base::ResetAndReturn(&read_cb_).Run(status, output);
279 template <DemuxerStream::Type StreamType>
280 void DecoderStream<StreamType>::Decode(
281 const scoped_refptr<DecoderBuffer>& buffer) {
282 FUNCTION_DVLOG(2);
283 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_;
284 DCHECK_LT(pending_decode_requests_, GetMaxDecodeRequests());
285 DCHECK(reset_cb_.is_null());
286 DCHECK(buffer.get());
288 int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size();
290 TRACE_EVENT_ASYNC_BEGIN0("media", GetTraceString<StreamType>(), this);
292 if (buffer->end_of_stream())
293 decoding_eos_ = true;
295 ++pending_decode_requests_;
296 decoder_->Decode(buffer,
297 base::Bind(&DecoderStream<StreamType>::OnDecodeDone,
298 weak_factory_.GetWeakPtr(),
299 buffer_size,
300 buffer->end_of_stream()));
303 template <DemuxerStream::Type StreamType>
304 void DecoderStream<StreamType>::FlushDecoder() {
305 Decode(DecoderBuffer::CreateEOSBuffer());
308 template <DemuxerStream::Type StreamType>
309 void DecoderStream<StreamType>::OnDecodeDone(int buffer_size,
310 bool end_of_stream,
311 typename Decoder::Status status) {
312 FUNCTION_DVLOG(2) << ": " << status;
313 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
314 state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR)
315 << state_;
316 DCHECK_GT(pending_decode_requests_, 0);
318 --pending_decode_requests_;
320 TRACE_EVENT_ASYNC_END0("media", GetTraceString<StreamType>(), this);
322 if (end_of_stream) {
323 DCHECK(!pending_decode_requests_);
324 decoding_eos_ = false;
327 if (state_ == STATE_ERROR) {
328 DCHECK(read_cb_.is_null());
329 return;
332 // Drop decoding result if Reset() was called during decoding.
333 // The resetting process will be handled when the decoder is reset.
334 if (!reset_cb_.is_null())
335 return;
337 switch (status) {
338 case Decoder::kDecodeError:
339 case Decoder::kDecryptError:
340 state_ = STATE_ERROR;
341 ready_outputs_.clear();
342 if (!read_cb_.is_null())
343 SatisfyRead(DECODE_ERROR, NULL);
344 return;
346 case Decoder::kAborted:
347 // Decoder can return kAborted during Reset() or during destruction.
348 return;
350 case Decoder::kOk:
351 // Any successful decode counts!
352 if (buffer_size > 0)
353 StreamTraits::ReportStatistics(statistics_cb_, buffer_size);
355 if (state_ == STATE_NORMAL) {
356 if (end_of_stream) {
357 state_ = STATE_END_OF_STREAM;
358 if (ready_outputs_.empty() && !read_cb_.is_null())
359 SatisfyRead(OK, StreamTraits::CreateEOSOutput());
360 return;
363 if (CanDecodeMore())
364 ReadFromDemuxerStream();
365 return;
368 if (state_ == STATE_FLUSHING_DECODER && !pending_decode_requests_)
369 ReinitializeDecoder();
370 return;
374 template <DemuxerStream::Type StreamType>
375 void DecoderStream<StreamType>::OnDecodeOutputReady(
376 const scoped_refptr<Output>& output) {
377 FUNCTION_DVLOG(2) << ": " << output->timestamp().InMilliseconds() << " ms";
378 DCHECK(output.get());
379 DCHECK(!output->end_of_stream());
380 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
381 state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR)
382 << state_;
384 if (state_ == STATE_ERROR) {
385 DCHECK(read_cb_.is_null());
386 return;
389 // Drop decoding result if Reset() was called during decoding.
390 // The resetting process will be handled when the decoder is reset.
391 if (!reset_cb_.is_null())
392 return;
394 if (!read_cb_.is_null()) {
395 // If |ready_outputs_| was non-empty, the read would have already been
396 // satisifed by Read().
397 DCHECK(ready_outputs_.empty());
398 SatisfyRead(OK, output);
399 return;
402 // Store decoded output.
403 ready_outputs_.push_back(output);
406 template <DemuxerStream::Type StreamType>
407 void DecoderStream<StreamType>::ReadFromDemuxerStream() {
408 FUNCTION_DVLOG(2);
409 DCHECK_EQ(state_, STATE_NORMAL);
410 DCHECK(CanDecodeMore());
411 DCHECK(reset_cb_.is_null());
413 state_ = STATE_PENDING_DEMUXER_READ;
414 stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady,
415 weak_factory_.GetWeakPtr()));
418 template <DemuxerStream::Type StreamType>
419 void DecoderStream<StreamType>::OnBufferReady(
420 DemuxerStream::Status status,
421 const scoped_refptr<DecoderBuffer>& buffer) {
422 FUNCTION_DVLOG(2) << ": " << status << ", "
423 << (buffer.get() ? buffer->AsHumanReadableString()
424 : "NULL");
426 DCHECK(task_runner_->BelongsToCurrentThread());
427 DCHECK(state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR)
428 << state_;
429 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status;
431 // Decoding has been stopped (e.g due to an error).
432 if (state_ != STATE_PENDING_DEMUXER_READ) {
433 DCHECK(state_ == STATE_ERROR);
434 DCHECK(read_cb_.is_null());
435 return;
438 state_ = STATE_NORMAL;
440 if (status == DemuxerStream::kConfigChanged) {
441 FUNCTION_DVLOG(2) << ": " << "ConfigChanged";
442 DCHECK(stream_->SupportsConfigChanges());
444 if (!config_change_observer_cb_.is_null())
445 config_change_observer_cb_.Run();
447 state_ = STATE_FLUSHING_DECODER;
448 if (!reset_cb_.is_null()) {
449 // If we are using DecryptingDemuxerStream, we already called DDS::Reset()
450 // which will continue the resetting process in it's callback.
451 if (!decrypting_demuxer_stream_)
452 Reset(base::ResetAndReturn(&reset_cb_));
453 // Reinitialization will continue after Reset() is done.
454 } else {
455 FlushDecoder();
457 return;
460 if (!reset_cb_.is_null()) {
461 // If we are using DecryptingDemuxerStream, we already called DDS::Reset()
462 // which will continue the resetting process in it's callback.
463 if (!decrypting_demuxer_stream_)
464 Reset(base::ResetAndReturn(&reset_cb_));
465 return;
468 if (status == DemuxerStream::kAborted) {
469 if (!read_cb_.is_null())
470 SatisfyRead(DEMUXER_READ_ABORTED, NULL);
471 return;
474 if (!splice_observer_cb_.is_null() && !buffer->end_of_stream()) {
475 const bool has_splice_ts = buffer->splice_timestamp() != kNoTimestamp();
476 if (active_splice_ || has_splice_ts) {
477 splice_observer_cb_.Run(buffer->splice_timestamp());
478 active_splice_ = has_splice_ts;
482 DCHECK(status == DemuxerStream::kOk) << status;
483 Decode(buffer);
485 // Read more data if the decoder supports multiple parallel decoding requests.
486 if (CanDecodeMore())
487 ReadFromDemuxerStream();
490 template <DemuxerStream::Type StreamType>
491 void DecoderStream<StreamType>::ReinitializeDecoder() {
492 FUNCTION_DVLOG(2);
493 DCHECK(task_runner_->BelongsToCurrentThread());
494 DCHECK_EQ(state_, STATE_FLUSHING_DECODER);
495 DCHECK_EQ(pending_decode_requests_, 0);
497 state_ = STATE_REINITIALIZING_DECODER;
498 DecoderStreamTraits<StreamType>::InitializeDecoder(
499 decoder_.get(), stream_,
500 base::Bind(&DecoderStream<StreamType>::OnDecoderReinitialized,
501 weak_factory_.GetWeakPtr()),
502 base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady,
503 weak_factory_.GetWeakPtr()));
506 template <DemuxerStream::Type StreamType>
507 void DecoderStream<StreamType>::OnDecoderReinitialized(PipelineStatus status) {
508 FUNCTION_DVLOG(2);
509 DCHECK(task_runner_->BelongsToCurrentThread());
510 DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER);
512 // ReinitializeDecoder() can be called in two cases:
513 // 1, Flushing decoder finished (see OnDecodeOutputReady()).
514 // 2, Reset() was called during flushing decoder (see OnDecoderReset()).
515 // Also, Reset() can be called during pending ReinitializeDecoder().
516 // This function needs to handle them all!
518 if (status != PIPELINE_OK) {
519 // Reinitialization failed. Try to fall back to one of the remaining
520 // decoders. This will consume at least one decoder so doing it more than
521 // once is safe.
522 // For simplicity, don't attempt to fall back to a decryptor. Calling this
523 // with a null callback ensures that one won't be selected.
524 SelectDecoder(SetDecryptorReadyCB());
525 } else {
526 CompleteDecoderReinitialization(true);
530 template <DemuxerStream::Type StreamType>
531 void DecoderStream<StreamType>::CompleteDecoderReinitialization(bool success) {
532 FUNCTION_DVLOG(2);
533 DCHECK(task_runner_->BelongsToCurrentThread());
534 DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER);
536 state_ = success ? STATE_NORMAL : STATE_ERROR;
538 if (!reset_cb_.is_null()) {
539 base::ResetAndReturn(&reset_cb_).Run();
540 return;
543 if (read_cb_.is_null())
544 return;
546 if (state_ == STATE_ERROR) {
547 SatisfyRead(DECODE_ERROR, NULL);
548 return;
551 ReadFromDemuxerStream();
554 template <DemuxerStream::Type StreamType>
555 void DecoderStream<StreamType>::ResetDecoder() {
556 FUNCTION_DVLOG(2);
557 DCHECK(task_runner_->BelongsToCurrentThread());
558 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
559 state_ == STATE_ERROR || state_ == STATE_END_OF_STREAM) << state_;
560 DCHECK(!reset_cb_.is_null());
562 decoder_->Reset(base::Bind(&DecoderStream<StreamType>::OnDecoderReset,
563 weak_factory_.GetWeakPtr()));
566 template <DemuxerStream::Type StreamType>
567 void DecoderStream<StreamType>::OnDecoderReset() {
568 FUNCTION_DVLOG(2);
569 DCHECK(task_runner_->BelongsToCurrentThread());
570 DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
571 state_ == STATE_ERROR || state_ == STATE_END_OF_STREAM) << state_;
572 // If Reset() was called during pending read, read callback should be fired
573 // before the reset callback is fired.
574 DCHECK(read_cb_.is_null());
575 DCHECK(!reset_cb_.is_null());
577 if (state_ != STATE_FLUSHING_DECODER) {
578 state_ = STATE_NORMAL;
579 active_splice_ = false;
580 base::ResetAndReturn(&reset_cb_).Run();
581 return;
584 // The resetting process will be continued in OnDecoderReinitialized().
585 ReinitializeDecoder();
588 template class DecoderStream<DemuxerStream::VIDEO>;
589 template class DecoderStream<DemuxerStream::AUDIO>;
591 } // namespace media