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 const CreateDecodersCB& create_decoders_cb, |
47 const scoped_refptr<MediaLog>& media_log) | 47 const scoped_refptr<MediaLog>& media_log) |
48 : task_runner_(task_runner), | 48 : task_runner_(task_runner), |
49 decoders_(std::move(decoders)), | 49 create_decoders_cb_(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, | |
sandersd (OOO until July 31)
2017/04/24 20:55:14
I worry that blacklisting a single decoder may be
xhwang
2017/04/25 00:43:30
We "could" host the same decoder via GVD and MVD,
| |
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__; |
75 DCHECK(task_runner_->BelongsToCurrentThread()); | 76 DCHECK(task_runner_->BelongsToCurrentThread()); |
76 DCHECK(traits); | 77 DCHECK(traits); |
77 DCHECK(stream); | 78 DCHECK(stream); |
78 DCHECK(select_decoder_cb_.is_null()); | 79 DCHECK(select_decoder_cb_.is_null()); |
79 | 80 |
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. | 81 // Make sure |select_decoder_cb| runs on a different execution stack. |
84 select_decoder_cb_ = BindToCurrentLoop(select_decoder_cb); | 82 select_decoder_cb_ = BindToCurrentLoop(select_decoder_cb); |
85 | 83 |
86 if (!HasValidStreamConfig(stream)) { | 84 if (!HasValidStreamConfig(stream)) { |
87 DLOG(ERROR) << "Invalid stream config."; | 85 DLOG(ERROR) << "Invalid stream config."; |
88 ReturnNullDecoder(); | 86 ReturnNullDecoder(); |
89 return; | 87 return; |
90 } | 88 } |
91 | 89 |
92 traits_ = traits; | 90 traits_ = traits; |
93 input_stream_ = stream; | 91 input_stream_ = stream; |
92 cdm_context_ = cdm_context; | |
93 blacklisted_decoder_ = blacklisted_decoder; | |
94 output_cb_ = output_cb; | 94 output_cb_ = output_cb; |
95 waiting_for_decryption_key_cb_ = waiting_for_decryption_key_cb; | |
96 | |
97 decoders_ = create_decoders_cb_.Run(); | |
98 config_ = StreamTraits::GetDecoderConfig(input_stream_); | |
95 | 99 |
96 // When there is a CDM attached, always try the decrypting decoder or | 100 // When there is a CDM attached, always try the decrypting decoder or |
97 // demuxer-stream first. | 101 // demuxer-stream first. |
98 if (cdm_context_) { | 102 if (config_.is_encrypted()) { |
103 DCHECK(cdm_context_); | |
104 // TODO(xhwang): This if-defined doesn't make a lot of sense. It should be | |
105 // replaced by some better checks. | |
99 #if !defined(DISABLE_FFMPEG_VIDEO_DECODERS) | 106 #if !defined(DISABLE_FFMPEG_VIDEO_DECODERS) |
100 InitializeDecryptingDecoder(); | 107 InitializeDecryptingDecoder(); |
101 #else | 108 #else |
102 InitializeDecryptingDemuxerStream(); | 109 InitializeDecryptingDemuxerStream(); |
103 #endif | 110 #endif |
104 return; | 111 return; |
105 } | 112 } |
106 | 113 |
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(); | 114 InitializeDecoder(); |
113 } | 115 } |
114 | 116 |
115 #if !defined(DISABLE_FFMPEG_VIDEO_DECODERS) | 117 #if !defined(DISABLE_FFMPEG_VIDEO_DECODERS) |
116 template <DemuxerStream::Type StreamType> | 118 template <DemuxerStream::Type StreamType> |
117 void DecoderSelector<StreamType>::InitializeDecryptingDecoder() { | 119 void DecoderSelector<StreamType>::InitializeDecryptingDecoder() { |
118 DVLOG(2) << __func__; | 120 DVLOG(2) << __func__; |
121 | |
119 decoder_.reset(new typename StreamTraits::DecryptingDecoderType( | 122 decoder_.reset(new typename StreamTraits::DecryptingDecoderType( |
120 task_runner_, media_log_, waiting_for_decryption_key_cb_)); | 123 task_runner_, media_log_, waiting_for_decryption_key_cb_)); |
121 | 124 |
125 if (decoder_->GetDisplayName() == blacklisted_decoder_) { | |
sandersd (OOO until July 31)
2017/04/24 20:55:14
This implies some new semantics for the DisplayNam
xhwang
2017/04/25 00:43:30
Good point. Will do!
| |
126 DecryptingDecoderInitDone(false); | |
127 return; | |
128 } | |
129 | |
122 traits_->InitializeDecoder( | 130 traits_->InitializeDecoder( |
123 decoder_.get(), StreamTraits::GetDecoderConfig(input_stream_), | 131 decoder_.get(), StreamTraits::GetDecoderConfig(input_stream_), |
124 input_stream_->liveness() == DemuxerStream::LIVENESS_LIVE, cdm_context_, | 132 input_stream_->liveness() == DemuxerStream::LIVENESS_LIVE, cdm_context_, |
125 base::Bind(&DecoderSelector<StreamType>::DecryptingDecoderInitDone, | 133 base::Bind(&DecoderSelector<StreamType>::DecryptingDecoderInitDone, |
126 weak_ptr_factory_.GetWeakPtr()), | 134 weak_ptr_factory_.GetWeakPtr()), |
127 output_cb_); | 135 output_cb_); |
128 } | 136 } |
129 | 137 |
130 template <DemuxerStream::Type StreamType> | 138 template <DemuxerStream::Type StreamType> |
131 void DecoderSelector<StreamType>::DecryptingDecoderInitDone(bool success) { | 139 void DecoderSelector<StreamType>::DecryptingDecoderInitDone(bool success) { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
170 // decryption and use a decoder to decode the clear stream. Otherwise, we'll | 178 // 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 | 179 // try to see whether any decoder can decrypt-and-decode the encrypted stream |
172 // directly. So in both cases, we'll initialize the decoders. | 180 // directly. So in both cases, we'll initialize the decoders. |
173 | 181 |
174 if (status == PIPELINE_OK) { | 182 if (status == PIPELINE_OK) { |
175 input_stream_ = decrypted_stream_.get(); | 183 input_stream_ = decrypted_stream_.get(); |
176 config_ = StreamTraits::GetDecoderConfig(input_stream_); | 184 config_ = StreamTraits::GetDecoderConfig(input_stream_); |
177 DCHECK(!config_.is_encrypted()); | 185 DCHECK(!config_.is_encrypted()); |
178 } else { | 186 } else { |
179 decrypted_stream_.reset(); | 187 decrypted_stream_.reset(); |
180 config_ = StreamTraits::GetDecoderConfig(input_stream_); | 188 DCHECK(config_.is_encrypted()); |
181 | |
182 // Prefer decrypting decoder by using an encrypted config. | |
183 if (!config_.is_encrypted()) | |
184 config_.SetIsEncrypted(true); | |
185 } | 189 } |
186 | 190 |
187 InitializeDecoder(); | 191 InitializeDecoder(); |
188 } | 192 } |
189 | 193 |
190 template <DemuxerStream::Type StreamType> | 194 template <DemuxerStream::Type StreamType> |
191 void DecoderSelector<StreamType>::InitializeDecoder() { | 195 void DecoderSelector<StreamType>::InitializeDecoder() { |
192 DVLOG(2) << __func__; | 196 DVLOG(2) << __func__; |
193 DCHECK(task_runner_->BelongsToCurrentThread()); | 197 DCHECK(task_runner_->BelongsToCurrentThread()); |
194 DCHECK(!decoder_); | 198 DCHECK(!decoder_); |
195 | 199 |
196 if (decoders_.empty()) { | 200 // Select the next non-blacklisted decoder. |
201 while (!decoders_.empty()) { | |
202 std::unique_ptr<Decoder> decoder(decoders_.front()); | |
203 decoders_.weak_erase(decoders_.begin()); | |
204 // When |decrypted_stream_| is selected, the |config_| has changed so ignore | |
DaleCurtis
2017/04/24 19:39:39
Can you explain this comment a bit more? The code
DaleCurtis
2017/04/24 19:41:04
Ah just saw your entry in the CL description now.
xhwang
2017/04/25 00:43:29
From my understanding, DecoderStream doesn't know
| |
205 // the blacklist. | |
206 if (decrypted_stream_ || | |
207 decoder->GetDisplayName() != blacklisted_decoder_) { | |
208 decoder_ = std::move(decoder); | |
209 break; | |
210 } | |
211 } | |
212 | |
213 if (!decoder_) { | |
197 ReturnNullDecoder(); | 214 ReturnNullDecoder(); |
198 return; | 215 return; |
199 } | 216 } |
200 | 217 |
201 decoder_.reset(decoders_.front()); | |
202 decoders_.weak_erase(decoders_.begin()); | |
203 | |
204 traits_->InitializeDecoder( | 218 traits_->InitializeDecoder( |
205 decoder_.get(), config_, | 219 decoder_.get(), config_, |
206 input_stream_->liveness() == DemuxerStream::LIVENESS_LIVE, cdm_context_, | 220 input_stream_->liveness() == DemuxerStream::LIVENESS_LIVE, cdm_context_, |
207 base::Bind(&DecoderSelector<StreamType>::DecoderInitDone, | 221 base::Bind(&DecoderSelector<StreamType>::DecoderInitDone, |
208 weak_ptr_factory_.GetWeakPtr()), | 222 weak_ptr_factory_.GetWeakPtr()), |
209 output_cb_); | 223 output_cb_); |
210 } | 224 } |
211 | 225 |
212 template <DemuxerStream::Type StreamType> | 226 template <DemuxerStream::Type StreamType> |
213 void DecoderSelector<StreamType>::DecoderInitDone(bool success) { | 227 void DecoderSelector<StreamType>::DecoderInitDone(bool success) { |
(...skipping 25 matching lines...) Expand all Loading... | |
239 | 253 |
240 // These forward declarations tell the compiler that we will use | 254 // These forward declarations tell the compiler that we will use |
241 // DecoderSelector with these arguments, allowing us to keep these definitions | 255 // 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 | 256 // in our .cc without causing linker errors. This also means if anyone tries to |
243 // instantiate a DecoderSelector with anything but these two specializations | 257 // instantiate a DecoderSelector with anything but these two specializations |
244 // they'll most likely get linker errors. | 258 // they'll most likely get linker errors. |
245 template class DecoderSelector<DemuxerStream::AUDIO>; | 259 template class DecoderSelector<DemuxerStream::AUDIO>; |
246 template class DecoderSelector<DemuxerStream::VIDEO>; | 260 template class DecoderSelector<DemuxerStream::VIDEO>; |
247 | 261 |
248 } // namespace media | 262 } // namespace media |
OLD | NEW |