Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(34)

Side by Side Diff: media/filters/decoder_selector.cc

Issue 2837613004: media: Support better decoder switching (Closed)
Patch Set: update GetDisplayName() comments Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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(DISABLE_FFMPEG_VIDEO_DECODERS) 107 #if !defined(DISABLE_FFMPEG_VIDEO_DECODERS)
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(DISABLE_FFMPEG_VIDEO_DECODERS) 118 #if !defined(DISABLE_FFMPEG_VIDEO_DECODERS)
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__ << ": Decryping decoder is blacklisted.";
watk 2017/05/04 21:35:33 decrypting
xhwang 2017/05/04 23:53:13 Done.
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
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();
watk 2017/05/04 21:35:33 Potentially, instead of saving decoders_ and makin
xhwang 2017/05/04 23:53:13 Acknowledged.
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698