1 // Copyright (c) 2012 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 "media/filters/audio_decoder_selector.h" 6 7 #include "base/bind.h" 8 #include "base/callback_helpers.h" 9 #include "base/logging.h" 10 #include "base/message_loop/message_loop_proxy.h" 11 #include "media/base/audio_decoder_config.h" 12 #include "media/base/bind_to_loop.h" 13 #include "media/base/demuxer_stream.h" 14 #include "media/base/pipeline.h" 15 #include "media/filters/decrypting_audio_decoder.h" 16 #include "media/filters/decrypting_demuxer_stream.h" 17 18 namespace media { 19 20 AudioDecoderSelector::AudioDecoderSelector( 21 const scoped_refptr<base::MessageLoopProxy>& message_loop, 22 ScopedVector<AudioDecoder> decoders, 23 const SetDecryptorReadyCB& set_decryptor_ready_cb) 24 : message_loop_(message_loop), 25 decoders_(decoders.Pass()), 26 set_decryptor_ready_cb_(set_decryptor_ready_cb), 27 input_stream_(NULL), 28 weak_ptr_factory_(this) { 29 } 30 31 AudioDecoderSelector::~AudioDecoderSelector() { 32 DVLOG(2) << __FUNCTION__; 33 } 34 35 void AudioDecoderSelector::SelectAudioDecoder( 36 DemuxerStream* stream, 37 const StatisticsCB& statistics_cb, 38 const SelectDecoderCB& select_decoder_cb) { 39 DVLOG(2) << __FUNCTION__; 40 DCHECK(message_loop_->BelongsToCurrentThread()); 41 DCHECK(stream); 42 43 // Make sure |select_decoder_cb| runs on a different execution stack. 44 select_decoder_cb_ = BindToCurrentLoop(select_decoder_cb); 45 46 const AudioDecoderConfig& config = stream->audio_decoder_config(); 47 if (!config.IsValidConfig()) { 48 DLOG(ERROR) << "Invalid audio stream config."; 49 ReturnNullDecoder(); 50 return; 51 } 52 53 input_stream_ = stream; 54 statistics_cb_ = statistics_cb; 55 56 if (!config.is_encrypted()) { 57 InitializeDecoder(); 58 return; 59 } 60 61 // This could happen if Encrypted Media Extension (EME) is not enabled. 62 if (set_decryptor_ready_cb_.is_null()) { 63 ReturnNullDecoder(); 64 return; 65 } 66 67 audio_decoder_.reset(new DecryptingAudioDecoder( 68 message_loop_, set_decryptor_ready_cb_)); 69 70 audio_decoder_->Initialize( 71 input_stream_, 72 base::Bind(&AudioDecoderSelector::DecryptingAudioDecoderInitDone, 73 weak_ptr_factory_.GetWeakPtr()), 74 statistics_cb_); 75 } 76 77 void AudioDecoderSelector::Abort() { 78 DVLOG(2) << __FUNCTION__; 79 DCHECK(message_loop_->BelongsToCurrentThread()); 80 81 // This could happen when SelectAudioDecoder() was not called or when 82 // |select_decoder_cb_| was already posted but not fired (e.g. in the 83 // message loop queue). 84 if (select_decoder_cb_.is_null()) 85 return; 86 87 // We must be trying to initialize the |audio_decoder_| or the 88 // |decrypted_stream_|. Invalid all weak pointers so that all initialization 89 // callbacks won't fire. 90 weak_ptr_factory_.InvalidateWeakPtrs(); 91 92 if (audio_decoder_) { 93 // AudioDecoder doesn't provide a Stop() method. Also, |decrypted_stream_| 94 // is either NULL or already initialized. We don't need to Stop() 95 // |decrypted_stream_| in either case. 96 ReturnNullDecoder(); 97 return; 98 } 99 100 if (decrypted_stream_) { 101 decrypted_stream_->Stop( 102 base::Bind(&AudioDecoderSelector::ReturnNullDecoder, 103 weak_ptr_factory_.GetWeakPtr())); 104 return; 105 } 106 107 NOTREACHED(); 108 } 109 110 void AudioDecoderSelector::DecryptingAudioDecoderInitDone( 111 PipelineStatus status) { 112 DVLOG(2) << __FUNCTION__; 113 DCHECK(message_loop_->BelongsToCurrentThread()); 114 115 if (status == PIPELINE_OK) { 116 base::ResetAndReturn(&select_decoder_cb_).Run( 117 audio_decoder_.Pass(), scoped_ptr<DecryptingDemuxerStream>()); 118 return; 119 } 120 121 audio_decoder_.reset(); 122 123 decrypted_stream_.reset(new DecryptingDemuxerStream( 124 message_loop_, set_decryptor_ready_cb_)); 125 126 decrypted_stream_->Initialize( 127 input_stream_, 128 base::Bind(&AudioDecoderSelector::DecryptingDemuxerStreamInitDone, 129 weak_ptr_factory_.GetWeakPtr())); 130 } 131 132 void AudioDecoderSelector::DecryptingDemuxerStreamInitDone( 133 PipelineStatus status) { 134 DVLOG(2) << __FUNCTION__; 135 DCHECK(message_loop_->BelongsToCurrentThread()); 136 137 if (status != PIPELINE_OK) { 138 ReturnNullDecoder(); 139 return; 140 } 141 142 DCHECK(!decrypted_stream_->audio_decoder_config().is_encrypted()); 143 input_stream_ = decrypted_stream_.get(); 144 InitializeDecoder(); 145 } 146 147 void AudioDecoderSelector::InitializeDecoder() { 148 DVLOG(2) << __FUNCTION__; 149 DCHECK(message_loop_->BelongsToCurrentThread()); 150 DCHECK(!audio_decoder_); 151 152 if (decoders_.empty()) { 153 ReturnNullDecoder(); 154 return; 155 } 156 157 audio_decoder_.reset(decoders_.front()); 158 decoders_.weak_erase(decoders_.begin()); 159 160 audio_decoder_->Initialize(input_stream_, 161 base::Bind(&AudioDecoderSelector::DecoderInitDone, 162 weak_ptr_factory_.GetWeakPtr()), 163 statistics_cb_); 164 } 165 166 void AudioDecoderSelector::DecoderInitDone(PipelineStatus status) { 167 DVLOG(2) << __FUNCTION__; 168 DCHECK(message_loop_->BelongsToCurrentThread()); 169 170 if (status != PIPELINE_OK) { 171 audio_decoder_.reset(); 172 InitializeDecoder(); 173 return; 174 } 175 176 base::ResetAndReturn(&select_decoder_cb_).Run(audio_decoder_.Pass(), 177 decrypted_stream_.Pass()); 178 } 179 180 void AudioDecoderSelector::ReturnNullDecoder() { 181 DVLOG(2) << __FUNCTION__; 182 DCHECK(message_loop_->BelongsToCurrentThread()); 183 base::ResetAndReturn(&select_decoder_cb_).Run( 184 scoped_ptr<AudioDecoder>(), scoped_ptr<DecryptingDemuxerStream>()); 185 } 186 187 } // namespace media 188