| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/filters/decoder_selector.h" | 5 #include "media/filters/decoder_selector.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 case DemuxerStream::TEXT: | 36 case DemuxerStream::TEXT: |
| 37 case DemuxerStream::UNKNOWN: | 37 case DemuxerStream::UNKNOWN: |
| 38 NOTREACHED(); | 38 NOTREACHED(); |
| 39 } | 39 } |
| 40 return false; | 40 return false; |
| 41 } | 41 } |
| 42 | 42 |
| 43 template <DemuxerStream::Type StreamType> | 43 template <DemuxerStream::Type StreamType> |
| 44 DecoderSelector<StreamType>::DecoderSelector( | 44 DecoderSelector<StreamType>::DecoderSelector( |
| 45 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, | 45 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
| 46 ScopedVector<Decoder> decoders, | 46 CreateDecodersCB create_decoders_cb, |
| 47 MediaLog* media_log) | 47 MediaLog* media_log) |
| 48 : task_runner_(task_runner), | 48 : task_runner_(task_runner), |
| 49 decoders_(std::move(decoders)), | 49 create_decoders_cb_(std::move(create_decoders_cb)), |
| 50 media_log_(media_log), | 50 media_log_(media_log), |
| 51 input_stream_(nullptr), | 51 input_stream_(nullptr), |
| 52 weak_ptr_factory_(this) {} | 52 weak_ptr_factory_(this) {} |
| 53 | 53 |
| 54 template <DemuxerStream::Type StreamType> | 54 template <DemuxerStream::Type StreamType> |
| 55 DecoderSelector<StreamType>::~DecoderSelector() { | 55 DecoderSelector<StreamType>::~DecoderSelector() { |
| 56 DVLOG(2) << __func__; | 56 DVLOG(2) << __func__; |
| 57 DCHECK(task_runner_->BelongsToCurrentThread()); | 57 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 58 | 58 |
| 59 if (!select_decoder_cb_.is_null()) | 59 if (!select_decoder_cb_.is_null()) |
| 60 ReturnNullDecoder(); | 60 ReturnNullDecoder(); |
| 61 | 61 |
| 62 decoder_.reset(); | 62 decoder_.reset(); |
| 63 decrypted_stream_.reset(); | 63 decrypted_stream_.reset(); |
| 64 } | 64 } |
| 65 | 65 |
| 66 template <DemuxerStream::Type StreamType> | 66 template <DemuxerStream::Type StreamType> |
| 67 void DecoderSelector<StreamType>::SelectDecoder( | 67 void DecoderSelector<StreamType>::SelectDecoder( |
| 68 StreamTraits* traits, | 68 StreamTraits* traits, |
| 69 DemuxerStream* stream, | 69 DemuxerStream* stream, |
| 70 CdmContext* cdm_context, | 70 CdmContext* cdm_context, |
| 71 const std::string& blacklisted_decoder, |
| 71 const SelectDecoderCB& select_decoder_cb, | 72 const SelectDecoderCB& select_decoder_cb, |
| 72 const typename Decoder::OutputCB& output_cb, | 73 const typename Decoder::OutputCB& output_cb, |
| 73 const base::Closure& waiting_for_decryption_key_cb) { | 74 const base::Closure& waiting_for_decryption_key_cb) { |
| 74 DVLOG(2) << __func__; | 75 DVLOG(2) << __func__ << ": cdm_context=" << cdm_context |
| 76 << ", blacklisted_decoder=" << blacklisted_decoder; |
| 75 DCHECK(task_runner_->BelongsToCurrentThread()); | 77 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 76 DCHECK(traits); | 78 DCHECK(traits); |
| 77 DCHECK(stream); | 79 DCHECK(stream); |
| 78 DCHECK(select_decoder_cb_.is_null()); | 80 DCHECK(select_decoder_cb_.is_null()); |
| 79 | 81 |
| 80 cdm_context_ = cdm_context; | |
| 81 waiting_for_decryption_key_cb_ = waiting_for_decryption_key_cb; | |
| 82 | |
| 83 // Make sure |select_decoder_cb| runs on a different execution stack. | 82 // Make sure |select_decoder_cb| runs on a different execution stack. |
| 84 select_decoder_cb_ = BindToCurrentLoop(select_decoder_cb); | 83 select_decoder_cb_ = BindToCurrentLoop(select_decoder_cb); |
| 85 | 84 |
| 86 if (!HasValidStreamConfig(stream)) { | 85 if (!HasValidStreamConfig(stream)) { |
| 87 DLOG(ERROR) << "Invalid stream config."; | 86 DLOG(ERROR) << "Invalid stream config."; |
| 88 ReturnNullDecoder(); | 87 ReturnNullDecoder(); |
| 89 return; | 88 return; |
| 90 } | 89 } |
| 91 | 90 |
| 92 traits_ = traits; | 91 traits_ = traits; |
| 93 input_stream_ = stream; | 92 input_stream_ = stream; |
| 93 cdm_context_ = cdm_context; |
| 94 blacklisted_decoder_ = blacklisted_decoder; |
| 94 output_cb_ = output_cb; | 95 output_cb_ = output_cb; |
| 96 waiting_for_decryption_key_cb_ = waiting_for_decryption_key_cb; |
| 97 |
| 98 decoders_ = create_decoders_cb_.Run(); |
| 99 config_ = StreamTraits::GetDecoderConfig(input_stream_); |
| 95 | 100 |
| 96 // When there is a CDM attached, always try the decrypting decoder or | 101 // When there is a CDM attached, always try the decrypting decoder or |
| 97 // demuxer-stream first. | 102 // demuxer-stream first. |
| 98 if (cdm_context_) { | 103 if (config_.is_encrypted()) { |
| 104 DCHECK(cdm_context_); |
| 105 // TODO(xhwang): This if-defined doesn't make a lot of sense. It should be |
| 106 // replaced by some better checks. |
| 99 #if !defined(OS_ANDROID) | 107 #if !defined(OS_ANDROID) |
| 100 InitializeDecryptingDecoder(); | 108 InitializeDecryptingDecoder(); |
| 101 #else | 109 #else |
| 102 InitializeDecryptingDemuxerStream(); | 110 InitializeDecryptingDemuxerStream(); |
| 103 #endif | 111 #endif |
| 104 return; | 112 return; |
| 105 } | 113 } |
| 106 | 114 |
| 107 config_ = StreamTraits::GetDecoderConfig(input_stream_); | |
| 108 | |
| 109 // If the input stream is encrypted, CdmContext must be non-null. | |
| 110 DCHECK(!config_.is_encrypted()); | |
| 111 | |
| 112 InitializeDecoder(); | 115 InitializeDecoder(); |
| 113 } | 116 } |
| 114 | 117 |
| 115 #if !defined(OS_ANDROID) | 118 #if !defined(OS_ANDROID) |
| 116 template <DemuxerStream::Type StreamType> | 119 template <DemuxerStream::Type StreamType> |
| 117 void DecoderSelector<StreamType>::InitializeDecryptingDecoder() { | 120 void DecoderSelector<StreamType>::InitializeDecryptingDecoder() { |
| 118 DVLOG(2) << __func__; | 121 DVLOG(2) << __func__; |
| 122 |
| 119 decoder_.reset(new typename StreamTraits::DecryptingDecoderType( | 123 decoder_.reset(new typename StreamTraits::DecryptingDecoderType( |
| 120 task_runner_, media_log_, waiting_for_decryption_key_cb_)); | 124 task_runner_, media_log_, waiting_for_decryption_key_cb_)); |
| 121 | 125 |
| 126 if (decoder_->GetDisplayName() == blacklisted_decoder_) { |
| 127 DVLOG(1) << __func__ << ": Decrypting decoder is blacklisted."; |
| 128 DecryptingDecoderInitDone(false); |
| 129 return; |
| 130 } |
| 131 |
| 122 traits_->InitializeDecoder( | 132 traits_->InitializeDecoder( |
| 123 decoder_.get(), StreamTraits::GetDecoderConfig(input_stream_), | 133 decoder_.get(), StreamTraits::GetDecoderConfig(input_stream_), |
| 124 input_stream_->liveness() == DemuxerStream::LIVENESS_LIVE, cdm_context_, | 134 input_stream_->liveness() == DemuxerStream::LIVENESS_LIVE, cdm_context_, |
| 125 base::Bind(&DecoderSelector<StreamType>::DecryptingDecoderInitDone, | 135 base::Bind(&DecoderSelector<StreamType>::DecryptingDecoderInitDone, |
| 126 weak_ptr_factory_.GetWeakPtr()), | 136 weak_ptr_factory_.GetWeakPtr()), |
| 127 output_cb_); | 137 output_cb_); |
| 128 } | 138 } |
| 129 | 139 |
| 130 template <DemuxerStream::Type StreamType> | 140 template <DemuxerStream::Type StreamType> |
| 131 void DecoderSelector<StreamType>::DecryptingDecoderInitDone(bool success) { | 141 void DecoderSelector<StreamType>::DecryptingDecoderInitDone(bool success) { |
| 132 DVLOG(2) << __func__ << ": success=" << success; | 142 DVLOG(2) << __func__ << ": success=" << success; |
| 133 DCHECK(task_runner_->BelongsToCurrentThread()); | 143 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 134 | 144 |
| 135 if (success) { | 145 if (success) { |
| 136 DVLOG(1) << __func__ << ": " << decoder_->GetDisplayName() << " selected."; | 146 DVLOG(1) << __func__ << ": " << decoder_->GetDisplayName() << " selected."; |
| 147 decoders_.clear(); |
| 137 base::ResetAndReturn(&select_decoder_cb_) | 148 base::ResetAndReturn(&select_decoder_cb_) |
| 138 .Run(std::move(decoder_), std::unique_ptr<DecryptingDemuxerStream>()); | 149 .Run(std::move(decoder_), std::unique_ptr<DecryptingDemuxerStream>()); |
| 139 return; | 150 return; |
| 140 } | 151 } |
| 141 | 152 |
| 142 decoder_.reset(); | 153 decoder_.reset(); |
| 143 | 154 |
| 144 // When we get here decrypt-and-decode is not supported. Try to use | 155 // When we get here decrypt-and-decode is not supported. Try to use |
| 145 // DecryptingDemuxerStream to do decrypt-only. | 156 // DecryptingDemuxerStream to do decrypt-only. |
| 146 InitializeDecryptingDemuxerStream(); | 157 InitializeDecryptingDemuxerStream(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 170 // decryption and use a decoder to decode the clear stream. Otherwise, we'll | 181 // decryption and use a decoder to decode the clear stream. Otherwise, we'll |
| 171 // try to see whether any decoder can decrypt-and-decode the encrypted stream | 182 // try to see whether any decoder can decrypt-and-decode the encrypted stream |
| 172 // directly. So in both cases, we'll initialize the decoders. | 183 // directly. So in both cases, we'll initialize the decoders. |
| 173 | 184 |
| 174 if (status == PIPELINE_OK) { | 185 if (status == PIPELINE_OK) { |
| 175 input_stream_ = decrypted_stream_.get(); | 186 input_stream_ = decrypted_stream_.get(); |
| 176 config_ = StreamTraits::GetDecoderConfig(input_stream_); | 187 config_ = StreamTraits::GetDecoderConfig(input_stream_); |
| 177 DCHECK(!config_.is_encrypted()); | 188 DCHECK(!config_.is_encrypted()); |
| 178 } else { | 189 } else { |
| 179 decrypted_stream_.reset(); | 190 decrypted_stream_.reset(); |
| 180 config_ = StreamTraits::GetDecoderConfig(input_stream_); | 191 DCHECK(config_.is_encrypted()); |
| 181 | |
| 182 // Prefer decrypting decoder by using an encrypted config. | |
| 183 if (!config_.is_encrypted()) | |
| 184 config_.SetIsEncrypted(true); | |
| 185 } | 192 } |
| 186 | 193 |
| 187 InitializeDecoder(); | 194 InitializeDecoder(); |
| 188 } | 195 } |
| 189 | 196 |
| 190 template <DemuxerStream::Type StreamType> | 197 template <DemuxerStream::Type StreamType> |
| 191 void DecoderSelector<StreamType>::InitializeDecoder() { | 198 void DecoderSelector<StreamType>::InitializeDecoder() { |
| 192 DVLOG(2) << __func__; | 199 DVLOG(2) << __func__; |
| 193 DCHECK(task_runner_->BelongsToCurrentThread()); | 200 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 194 DCHECK(!decoder_); | 201 DCHECK(!decoder_); |
| 195 | 202 |
| 196 if (decoders_.empty()) { | 203 // Select the next non-blacklisted decoder. |
| 204 while (!decoders_.empty()) { |
| 205 std::unique_ptr<Decoder> decoder(decoders_.front()); |
| 206 decoders_.weak_erase(decoders_.begin()); |
| 207 // When |decrypted_stream_| is selected, the |config_| has changed so ignore |
| 208 // the blacklist. |
| 209 if (decrypted_stream_ || |
| 210 decoder->GetDisplayName() != blacklisted_decoder_) { |
| 211 decoder_ = std::move(decoder); |
| 212 break; |
| 213 } |
| 214 } |
| 215 |
| 216 if (!decoder_) { |
| 197 ReturnNullDecoder(); | 217 ReturnNullDecoder(); |
| 198 return; | 218 return; |
| 199 } | 219 } |
| 200 | 220 |
| 201 decoder_.reset(decoders_.front()); | |
| 202 decoders_.weak_erase(decoders_.begin()); | |
| 203 | |
| 204 traits_->InitializeDecoder( | 221 traits_->InitializeDecoder( |
| 205 decoder_.get(), config_, | 222 decoder_.get(), config_, |
| 206 input_stream_->liveness() == DemuxerStream::LIVENESS_LIVE, cdm_context_, | 223 input_stream_->liveness() == DemuxerStream::LIVENESS_LIVE, cdm_context_, |
| 207 base::Bind(&DecoderSelector<StreamType>::DecoderInitDone, | 224 base::Bind(&DecoderSelector<StreamType>::DecoderInitDone, |
| 208 weak_ptr_factory_.GetWeakPtr()), | 225 weak_ptr_factory_.GetWeakPtr()), |
| 209 output_cb_); | 226 output_cb_); |
| 210 } | 227 } |
| 211 | 228 |
| 212 template <DemuxerStream::Type StreamType> | 229 template <DemuxerStream::Type StreamType> |
| 213 void DecoderSelector<StreamType>::DecoderInitDone(bool success) { | 230 void DecoderSelector<StreamType>::DecoderInitDone(bool success) { |
| 214 DVLOG(2) << __func__ << ": success=" << success; | 231 DVLOG(2) << __func__ << ": success=" << success; |
| 215 DCHECK(task_runner_->BelongsToCurrentThread()); | 232 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 216 | 233 |
| 217 if (!success) { | 234 if (!success) { |
| 218 decoder_.reset(); | 235 decoder_.reset(); |
| 219 InitializeDecoder(); | 236 InitializeDecoder(); |
| 220 return; | 237 return; |
| 221 } | 238 } |
| 222 | 239 |
| 223 DVLOG(1) << __func__ << ": " << decoder_->GetDisplayName() | 240 DVLOG(1) << __func__ << ": " << decoder_->GetDisplayName() |
| 224 << " selected. DecryptingDemuxerStream " | 241 << " selected. DecryptingDemuxerStream " |
| 225 << (decrypted_stream_ ? "also" : "not") << " selected."; | 242 << (decrypted_stream_ ? "also" : "not") << " selected."; |
| 226 | 243 |
| 244 decoders_.clear(); |
| 227 base::ResetAndReturn(&select_decoder_cb_) | 245 base::ResetAndReturn(&select_decoder_cb_) |
| 228 .Run(std::move(decoder_), std::move(decrypted_stream_)); | 246 .Run(std::move(decoder_), std::move(decrypted_stream_)); |
| 229 } | 247 } |
| 230 | 248 |
| 231 template <DemuxerStream::Type StreamType> | 249 template <DemuxerStream::Type StreamType> |
| 232 void DecoderSelector<StreamType>::ReturnNullDecoder() { | 250 void DecoderSelector<StreamType>::ReturnNullDecoder() { |
| 233 DVLOG(1) << __func__ << ": No decoder selected."; | 251 DVLOG(1) << __func__ << ": No decoder selected."; |
| 234 DCHECK(task_runner_->BelongsToCurrentThread()); | 252 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 253 decoders_.clear(); |
| 235 base::ResetAndReturn(&select_decoder_cb_) | 254 base::ResetAndReturn(&select_decoder_cb_) |
| 236 .Run(std::unique_ptr<Decoder>(), | 255 .Run(std::unique_ptr<Decoder>(), |
| 237 std::unique_ptr<DecryptingDemuxerStream>()); | 256 std::unique_ptr<DecryptingDemuxerStream>()); |
| 238 } | 257 } |
| 239 | 258 |
| 240 // These forward declarations tell the compiler that we will use | 259 // These forward declarations tell the compiler that we will use |
| 241 // DecoderSelector with these arguments, allowing us to keep these definitions | 260 // DecoderSelector with these arguments, allowing us to keep these definitions |
| 242 // in our .cc without causing linker errors. This also means if anyone tries to | 261 // in our .cc without causing linker errors. This also means if anyone tries to |
| 243 // instantiate a DecoderSelector with anything but these two specializations | 262 // instantiate a DecoderSelector with anything but these two specializations |
| 244 // they'll most likely get linker errors. | 263 // they'll most likely get linker errors. |
| 245 template class DecoderSelector<DemuxerStream::AUDIO>; | 264 template class DecoderSelector<DemuxerStream::AUDIO>; |
| 246 template class DecoderSelector<DemuxerStream::VIDEO>; | 265 template class DecoderSelector<DemuxerStream::VIDEO>; |
| 247 | 266 |
| 248 } // namespace media | 267 } // namespace media |
| OLD | NEW |