[M120 Migration][hbbtv] Audio tracks count notification
[platform/framework/web/chromium-efl.git] / media / filters / decoder_selector.cc
1 // Copyright 2014 The Chromium Authors
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/decoder_selector.h"
6
7 #include <algorithm>
8 #include <utility>
9
10 #include "base/feature_list.h"
11 #include "base/functional/bind.h"
12 #include "base/functional/callback_helpers.h"
13 #include "base/location.h"
14 #include "base/logging.h"
15 #include "base/metrics/histogram_functions.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/task/sequenced_task_runner.h"
18 #include "base/trace_event/trace_event.h"
19 #include "build/build_config.h"
20 #include "build/chromeos_buildflags.h"
21 #include "media/base/audio_decoder.h"
22 #include "media/base/cdm_context.h"
23 #include "media/base/demuxer_stream.h"
24 #include "media/base/media_log.h"
25 #include "media/base/media_switches.h"
26 #include "media/base/video_decoder.h"
27 #include "media/filters/decoder_stream_traits.h"
28 #include "media/filters/decrypting_demuxer_stream.h"
29
30 namespace media {
31
32 namespace {
33
34 const char kSelectDecoderTrace[] = "DecoderSelector::SelectDecoder";
35
36 bool SkipDecoderForRTC(const AudioDecoderConfig& /*config*/,
37                        const AudioDecoder& /*decoder*/) {
38   return false;
39 }
40
41 bool SkipDecoderForRTC(const VideoDecoderConfig& config,
42                        const VideoDecoder& decoder) {
43   // Skip non-platform decoders for rtc based on the feature flag.
44   return config.is_rtc() && !decoder.IsPlatformDecoder() &&
45          !base::FeatureList::IsEnabled(kExposeSwDecodersToWebRTC);
46 }
47
48 template <typename ConfigT, typename DecoderT>
49 DecoderPriority NormalDecoderPriority(const ConfigT& config,
50                                       const DecoderT& decoder) {
51   if (SkipDecoderForRTC(config, decoder))
52     return DecoderPriority::kSkipped;
53
54   return DecoderPriority::kNormal;
55 }
56
57 DecoderPriority ResolutionBasedDecoderPriority(const VideoDecoderConfig& config,
58                                                const VideoDecoder& decoder) {
59 #if BUILDFLAG(IS_ANDROID)
60   constexpr auto kSoftwareDecoderHeightCutoff = 360;
61 #elif BUILDFLAG(IS_CHROMEOS_ASH)
62   constexpr auto kSoftwareDecoderHeightCutoff = 360;
63 #else
64   constexpr auto kSoftwareDecoderHeightCutoff = 720;
65 #endif
66
67   if (SkipDecoderForRTC(config, decoder))
68     return DecoderPriority::kSkipped;
69
70   // We only do a height check to err on the side of prioritizing platform
71   // decoders.
72   const auto at_or_above_software_cutoff =
73       config.visible_rect().height() >= kSoftwareDecoderHeightCutoff;
74
75   // Platform decoders are deprioritized below the cutoff, and non-platform
76   // decoders are deprioritized above it.
77   return at_or_above_software_cutoff == decoder.IsPlatformDecoder()
78              ? DecoderPriority::kNormal
79              : DecoderPriority::kDeprioritized;
80 }
81
82 DecoderPriority PreferNonPlatformDecoders(const VideoDecoderConfig& config,
83                                           const VideoDecoder& decoder) {
84   // Prefer software decoders over hardware decoders.  This is useful to force
85   // software fallback for WebRTC, but still use hardware if there's no software
86   // implementation to choose.
87   return decoder.IsPlatformDecoder() ? DecoderPriority::kDeprioritized
88                                      : DecoderPriority::kNormal;
89 }
90
91 DecoderPriority UnifiedDecoderPriority(const VideoDecoderConfig& config,
92                                        const VideoDecoder& decoder) {
93   if (config.is_rtc() ||
94       base::FeatureList::IsEnabled(kResolutionBasedDecoderPriority)) {
95     return ResolutionBasedDecoderPriority(config, decoder);
96   } else {
97     return NormalDecoderPriority(config, decoder);
98   }
99 }
100
101 template <typename ConfigT, typename DecoderT>
102 DecoderPriority SkipNonPlatformDecoders(const ConfigT& config,
103                                         const DecoderT& decoder) {
104   if (SkipDecoderForRTC(config, decoder))
105     return DecoderPriority::kSkipped;
106
107   return decoder.IsPlatformDecoder() ? DecoderPriority::kNormal
108                                      : DecoderPriority::kSkipped;
109 }
110
111 void SetDefaultDecoderPriorityCB(
112     VideoDecoderSelector::DecoderPriorityCB* out,
113     const DecoderStreamTraits<DemuxerStream::VIDEO>* traits) {
114   if (base::FeatureList::IsEnabled(kForceHardwareVideoDecoders)) {
115     *out = base::BindRepeating(
116         SkipNonPlatformDecoders<VideoDecoderConfig, VideoDecoder>);
117   } else if (traits->GetPreferNonPlatformDecoders()) {
118     *out = base::BindRepeating(PreferNonPlatformDecoders);
119   } else {
120     *out = base::BindRepeating(UnifiedDecoderPriority);
121   }
122 }
123
124 void SetDefaultDecoderPriorityCB(
125     AudioDecoderSelector::DecoderPriorityCB* out,
126     const DecoderStreamTraits<DemuxerStream::AUDIO>*) {
127   if (base::FeatureList::IsEnabled(kForceHardwareAudioDecoders)) {
128     *out = base::BindRepeating(
129         SkipNonPlatformDecoders<AudioDecoderConfig, AudioDecoder>);
130   } else {
131     // Platform audio decoders are not currently prioritized or deprioritized
132     *out = base::BindRepeating(
133         NormalDecoderPriority<AudioDecoderConfig, AudioDecoder>);
134   }
135 }
136
137 }  // namespace
138
139 template <DemuxerStream::Type StreamType>
140 DecoderSelector<StreamType>::DecoderSelector(
141     scoped_refptr<base::SequencedTaskRunner> task_runner,
142     CreateDecodersCB create_decoders_cb,
143     MediaLog* media_log)
144     : task_runner_(std::move(task_runner)),
145       create_decoders_cb_(std::move(create_decoders_cb)),
146       media_log_(media_log) {
147   DETACH_FROM_SEQUENCE(sequence_checker_);
148 }
149
150 template <DemuxerStream::Type StreamType>
151 DecoderSelector<StreamType>::~DecoderSelector() {
152   DVLOG(2) << __func__;
153   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
154   if (select_decoder_cb_)
155     ReturnSelectionError(DecoderStatus::Codes::kFailed);
156 }
157
158 template <DemuxerStream::Type StreamType>
159 void DecoderSelector<StreamType>::Initialize(StreamTraits* traits,
160                                              DemuxerStream* stream,
161                                              CdmContext* cdm_context,
162                                              WaitingCB waiting_cb) {
163   DVLOG(2) << __func__;
164   DCHECK(traits);
165   DCHECK(stream);
166
167   traits_ = traits;
168   stream_ = stream;
169   cdm_context_ = cdm_context;
170   waiting_cb_ = std::move(waiting_cb);
171   // Only set this here if nobody has overridden it for tests.
172   if (!decoder_priority_cb_)
173     SetDefaultDecoderPriorityCB(&decoder_priority_cb_, traits_);
174 }
175
176 template <DemuxerStream::Type StreamType>
177 void DecoderSelector<StreamType>::SelectDecoderInternal(
178     SelectDecoderCB select_decoder_cb,
179     typename Decoder::OutputCB output_cb,
180     bool needs_new_decoders) {
181   DVLOG(2) << __func__;
182   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
183   DCHECK(select_decoder_cb);
184   DCHECK(!select_decoder_cb_);
185   select_decoder_cb_ = std::move(select_decoder_cb);
186   output_cb_ = std::move(output_cb);
187   config_ = traits_->GetDecoderConfig(stream_);
188
189   TRACE_EVENT_ASYNC_BEGIN2("media", kSelectDecoderTrace, this, "type",
190                            DemuxerStream::GetTypeName(StreamType), "config",
191                            config_.AsHumanReadableString());
192
193   if (!config_.IsValidConfig()) {
194     DLOG(ERROR) << "Invalid stream config";
195     ReturnSelectionError(DecoderStatus::Codes::kUnsupportedConfig);
196     return;
197   }
198
199   if (needs_new_decoders) {
200     decode_failure_reinit_cause_ = absl::nullopt;
201     CreateDecoders();
202   }
203
204   GetAndInitializeNextDecoder();
205 }
206
207 template <DemuxerStream::Type StreamType>
208 void DecoderSelector<StreamType>::BeginDecoderSelection(
209     SelectDecoderCB select_decoder_cb,
210     typename Decoder::OutputCB output_cb) {
211   SelectDecoderInternal(std::move(select_decoder_cb), std::move(output_cb),
212                         /*needs_new_decoders = */ true);
213 }
214
215 template <DemuxerStream::Type StreamType>
216 void DecoderSelector<StreamType>::ResumeDecoderSelection(
217     SelectDecoderCB select_decoder_cb,
218     typename Decoder::OutputCB output_cb,
219     DecoderStatus&& reinit_cause) {
220   DVLOG(2) << __func__;
221   if (!decode_failure_reinit_cause_.has_value())
222     decode_failure_reinit_cause_ = std::move(reinit_cause);
223   SelectDecoderInternal(std::move(select_decoder_cb), std::move(output_cb),
224                         /*needs_new_decoders = */ false);
225 }
226
227 template <DemuxerStream::Type StreamType>
228 void DecoderSelector<StreamType>::FinalizeDecoderSelection() {
229   DVLOG(2) << __func__;
230   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
231   DCHECK(!select_decoder_cb_);
232
233   // Discard any remaining decoder instances, they won't be used.
234   decoders_.clear();
235 }
236
237 template <DemuxerStream::Type StreamType>
238 void DecoderSelector<StreamType>::PrependDecoder(
239     std::unique_ptr<Decoder> decoder) {
240   DVLOG(2) << __func__;
241   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
242
243   // Decoders inserted directly should be given priority over those returned by
244   // |create_decoders_cb_|.
245   decoders_.insert(decoders_.begin(), std::move(decoder));
246   FilterAndSortAvailableDecoders();
247 }
248
249 template <DemuxerStream::Type StreamType>
250 void DecoderSelector<StreamType>::OverrideDecoderPriorityCBForTesting(
251     DecoderPriorityCB decoder_priority_cb) {
252   decoder_priority_cb_ = std::move(decoder_priority_cb);
253 }
254
255 template <DemuxerStream::Type StreamType>
256 void DecoderSelector<StreamType>::CreateDecoders() {
257   // Post-insert decoders returned by `create_decoders_cb_`, so that
258   // any decoders added via `PrependDecoder()` are not overwritten and retain
259   // priority (even if they are ultimately de-ranked by
260   // `FilterAndSortAvailableDecoders()`)
261   auto new_decoders = create_decoders_cb_.Run();
262   std::move(new_decoders.begin(), new_decoders.end(),
263             std::inserter(decoders_, decoders_.end()));
264   FilterAndSortAvailableDecoders();
265 }
266
267 template <DemuxerStream::Type StreamType>
268 void DecoderSelector<StreamType>::GetAndInitializeNextDecoder() {
269   DVLOG(2) << __func__;
270   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
271   DCHECK(!decoder_);
272
273   if (decoders_.empty()) {
274     // Decoder selection failed. If the stream is encrypted, try again using
275     // DecryptingDemuxerStream.
276     if (config_.is_encrypted() && cdm_context_) {
277       InitializeDecryptingDemuxerStream();
278       return;
279     }
280
281     if (decode_failure_reinit_cause_.has_value()) {
282       ReturnSelectionError(std::move(*decode_failure_reinit_cause_));
283     } else {
284       ReturnSelectionError(DecoderStatus::Codes::kUnsupportedConfig);
285     }
286     return;
287   }
288
289   // Initialize the first decoder on the list.
290   decoder_ = std::move(decoders_.front());
291   decoders_.erase(decoders_.begin());
292   TRACE_EVENT_ASYNC_STEP_INTO0("media", kSelectDecoderTrace, this,
293                                GetDecoderName(decoder_->GetDecoderType()));
294
295   DVLOG(2) << __func__ << ": initializing " << decoder_->GetDecoderType();
296   const bool is_live = stream_->liveness() == StreamLiveness::kLive;
297   traits_->InitializeDecoder(
298       decoder_.get(), config_, is_live, cdm_context_,
299       base::BindOnce(&DecoderSelector<StreamType>::OnDecoderInitializeDone,
300                      weak_this_factory_.GetWeakPtr()),
301       output_cb_, waiting_cb_);
302 }
303
304 template <DemuxerStream::Type StreamType>
305 void DecoderSelector<StreamType>::OnDecoderInitializeDone(
306     DecoderStatus status) {
307   DCHECK(decoder_);
308   DVLOG(2) << __func__ << ": " << decoder_->GetDecoderType()
309            << " success=" << static_cast<int>(status.code());
310   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
311
312   if (!status.is_ok()) {
313     // Note: Don't track this decode status, as it is the result of decoder
314     // selection (initialization) failure.
315     MEDIA_LOG(INFO, media_log_)
316         << "Cannot select " << decoder_->GetDecoderType() << " for "
317         << DemuxerStream::GetTypeName(StreamType) << " decoding";
318
319     // Try the next decoder on the list.
320     decoder_ = nullptr;
321     GetAndInitializeNextDecoder();
322     return;
323   }
324
325   RunSelectDecoderCB(std::move(decoder_));
326 }
327
328 template <DemuxerStream::Type StreamType>
329 void DecoderSelector<StreamType>::ReturnSelectionError(DecoderStatus error) {
330   DVLOG(1) << __func__ << ": No decoder selected";
331   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
332   DCHECK(!error.is_ok());
333
334   decrypting_demuxer_stream_.reset();
335   decoders_.clear();
336   RunSelectDecoderCB(std::move(error));
337 }
338
339 template <DemuxerStream::Type StreamType>
340 void DecoderSelector<StreamType>::InitializeDecryptingDemuxerStream() {
341   DCHECK(decoders_.empty());
342   DCHECK(config_.is_encrypted());
343   DCHECK(cdm_context_);
344   TRACE_EVENT_ASYNC_STEP_INTO0("media", kSelectDecoderTrace, this,
345                                "DecryptingDemuxerStream");
346
347   decrypting_demuxer_stream_ = std::make_unique<DecryptingDemuxerStream>(
348       task_runner_, media_log_, waiting_cb_);
349
350   decrypting_demuxer_stream_->Initialize(
351       stream_, cdm_context_,
352       base::BindOnce(
353           &DecoderSelector<StreamType>::OnDecryptingDemuxerStreamInitializeDone,
354           weak_this_factory_.GetWeakPtr()));
355 }
356
357 template <DemuxerStream::Type StreamType>
358 void DecoderSelector<StreamType>::OnDecryptingDemuxerStreamInitializeDone(
359     PipelineStatus status) {
360   DVLOG(2) << __func__ << ": status=" << status;
361   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
362
363   if (status != PIPELINE_OK) {
364     // Since we already tried every potential decoder without DDS, give up.
365     ReturnSelectionError(
366         {DecoderStatus::Codes::kUnsupportedEncryptionMode, std::move(status)});
367     return;
368   }
369
370   // Once DDS is enabled, there is no going back.
371   // TODO(sandersd): Support transitions from encrypted to unencrypted.
372   stream_ = decrypting_demuxer_stream_.get();
373   cdm_context_ = nullptr;
374
375   // We'll use the decrypted config from now on.
376   config_ = traits_->GetDecoderConfig(stream_);
377   DCHECK(!config_.is_encrypted());
378
379   // Try decoder selection again now that DDS is being used.
380   CreateDecoders();
381   GetAndInitializeNextDecoder();
382 }
383
384 template <DemuxerStream::Type StreamType>
385 void DecoderSelector<StreamType>::RunSelectDecoderCB(
386     DecoderOrError decoder_or_error) {
387   DCHECK(select_decoder_cb_);
388   TRACE_EVENT_ASYNC_END2(
389       "media", kSelectDecoderTrace, this, "type",
390       DemuxerStream::GetTypeName(StreamType), "decoder",
391       base::StringPrintf(
392           "%s (%s)",
393           decoder_or_error.has_value()
394               ? GetDecoderName(decoder_or_error->GetDecoderType()).c_str()
395               : "null",
396           decrypting_demuxer_stream_ ? "encrypted" : "unencrypted"));
397
398   task_runner_->PostTask(
399       FROM_HERE,
400       base::BindOnce(std::move(select_decoder_cb_), std::move(decoder_or_error),
401                      std::move(decrypting_demuxer_stream_)));
402 }
403
404 template <DemuxerStream::Type StreamType>
405 void DecoderSelector<StreamType>::FilterAndSortAvailableDecoders() {
406   std::vector<std::unique_ptr<Decoder>> decoders = std::move(decoders_);
407   std::vector<std::unique_ptr<Decoder>> deprioritized_decoders;
408   DCHECK(decoder_priority_cb_);
409
410   for (auto& decoder : decoders) {
411     // Skip the decoder if this decoder doesn't support encryption for a
412     // decrypting config
413     if (config_.is_encrypted() && !decoder->SupportsDecryption())
414       continue;
415
416     // Run the predicate on this decoder.
417     switch (decoder_priority_cb_.Run(config_, *decoder)) {
418       case DecoderPriority::kSkipped:
419         continue;
420       case DecoderPriority::kNormal:
421         decoders_.push_back(std::move(decoder));
422         break;
423       case DecoderPriority::kDeprioritized:
424         deprioritized_decoders.push_back(std::move(decoder));
425         break;
426     }
427   }
428
429   // Post-insert deprioritized decoders
430   std::move(deprioritized_decoders.begin(), deprioritized_decoders.end(),
431             std::inserter(decoders_, decoders_.end()));
432 }
433
434 // These forward declarations tell the compiler that we will use
435 // DecoderSelector with these arguments, allowing us to keep these definitions
436 // in our .cc without causing linker errors. This also means if anyone tries to
437 // instantiate a DecoderSelector with anything but these two specializations
438 // they'll most likely get linker errors.
439 template class DecoderSelector<DemuxerStream::AUDIO>;
440 template class DecoderSelector<DemuxerStream::VIDEO>;
441
442 }  // namespace media