Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / media / filters / decoder_selector.cc
blobca32c2609da2569f43eede282da66f79138388b4
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/media_log.h"
15 #include "media/base/pipeline.h"
16 #include "media/base/video_decoder.h"
17 #include "media/filters/decoder_stream_traits.h"
18 #include "media/filters/decrypting_audio_decoder.h"
19 #include "media/filters/decrypting_demuxer_stream.h"
20 #include "media/filters/decrypting_video_decoder.h"
22 namespace media {
24 static bool HasValidStreamConfig(DemuxerStream* stream) {
25 switch (stream->type()) {
26 case DemuxerStream::AUDIO:
27 return stream->audio_decoder_config().IsValidConfig();
28 case DemuxerStream::VIDEO:
29 return stream->video_decoder_config().IsValidConfig();
30 case DemuxerStream::UNKNOWN:
31 case DemuxerStream::TEXT:
32 case DemuxerStream::NUM_TYPES:
33 NOTREACHED();
35 return false;
38 static bool IsStreamEncrypted(DemuxerStream* stream) {
39 switch (stream->type()) {
40 case DemuxerStream::AUDIO:
41 return stream->audio_decoder_config().is_encrypted();
42 case DemuxerStream::VIDEO:
43 return stream->video_decoder_config().is_encrypted();
44 case DemuxerStream::UNKNOWN:
45 case DemuxerStream::TEXT:
46 case DemuxerStream::NUM_TYPES:
47 NOTREACHED();
49 return false;
52 template <DemuxerStream::Type StreamType>
53 DecoderSelector<StreamType>::DecoderSelector(
54 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
55 ScopedVector<Decoder> decoders,
56 const scoped_refptr<MediaLog>& media_log)
57 : task_runner_(task_runner),
58 decoders_(decoders.Pass()),
59 media_log_(media_log),
60 input_stream_(NULL),
61 weak_ptr_factory_(this) {
64 template <DemuxerStream::Type StreamType>
65 DecoderSelector<StreamType>::~DecoderSelector() {
66 DVLOG(2) << __FUNCTION__;
67 DCHECK(task_runner_->BelongsToCurrentThread());
69 if (!select_decoder_cb_.is_null())
70 ReturnNullDecoder();
72 decoder_.reset();
73 decrypted_stream_.reset();
76 template <DemuxerStream::Type StreamType>
77 void DecoderSelector<StreamType>::SelectDecoder(
78 DemuxerStream* stream,
79 const SetDecryptorReadyCB& set_decryptor_ready_cb,
80 const SelectDecoderCB& select_decoder_cb,
81 const typename Decoder::OutputCB& output_cb,
82 const base::Closure& waiting_for_decryption_key_cb) {
83 DVLOG(2) << __FUNCTION__;
84 DCHECK(task_runner_->BelongsToCurrentThread());
85 DCHECK(stream);
86 DCHECK(select_decoder_cb_.is_null());
88 set_decryptor_ready_cb_ = set_decryptor_ready_cb;
89 waiting_for_decryption_key_cb_ = waiting_for_decryption_key_cb;
91 // Make sure |select_decoder_cb| runs on a different execution stack.
92 select_decoder_cb_ = BindToCurrentLoop(select_decoder_cb);
94 if (!HasValidStreamConfig(stream)) {
95 DLOG(ERROR) << "Invalid stream config.";
96 ReturnNullDecoder();
97 return;
100 input_stream_ = stream;
101 output_cb_ = output_cb;
103 if (!IsStreamEncrypted(input_stream_)) {
104 InitializeDecoder();
105 return;
108 // This could be null if Encrypted Media Extension (EME) is not enabled.
109 if (set_decryptor_ready_cb_.is_null()) {
110 ReturnNullDecoder();
111 return;
114 decoder_.reset(new typename StreamTraits::DecryptingDecoderType(
115 task_runner_, media_log_, set_decryptor_ready_cb_,
116 waiting_for_decryption_key_cb_));
118 DecoderStreamTraits<StreamType>::InitializeDecoder(
119 decoder_.get(), input_stream_,
120 base::Bind(&DecoderSelector<StreamType>::DecryptingDecoderInitDone,
121 weak_ptr_factory_.GetWeakPtr()),
122 output_cb_);
125 template <DemuxerStream::Type StreamType>
126 void DecoderSelector<StreamType>::DecryptingDecoderInitDone(bool success) {
127 DVLOG(2) << __FUNCTION__;
128 DCHECK(task_runner_->BelongsToCurrentThread());
130 if (success) {
131 base::ResetAndReturn(&select_decoder_cb_)
132 .Run(decoder_.Pass(), scoped_ptr<DecryptingDemuxerStream>());
133 return;
136 decoder_.reset();
138 decrypted_stream_.reset(new DecryptingDemuxerStream(
139 task_runner_, media_log_, set_decryptor_ready_cb_,
140 waiting_for_decryption_key_cb_));
142 decrypted_stream_->Initialize(
143 input_stream_,
144 base::Bind(&DecoderSelector<StreamType>::DecryptingDemuxerStreamInitDone,
145 weak_ptr_factory_.GetWeakPtr()));
148 template <DemuxerStream::Type StreamType>
149 void DecoderSelector<StreamType>::DecryptingDemuxerStreamInitDone(
150 PipelineStatus status) {
151 DVLOG(2) << __FUNCTION__;
152 DCHECK(task_runner_->BelongsToCurrentThread());
154 if (status != PIPELINE_OK) {
155 ReturnNullDecoder();
156 return;
159 DCHECK(!IsStreamEncrypted(decrypted_stream_.get()));
160 input_stream_ = decrypted_stream_.get();
161 InitializeDecoder();
164 template <DemuxerStream::Type StreamType>
165 void DecoderSelector<StreamType>::InitializeDecoder() {
166 DVLOG(2) << __FUNCTION__;
167 DCHECK(task_runner_->BelongsToCurrentThread());
168 DCHECK(!decoder_);
170 if (decoders_.empty()) {
171 ReturnNullDecoder();
172 return;
175 decoder_.reset(decoders_.front());
176 decoders_.weak_erase(decoders_.begin());
178 DecoderStreamTraits<StreamType>::InitializeDecoder(
179 decoder_.get(), input_stream_,
180 base::Bind(&DecoderSelector<StreamType>::DecoderInitDone,
181 weak_ptr_factory_.GetWeakPtr()),
182 output_cb_);
185 template <DemuxerStream::Type StreamType>
186 void DecoderSelector<StreamType>::DecoderInitDone(bool success) {
187 DVLOG(2) << __FUNCTION__;
188 DCHECK(task_runner_->BelongsToCurrentThread());
190 if (!success) {
191 decoder_.reset();
192 InitializeDecoder();
193 return;
196 base::ResetAndReturn(&select_decoder_cb_)
197 .Run(decoder_.Pass(), decrypted_stream_.Pass());
200 template <DemuxerStream::Type StreamType>
201 void DecoderSelector<StreamType>::ReturnNullDecoder() {
202 DVLOG(2) << __FUNCTION__;
203 DCHECK(task_runner_->BelongsToCurrentThread());
204 base::ResetAndReturn(&select_decoder_cb_)
205 .Run(scoped_ptr<Decoder>(),
206 scoped_ptr<DecryptingDemuxerStream>());
209 // These forward declarations tell the compiler that we will use
210 // DecoderSelector with these arguments, allowing us to keep these definitions
211 // in our .cc without causing linker errors. This also means if anyone tries to
212 // instantiate a DecoderSelector with anything but these two specializations
213 // they'll most likely get linker errors.
214 template class DecoderSelector<DemuxerStream::AUDIO>;
215 template class DecoderSelector<DemuxerStream::VIDEO>;
217 } // namespace media