Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / media / filters / decoder_selector.cc
blob555a411bd760f97253bbe7a64e92637aea4a06d3
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 : task_runner_(task_runner),
56 decoders_(decoders.Pass()),
57 input_stream_(NULL),
58 weak_ptr_factory_(this) {
61 template <DemuxerStream::Type StreamType>
62 DecoderSelector<StreamType>::~DecoderSelector() {
63 DVLOG(2) << __FUNCTION__;
64 DCHECK(task_runner_->BelongsToCurrentThread());
66 if (!select_decoder_cb_.is_null())
67 ReturnNullDecoder();
69 decoder_.reset();
70 decrypted_stream_.reset();
73 template <DemuxerStream::Type StreamType>
74 void DecoderSelector<StreamType>::SelectDecoder(
75 DemuxerStream* stream,
76 const SetDecryptorReadyCB& set_decryptor_ready_cb,
77 const SelectDecoderCB& select_decoder_cb,
78 const typename Decoder::OutputCB& output_cb,
79 const base::Closure& waiting_for_decryption_key_cb) {
80 DVLOG(2) << __FUNCTION__;
81 DCHECK(task_runner_->BelongsToCurrentThread());
82 DCHECK(stream);
83 DCHECK(select_decoder_cb_.is_null());
85 set_decryptor_ready_cb_ = set_decryptor_ready_cb;
86 waiting_for_decryption_key_cb_ = waiting_for_decryption_key_cb;
88 // Make sure |select_decoder_cb| runs on a different execution stack.
89 select_decoder_cb_ = BindToCurrentLoop(select_decoder_cb);
91 if (!HasValidStreamConfig(stream)) {
92 DLOG(ERROR) << "Invalid stream config.";
93 ReturnNullDecoder();
94 return;
97 input_stream_ = stream;
98 output_cb_ = output_cb;
100 if (!IsStreamEncrypted(input_stream_)) {
101 InitializeDecoder();
102 return;
105 // This could be null if Encrypted Media Extension (EME) is not enabled.
106 if (set_decryptor_ready_cb_.is_null()) {
107 ReturnNullDecoder();
108 return;
111 decoder_.reset(new typename StreamTraits::DecryptingDecoderType(
112 task_runner_, set_decryptor_ready_cb_, waiting_for_decryption_key_cb_));
114 DecoderStreamTraits<StreamType>::InitializeDecoder(
115 decoder_.get(), input_stream_,
116 base::Bind(&DecoderSelector<StreamType>::DecryptingDecoderInitDone,
117 weak_ptr_factory_.GetWeakPtr()),
118 output_cb_);
121 template <DemuxerStream::Type StreamType>
122 void DecoderSelector<StreamType>::DecryptingDecoderInitDone(
123 PipelineStatus status) {
124 DVLOG(2) << __FUNCTION__;
125 DCHECK(task_runner_->BelongsToCurrentThread());
127 if (status == PIPELINE_OK) {
128 base::ResetAndReturn(&select_decoder_cb_)
129 .Run(decoder_.Pass(), scoped_ptr<DecryptingDemuxerStream>());
130 return;
133 decoder_.reset();
135 decrypted_stream_.reset(new DecryptingDemuxerStream(
136 task_runner_, set_decryptor_ready_cb_, waiting_for_decryption_key_cb_));
138 decrypted_stream_->Initialize(
139 input_stream_,
140 base::Bind(&DecoderSelector<StreamType>::DecryptingDemuxerStreamInitDone,
141 weak_ptr_factory_.GetWeakPtr()));
144 template <DemuxerStream::Type StreamType>
145 void DecoderSelector<StreamType>::DecryptingDemuxerStreamInitDone(
146 PipelineStatus status) {
147 DVLOG(2) << __FUNCTION__;
148 DCHECK(task_runner_->BelongsToCurrentThread());
150 if (status != PIPELINE_OK) {
151 ReturnNullDecoder();
152 return;
155 DCHECK(!IsStreamEncrypted(decrypted_stream_.get()));
156 input_stream_ = decrypted_stream_.get();
157 InitializeDecoder();
160 template <DemuxerStream::Type StreamType>
161 void DecoderSelector<StreamType>::InitializeDecoder() {
162 DVLOG(2) << __FUNCTION__;
163 DCHECK(task_runner_->BelongsToCurrentThread());
164 DCHECK(!decoder_);
166 if (decoders_.empty()) {
167 ReturnNullDecoder();
168 return;
171 decoder_.reset(decoders_.front());
172 decoders_.weak_erase(decoders_.begin());
174 DecoderStreamTraits<StreamType>::InitializeDecoder(
175 decoder_.get(), input_stream_,
176 base::Bind(&DecoderSelector<StreamType>::DecoderInitDone,
177 weak_ptr_factory_.GetWeakPtr()),
178 output_cb_);
181 template <DemuxerStream::Type StreamType>
182 void DecoderSelector<StreamType>::DecoderInitDone(PipelineStatus status) {
183 DVLOG(2) << __FUNCTION__;
184 DCHECK(task_runner_->BelongsToCurrentThread());
186 if (status != PIPELINE_OK) {
187 decoder_.reset();
188 InitializeDecoder();
189 return;
192 base::ResetAndReturn(&select_decoder_cb_)
193 .Run(decoder_.Pass(), decrypted_stream_.Pass());
196 template <DemuxerStream::Type StreamType>
197 void DecoderSelector<StreamType>::ReturnNullDecoder() {
198 DVLOG(2) << __FUNCTION__;
199 DCHECK(task_runner_->BelongsToCurrentThread());
200 base::ResetAndReturn(&select_decoder_cb_)
201 .Run(scoped_ptr<Decoder>(),
202 scoped_ptr<DecryptingDemuxerStream>());
205 // These forward declarations tell the compiler that we will use
206 // DecoderSelector with these arguments, allowing us to keep these definitions
207 // in our .cc without causing linker errors. This also means if anyone tries to
208 // instantiate a DecoderSelector with anything but these two specializations
209 // they'll most likely get linker errors.
210 template class DecoderSelector<DemuxerStream::AUDIO>;
211 template class DecoderSelector<DemuxerStream::VIDEO>;
213 } // namespace media