Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / media / filters / decoder_selector.cc
blobfa12c17eea569e7f0338212fff60cf95e1489162
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 "decoder_selector.h"
7 #include "base/bind.h"
8 #include "base/callback_helpers.h"
9 #include "base/logging.h"
10 #include "base/single_thread_task_runner.h"
11 #include "media/base/audio_decoder.h"
12 #include "media/base/bind_to_current_loop.h"
13 #include "media/base/demuxer_stream.h"
14 #include "media/base/pipeline.h"
15 #include "media/base/video_decoder.h"
16 #include "media/filters/decoder_stream_traits.h"
17 #include "media/filters/decrypting_audio_decoder.h"
18 #include "media/filters/decrypting_demuxer_stream.h"
19 #include "media/filters/decrypting_video_decoder.h"
21 namespace media {
23 static bool HasValidStreamConfig(DemuxerStream* stream) {
24 switch (stream->type()) {
25 case DemuxerStream::AUDIO:
26 return stream->audio_decoder_config().IsValidConfig();
27 case DemuxerStream::VIDEO:
28 return stream->video_decoder_config().IsValidConfig();
29 case DemuxerStream::UNKNOWN:
30 case DemuxerStream::TEXT:
31 case DemuxerStream::NUM_TYPES:
32 NOTREACHED();
34 return false;
37 static bool IsStreamEncrypted(DemuxerStream* stream) {
38 switch (stream->type()) {
39 case DemuxerStream::AUDIO:
40 return stream->audio_decoder_config().is_encrypted();
41 case DemuxerStream::VIDEO:
42 return stream->video_decoder_config().is_encrypted();
43 case DemuxerStream::UNKNOWN:
44 case DemuxerStream::TEXT:
45 case DemuxerStream::NUM_TYPES:
46 NOTREACHED();
48 return false;
51 template <DemuxerStream::Type StreamType>
52 DecoderSelector<StreamType>::DecoderSelector(
53 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
54 ScopedVector<Decoder> decoders,
55 const SetDecryptorReadyCB& set_decryptor_ready_cb)
56 : task_runner_(task_runner),
57 decoders_(decoders.Pass()),
58 set_decryptor_ready_cb_(set_decryptor_ready_cb),
59 input_stream_(NULL),
60 weak_ptr_factory_(this) {}
62 template <DemuxerStream::Type StreamType>
63 DecoderSelector<StreamType>::~DecoderSelector() {
64 DVLOG(2) << __FUNCTION__;
65 DCHECK(select_decoder_cb_.is_null());
68 template <DemuxerStream::Type StreamType>
69 void DecoderSelector<StreamType>::SelectDecoder(
70 DemuxerStream* stream,
71 bool low_delay,
72 const SelectDecoderCB& select_decoder_cb) {
73 DVLOG(2) << __FUNCTION__;
74 DCHECK(task_runner_->BelongsToCurrentThread());
75 DCHECK(stream);
77 // Make sure |select_decoder_cb| runs on a different execution stack.
78 select_decoder_cb_ = BindToCurrentLoop(select_decoder_cb);
80 if (!HasValidStreamConfig(stream)) {
81 DLOG(ERROR) << "Invalid stream config.";
82 ReturnNullDecoder();
83 return;
86 input_stream_ = stream;
87 low_delay_ = low_delay;
89 if (!IsStreamEncrypted(input_stream_)) {
90 InitializeDecoder();
91 return;
94 // This could happen if Encrypted Media Extension (EME) is not enabled.
95 if (set_decryptor_ready_cb_.is_null()) {
96 ReturnNullDecoder();
97 return;
100 decoder_.reset(new typename StreamTraits::DecryptingDecoderType(
101 task_runner_, set_decryptor_ready_cb_));
103 DecoderStreamTraits<StreamType>::Initialize(
104 decoder_.get(),
105 StreamTraits::GetDecoderConfig(*input_stream_),
106 low_delay_,
107 base::Bind(&DecoderSelector<StreamType>::DecryptingDecoderInitDone,
108 weak_ptr_factory_.GetWeakPtr()));
111 template <DemuxerStream::Type StreamType>
112 void DecoderSelector<StreamType>::Abort() {
113 DVLOG(2) << __FUNCTION__;
114 DCHECK(task_runner_->BelongsToCurrentThread());
116 // This could happen when SelectDecoder() was not called or when
117 // |select_decoder_cb_| was already posted but not fired (e.g. in the
118 // message loop queue).
119 if (select_decoder_cb_.is_null())
120 return;
122 // We must be trying to initialize the |decoder_| or the
123 // |decrypted_stream_|. Invalid all weak pointers so that all initialization
124 // callbacks won't fire.
125 weak_ptr_factory_.InvalidateWeakPtrs();
127 if (decoder_) {
128 // |decrypted_stream_| is either NULL or already initialized. We don't
129 // need to Stop() |decrypted_stream_| in either case.
130 decoder_->Stop();
131 ReturnNullDecoder();
132 return;
135 if (decrypted_stream_) {
136 decrypted_stream_->Stop(
137 base::Bind(&DecoderSelector<StreamType>::ReturnNullDecoder,
138 weak_ptr_factory_.GetWeakPtr()));
139 return;
142 NOTREACHED();
145 template <DemuxerStream::Type StreamType>
146 void DecoderSelector<StreamType>::DecryptingDecoderInitDone(
147 PipelineStatus status) {
148 DVLOG(2) << __FUNCTION__;
149 DCHECK(task_runner_->BelongsToCurrentThread());
151 if (status == PIPELINE_OK) {
152 base::ResetAndReturn(&select_decoder_cb_)
153 .Run(decoder_.Pass(), scoped_ptr<DecryptingDemuxerStream>());
154 return;
157 decoder_.reset();
159 decrypted_stream_.reset(
160 new DecryptingDemuxerStream(task_runner_, set_decryptor_ready_cb_));
162 decrypted_stream_->Initialize(
163 input_stream_,
164 base::Bind(&DecoderSelector<StreamType>::DecryptingDemuxerStreamInitDone,
165 weak_ptr_factory_.GetWeakPtr()));
168 template <DemuxerStream::Type StreamType>
169 void DecoderSelector<StreamType>::DecryptingDemuxerStreamInitDone(
170 PipelineStatus status) {
171 DVLOG(2) << __FUNCTION__;
172 DCHECK(task_runner_->BelongsToCurrentThread());
174 if (status != PIPELINE_OK) {
175 ReturnNullDecoder();
176 return;
179 DCHECK(!IsStreamEncrypted(decrypted_stream_.get()));
180 input_stream_ = decrypted_stream_.get();
181 InitializeDecoder();
184 template <DemuxerStream::Type StreamType>
185 void DecoderSelector<StreamType>::InitializeDecoder() {
186 DVLOG(2) << __FUNCTION__;
187 DCHECK(task_runner_->BelongsToCurrentThread());
188 DCHECK(!decoder_);
190 if (decoders_.empty()) {
191 ReturnNullDecoder();
192 return;
195 decoder_.reset(decoders_.front());
196 decoders_.weak_erase(decoders_.begin());
198 DecoderStreamTraits<StreamType>::Initialize(
199 decoder_.get(),
200 StreamTraits::GetDecoderConfig(*input_stream_),
201 low_delay_,
202 base::Bind(&DecoderSelector<StreamType>::DecoderInitDone,
203 weak_ptr_factory_.GetWeakPtr()));
206 template <DemuxerStream::Type StreamType>
207 void DecoderSelector<StreamType>::DecoderInitDone(PipelineStatus status) {
208 DVLOG(2) << __FUNCTION__;
209 DCHECK(task_runner_->BelongsToCurrentThread());
211 if (status != PIPELINE_OK) {
212 decoder_.reset();
213 InitializeDecoder();
214 return;
217 base::ResetAndReturn(&select_decoder_cb_)
218 .Run(decoder_.Pass(), decrypted_stream_.Pass());
221 template <DemuxerStream::Type StreamType>
222 void DecoderSelector<StreamType>::ReturnNullDecoder() {
223 DVLOG(2) << __FUNCTION__;
224 DCHECK(task_runner_->BelongsToCurrentThread());
225 base::ResetAndReturn(&select_decoder_cb_)
226 .Run(scoped_ptr<Decoder>(),
227 scoped_ptr<DecryptingDemuxerStream>());
230 // These forward declarations tell the compiler that we will use
231 // DecoderSelector with these arguments, allowing us to keep these definitions
232 // in our .cc without causing linker errors. This also means if anyone tries to
233 // instantiate a DecoderSelector with anything but these two specializations
234 // they'll most likely get linker errors.
235 template class DecoderSelector<DemuxerStream::AUDIO>;
236 template class DecoderSelector<DemuxerStream::VIDEO>;
238 } // namespace media