Index: media/filters/decoder_selector.cc |
diff --git a/media/filters/decoder_selector.cc b/media/filters/decoder_selector.cc |
index 3f8a25f84b3170a3e5ebe873c2ec9403dfe10710..c520eb886226c90fb3ecdcacb1d38b6e45cd64fe 100644 |
--- a/media/filters/decoder_selector.cc |
+++ b/media/filters/decoder_selector.cc |
@@ -43,10 +43,10 @@ static bool HasValidStreamConfig(DemuxerStream* stream) { |
template <DemuxerStream::Type StreamType> |
DecoderSelector<StreamType>::DecoderSelector( |
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
- ScopedVector<Decoder> decoders, |
+ CreateDecodersCB create_decoders_cb, |
MediaLog* media_log) |
: task_runner_(task_runner), |
- decoders_(std::move(decoders)), |
+ create_decoders_cb_(std::move(create_decoders_cb)), |
media_log_(media_log), |
input_stream_(nullptr), |
weak_ptr_factory_(this) {} |
@@ -68,18 +68,17 @@ void DecoderSelector<StreamType>::SelectDecoder( |
StreamTraits* traits, |
DemuxerStream* stream, |
CdmContext* cdm_context, |
+ const std::string& blacklisted_decoder, |
const SelectDecoderCB& select_decoder_cb, |
const typename Decoder::OutputCB& output_cb, |
const base::Closure& waiting_for_decryption_key_cb) { |
- DVLOG(2) << __func__; |
+ DVLOG(2) << __func__ << ": cdm_context=" << cdm_context |
+ << ", blacklisted_decoder=" << blacklisted_decoder; |
DCHECK(task_runner_->BelongsToCurrentThread()); |
DCHECK(traits); |
DCHECK(stream); |
DCHECK(select_decoder_cb_.is_null()); |
- cdm_context_ = cdm_context; |
- waiting_for_decryption_key_cb_ = waiting_for_decryption_key_cb; |
- |
// Make sure |select_decoder_cb| runs on a different execution stack. |
select_decoder_cb_ = BindToCurrentLoop(select_decoder_cb); |
@@ -91,11 +90,20 @@ void DecoderSelector<StreamType>::SelectDecoder( |
traits_ = traits; |
input_stream_ = stream; |
+ cdm_context_ = cdm_context; |
+ blacklisted_decoder_ = blacklisted_decoder; |
output_cb_ = output_cb; |
+ waiting_for_decryption_key_cb_ = waiting_for_decryption_key_cb; |
+ |
+ decoders_ = create_decoders_cb_.Run(); |
+ config_ = StreamTraits::GetDecoderConfig(input_stream_); |
// When there is a CDM attached, always try the decrypting decoder or |
// demuxer-stream first. |
- if (cdm_context_) { |
+ if (config_.is_encrypted()) { |
+ DCHECK(cdm_context_); |
+// TODO(xhwang): This if-defined doesn't make a lot of sense. It should be |
+// replaced by some better checks. |
#if !defined(OS_ANDROID) |
InitializeDecryptingDecoder(); |
#else |
@@ -104,11 +112,6 @@ void DecoderSelector<StreamType>::SelectDecoder( |
return; |
} |
- config_ = StreamTraits::GetDecoderConfig(input_stream_); |
- |
- // If the input stream is encrypted, CdmContext must be non-null. |
- DCHECK(!config_.is_encrypted()); |
- |
InitializeDecoder(); |
} |
@@ -116,9 +119,16 @@ void DecoderSelector<StreamType>::SelectDecoder( |
template <DemuxerStream::Type StreamType> |
void DecoderSelector<StreamType>::InitializeDecryptingDecoder() { |
DVLOG(2) << __func__; |
+ |
decoder_.reset(new typename StreamTraits::DecryptingDecoderType( |
task_runner_, media_log_, waiting_for_decryption_key_cb_)); |
+ if (decoder_->GetDisplayName() == blacklisted_decoder_) { |
+ DVLOG(1) << __func__ << ": Decrypting decoder is blacklisted."; |
+ DecryptingDecoderInitDone(false); |
+ return; |
+ } |
+ |
traits_->InitializeDecoder( |
decoder_.get(), StreamTraits::GetDecoderConfig(input_stream_), |
input_stream_->liveness() == DemuxerStream::LIVENESS_LIVE, cdm_context_, |
@@ -134,6 +144,7 @@ void DecoderSelector<StreamType>::DecryptingDecoderInitDone(bool success) { |
if (success) { |
DVLOG(1) << __func__ << ": " << decoder_->GetDisplayName() << " selected."; |
+ decoders_.clear(); |
base::ResetAndReturn(&select_decoder_cb_) |
.Run(std::move(decoder_), std::unique_ptr<DecryptingDemuxerStream>()); |
return; |
@@ -177,11 +188,7 @@ void DecoderSelector<StreamType>::DecryptingDemuxerStreamInitDone( |
DCHECK(!config_.is_encrypted()); |
} else { |
decrypted_stream_.reset(); |
- config_ = StreamTraits::GetDecoderConfig(input_stream_); |
- |
- // Prefer decrypting decoder by using an encrypted config. |
- if (!config_.is_encrypted()) |
- config_.SetIsEncrypted(true); |
+ DCHECK(config_.is_encrypted()); |
} |
InitializeDecoder(); |
@@ -193,14 +200,24 @@ void DecoderSelector<StreamType>::InitializeDecoder() { |
DCHECK(task_runner_->BelongsToCurrentThread()); |
DCHECK(!decoder_); |
- if (decoders_.empty()) { |
+ // Select the next non-blacklisted decoder. |
+ while (!decoders_.empty()) { |
+ std::unique_ptr<Decoder> decoder(decoders_.front()); |
+ decoders_.weak_erase(decoders_.begin()); |
+ // When |decrypted_stream_| is selected, the |config_| has changed so ignore |
+ // the blacklist. |
+ if (decrypted_stream_ || |
+ decoder->GetDisplayName() != blacklisted_decoder_) { |
+ decoder_ = std::move(decoder); |
+ break; |
+ } |
+ } |
+ |
+ if (!decoder_) { |
ReturnNullDecoder(); |
return; |
} |
- decoder_.reset(decoders_.front()); |
- decoders_.weak_erase(decoders_.begin()); |
- |
traits_->InitializeDecoder( |
decoder_.get(), config_, |
input_stream_->liveness() == DemuxerStream::LIVENESS_LIVE, cdm_context_, |
@@ -224,6 +241,7 @@ void DecoderSelector<StreamType>::DecoderInitDone(bool success) { |
<< " selected. DecryptingDemuxerStream " |
<< (decrypted_stream_ ? "also" : "not") << " selected."; |
+ decoders_.clear(); |
base::ResetAndReturn(&select_decoder_cb_) |
.Run(std::move(decoder_), std::move(decrypted_stream_)); |
} |
@@ -232,6 +250,7 @@ template <DemuxerStream::Type StreamType> |
void DecoderSelector<StreamType>::ReturnNullDecoder() { |
DVLOG(1) << __func__ << ": No decoder selected."; |
DCHECK(task_runner_->BelongsToCurrentThread()); |
+ decoders_.clear(); |
base::ResetAndReturn(&select_decoder_cb_) |
.Run(std::unique_ptr<Decoder>(), |
std::unique_ptr<DecryptingDemuxerStream>()); |