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. 4 5 #include "decoder_selector.h" 6 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" 20 21 namespace media { 22 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(); 33 } 34 return false; 35 } 36 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(); 47 } 48 return false; 49 } 50 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) {} 61 62 template <DemuxerStream::Type StreamType> 63 DecoderSelector<StreamType>::~DecoderSelector() { 64 DVLOG(2) << __FUNCTION__; 65 DCHECK(select_decoder_cb_.is_null()); 66 } 67 68 template <DemuxerStream::Type StreamType> 69 void DecoderSelector<StreamType>::SelectDecoder( 70 DemuxerStream* stream, 71 bool low_delay, 72 const SelectDecoderCB& select_decoder_cb, 73 const typename Decoder::OutputCB& output_cb) { 74 DVLOG(2) << __FUNCTION__; 75 DCHECK(task_runner_->BelongsToCurrentThread()); 76 DCHECK(stream); 77 78 // Make sure |select_decoder_cb| runs on a different execution stack. 79 select_decoder_cb_ = BindToCurrentLoop(select_decoder_cb); 80 81 if (!HasValidStreamConfig(stream)) { 82 DLOG(ERROR) << "Invalid stream config."; 83 ReturnNullDecoder(); 84 return; 85 } 86 87 input_stream_ = stream; 88 low_delay_ = low_delay; 89 output_cb_ = output_cb; 90 91 if (!IsStreamEncrypted(input_stream_)) { 92 InitializeDecoder(); 93 return; 94 } 95 96 // This could happen if Encrypted Media Extension (EME) is not enabled. 97 if (set_decryptor_ready_cb_.is_null()) { 98 ReturnNullDecoder(); 99 return; 100 } 101 102 decoder_.reset(new typename StreamTraits::DecryptingDecoderType( 103 task_runner_, set_decryptor_ready_cb_)); 104 105 DecoderStreamTraits<StreamType>::Initialize( 106 decoder_.get(), 107 StreamTraits::GetDecoderConfig(*input_stream_), 108 low_delay_, 109 base::Bind(&DecoderSelector<StreamType>::DecryptingDecoderInitDone, 110 weak_ptr_factory_.GetWeakPtr()), 111 output_cb_); 112 } 113 114 template <DemuxerStream::Type StreamType> 115 void DecoderSelector<StreamType>::Abort() { 116 DVLOG(2) << __FUNCTION__; 117 DCHECK(task_runner_->BelongsToCurrentThread()); 118 119 // This could happen when SelectDecoder() was not called or when 120 // |select_decoder_cb_| was already posted but not fired (e.g. in the 121 // message loop queue). 122 if (select_decoder_cb_.is_null()) 123 return; 124 125 // We must be trying to initialize the |decoder_| or the 126 // |decrypted_stream_|. Invalid all weak pointers so that all initialization 127 // callbacks won't fire. 128 weak_ptr_factory_.InvalidateWeakPtrs(); 129 130 if (decoder_) { 131 // |decrypted_stream_| is either NULL or already initialized. We don't 132 // need to Stop() |decrypted_stream_| in either case. 133 decoder_->Stop(); 134 ReturnNullDecoder(); 135 return; 136 } 137 138 if (decrypted_stream_) { 139 decrypted_stream_->Stop( 140 base::Bind(&DecoderSelector<StreamType>::ReturnNullDecoder, 141 weak_ptr_factory_.GetWeakPtr())); 142 return; 143 } 144 145 NOTREACHED(); 146 } 147 148 template <DemuxerStream::Type StreamType> 149 void DecoderSelector<StreamType>::DecryptingDecoderInitDone( 150 PipelineStatus status) { 151 DVLOG(2) << __FUNCTION__; 152 DCHECK(task_runner_->BelongsToCurrentThread()); 153 154 if (status == PIPELINE_OK) { 155 base::ResetAndReturn(&select_decoder_cb_) 156 .Run(decoder_.Pass(), scoped_ptr<DecryptingDemuxerStream>()); 157 return; 158 } 159 160 decoder_.reset(); 161 162 decrypted_stream_.reset( 163 new DecryptingDemuxerStream(task_runner_, set_decryptor_ready_cb_)); 164 165 decrypted_stream_->Initialize( 166 input_stream_, 167 base::Bind(&DecoderSelector<StreamType>::DecryptingDemuxerStreamInitDone, 168 weak_ptr_factory_.GetWeakPtr())); 169 } 170 171 template <DemuxerStream::Type StreamType> 172 void DecoderSelector<StreamType>::DecryptingDemuxerStreamInitDone( 173 PipelineStatus status) { 174 DVLOG(2) << __FUNCTION__; 175 DCHECK(task_runner_->BelongsToCurrentThread()); 176 177 if (status != PIPELINE_OK) { 178 ReturnNullDecoder(); 179 return; 180 } 181 182 DCHECK(!IsStreamEncrypted(decrypted_stream_.get())); 183 input_stream_ = decrypted_stream_.get(); 184 InitializeDecoder(); 185 } 186 187 template <DemuxerStream::Type StreamType> 188 void DecoderSelector<StreamType>::InitializeDecoder() { 189 DVLOG(2) << __FUNCTION__; 190 DCHECK(task_runner_->BelongsToCurrentThread()); 191 DCHECK(!decoder_); 192 193 if (decoders_.empty()) { 194 ReturnNullDecoder(); 195 return; 196 } 197 198 decoder_.reset(decoders_.front()); 199 decoders_.weak_erase(decoders_.begin()); 200 201 DecoderStreamTraits<StreamType>::Initialize( 202 decoder_.get(), 203 StreamTraits::GetDecoderConfig(*input_stream_), 204 low_delay_, 205 base::Bind(&DecoderSelector<StreamType>::DecoderInitDone, 206 weak_ptr_factory_.GetWeakPtr()), 207 output_cb_); 208 } 209 210 template <DemuxerStream::Type StreamType> 211 void DecoderSelector<StreamType>::DecoderInitDone(PipelineStatus status) { 212 DVLOG(2) << __FUNCTION__; 213 DCHECK(task_runner_->BelongsToCurrentThread()); 214 215 if (status != PIPELINE_OK) { 216 decoder_.reset(); 217 InitializeDecoder(); 218 return; 219 } 220 221 base::ResetAndReturn(&select_decoder_cb_) 222 .Run(decoder_.Pass(), decrypted_stream_.Pass()); 223 } 224 225 template <DemuxerStream::Type StreamType> 226 void DecoderSelector<StreamType>::ReturnNullDecoder() { 227 DVLOG(2) << __FUNCTION__; 228 DCHECK(task_runner_->BelongsToCurrentThread()); 229 base::ResetAndReturn(&select_decoder_cb_) 230 .Run(scoped_ptr<Decoder>(), 231 scoped_ptr<DecryptingDemuxerStream>()); 232 } 233 234 // These forward declarations tell the compiler that we will use 235 // DecoderSelector with these arguments, allowing us to keep these definitions 236 // in our .cc without causing linker errors. This also means if anyone tries to 237 // instantiate a DecoderSelector with anything but these two specializations 238 // they'll most likely get linker errors. 239 template class DecoderSelector<DemuxerStream::AUDIO>; 240 template class DecoderSelector<DemuxerStream::VIDEO>; 241 242 } // namespace media 243