decoder_selector.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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 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 114template <DemuxerStream::Type StreamType> 115void 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 148template <DemuxerStream::Type StreamType> 149void 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 171template <DemuxerStream::Type StreamType> 172void 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 187template <DemuxerStream::Type StreamType> 188void 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 210template <DemuxerStream::Type StreamType> 211void 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 225template <DemuxerStream::Type StreamType> 226void 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. 239template class DecoderSelector<DemuxerStream::AUDIO>; 240template class DecoderSelector<DemuxerStream::VIDEO>; 241 242} // namespace media 243