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(task_runner_->BelongsToCurrentThread()); 66 67 if (!select_decoder_cb_.is_null()) 68 ReturnNullDecoder(); 69 70 decoder_.reset(); 71 decrypted_stream_.reset(); 72} 73 74template <DemuxerStream::Type StreamType> 75void DecoderSelector<StreamType>::SelectDecoder( 76 DemuxerStream* stream, 77 bool low_delay, 78 const SelectDecoderCB& select_decoder_cb, 79 const typename Decoder::OutputCB& output_cb) { 80 DVLOG(2) << __FUNCTION__; 81 DCHECK(task_runner_->BelongsToCurrentThread()); 82 DCHECK(stream); 83 84 // Make sure |select_decoder_cb| runs on a different execution stack. 85 select_decoder_cb_ = BindToCurrentLoop(select_decoder_cb); 86 87 if (!HasValidStreamConfig(stream)) { 88 DLOG(ERROR) << "Invalid stream config."; 89 ReturnNullDecoder(); 90 return; 91 } 92 93 input_stream_ = stream; 94 low_delay_ = low_delay; 95 output_cb_ = output_cb; 96 97 if (!IsStreamEncrypted(input_stream_)) { 98 InitializeDecoder(); 99 return; 100 } 101 102 // This could happen if Encrypted Media Extension (EME) is not enabled. 103 if (set_decryptor_ready_cb_.is_null()) { 104 ReturnNullDecoder(); 105 return; 106 } 107 108 decoder_.reset(new typename StreamTraits::DecryptingDecoderType( 109 task_runner_, set_decryptor_ready_cb_)); 110 111 DecoderStreamTraits<StreamType>::Initialize( 112 decoder_.get(), 113 StreamTraits::GetDecoderConfig(*input_stream_), 114 low_delay_, 115 base::Bind(&DecoderSelector<StreamType>::DecryptingDecoderInitDone, 116 weak_ptr_factory_.GetWeakPtr()), 117 output_cb_); 118} 119 120template <DemuxerStream::Type StreamType> 121void DecoderSelector<StreamType>::DecryptingDecoderInitDone( 122 PipelineStatus status) { 123 DVLOG(2) << __FUNCTION__; 124 DCHECK(task_runner_->BelongsToCurrentThread()); 125 126 if (status == PIPELINE_OK) { 127 base::ResetAndReturn(&select_decoder_cb_) 128 .Run(decoder_.Pass(), scoped_ptr<DecryptingDemuxerStream>()); 129 return; 130 } 131 132 decoder_.reset(); 133 134 decrypted_stream_.reset( 135 new DecryptingDemuxerStream(task_runner_, set_decryptor_ready_cb_)); 136 137 decrypted_stream_->Initialize( 138 input_stream_, 139 base::Bind(&DecoderSelector<StreamType>::DecryptingDemuxerStreamInitDone, 140 weak_ptr_factory_.GetWeakPtr())); 141} 142 143template <DemuxerStream::Type StreamType> 144void DecoderSelector<StreamType>::DecryptingDemuxerStreamInitDone( 145 PipelineStatus status) { 146 DVLOG(2) << __FUNCTION__; 147 DCHECK(task_runner_->BelongsToCurrentThread()); 148 149 if (status != PIPELINE_OK) { 150 ReturnNullDecoder(); 151 return; 152 } 153 154 DCHECK(!IsStreamEncrypted(decrypted_stream_.get())); 155 input_stream_ = decrypted_stream_.get(); 156 InitializeDecoder(); 157} 158 159template <DemuxerStream::Type StreamType> 160void DecoderSelector<StreamType>::InitializeDecoder() { 161 DVLOG(2) << __FUNCTION__; 162 DCHECK(task_runner_->BelongsToCurrentThread()); 163 DCHECK(!decoder_); 164 165 if (decoders_.empty()) { 166 ReturnNullDecoder(); 167 return; 168 } 169 170 decoder_.reset(decoders_.front()); 171 decoders_.weak_erase(decoders_.begin()); 172 173 DecoderStreamTraits<StreamType>::Initialize( 174 decoder_.get(), 175 StreamTraits::GetDecoderConfig(*input_stream_), 176 low_delay_, 177 base::Bind(&DecoderSelector<StreamType>::DecoderInitDone, 178 weak_ptr_factory_.GetWeakPtr()), 179 output_cb_); 180} 181 182template <DemuxerStream::Type StreamType> 183void DecoderSelector<StreamType>::DecoderInitDone(PipelineStatus status) { 184 DVLOG(2) << __FUNCTION__; 185 DCHECK(task_runner_->BelongsToCurrentThread()); 186 187 if (status != PIPELINE_OK) { 188 decoder_.reset(); 189 InitializeDecoder(); 190 return; 191 } 192 193 base::ResetAndReturn(&select_decoder_cb_) 194 .Run(decoder_.Pass(), decrypted_stream_.Pass()); 195} 196 197template <DemuxerStream::Type StreamType> 198void DecoderSelector<StreamType>::ReturnNullDecoder() { 199 DVLOG(2) << __FUNCTION__; 200 DCHECK(task_runner_->BelongsToCurrentThread()); 201 base::ResetAndReturn(&select_decoder_cb_) 202 .Run(scoped_ptr<Decoder>(), 203 scoped_ptr<DecryptingDemuxerStream>()); 204} 205 206// These forward declarations tell the compiler that we will use 207// DecoderSelector with these arguments, allowing us to keep these definitions 208// in our .cc without causing linker errors. This also means if anyone tries to 209// instantiate a DecoderSelector with anything but these two specializations 210// they'll most likely get linker errors. 211template class DecoderSelector<DemuxerStream::AUDIO>; 212template class DecoderSelector<DemuxerStream::VIDEO>; 213 214} // namespace media 215