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