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.
5 #ifndef MEDIA_FILTERS_DECODER_SELECTOR_H_
6 #define MEDIA_FILTERS_DECODER_SELECTOR_H_
11 #include "base/functional/callback.h"
12 #include "base/memory/raw_ptr.h"
13 #include "base/memory/scoped_refptr.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/sequence_checker.h"
16 #include "base/time/time.h"
17 #include "media/base/demuxer_stream.h"
18 #include "media/base/pipeline_status.h"
19 #include "media/base/waiting.h"
20 #include "media/filters/decoder_stream_traits.h"
23 class SequencedTaskRunner;
29 class DecryptingDemuxerStream;
32 // Enum returned by `DecoderSelector::DecoderPriorityCB` to indicate
33 // priority of the current decoder.
34 enum class DecoderPriority {
35 // `kNormal` indicates that the current decoder should continue through with
36 // selection in it's current order.
39 // `kDeprioritized` indicates that the current decoder should only be selected
40 // if other decoders have failed.
43 // `kSkipped` indicates that the current decoder should not be used at all.
47 // DecoderSelector handles construction and initialization of Decoders for a
48 // DemuxerStream, and maintains the state required for decoder fallback.
49 // The template parameter |StreamType| is the type of stream we will be
50 // selecting a decoder for.
51 template<DemuxerStream::Type StreamType>
52 class MEDIA_EXPORT DecoderSelector {
54 typedef DecoderStreamTraits<StreamType> StreamTraits;
55 typedef typename StreamTraits::DecoderType Decoder;
56 typedef typename StreamTraits::DecoderConfigType DecoderConfig;
57 using DecoderOrError = DecoderStatus::Or<std::unique_ptr<Decoder>>;
59 // Callback to create a list of decoders to select from.
60 // TODO(xhwang): Use a DecoderFactory to create decoders one by one as needed,
61 // instead of creating a list of decoders all at once.
62 using CreateDecodersCB =
63 base::RepeatingCallback<std::vector<std::unique_ptr<Decoder>>()>;
65 // Prediate to evaluate whether a decoder should be prioritized,
66 // deprioritized, or skipped.
67 using DecoderPriorityCB =
68 base::RepeatingCallback<DecoderPriority(const DecoderConfig&,
71 // Emits the result of a single call to SelectDecoder(). Parameters are
72 // 1: The initialized Decoder. nullptr if selection failed.
73 // 2: The initialized DecryptingDemuxerStream, if one was created. This
74 // happens at most once for a DecoderSelector instance.
75 // The caller owns the Decoder and DecryptingDemuxerStream.
77 // The caller should call DecryptingDemuxerStream::Reset() before
78 // calling Decoder::Reset() to release any pending decryption or read.
79 using SelectDecoderCB =
80 base::OnceCallback<void(DecoderOrError,
81 std::unique_ptr<DecryptingDemuxerStream>)>;
83 DecoderSelector() = delete;
85 DecoderSelector(scoped_refptr<base::SequencedTaskRunner> task_runner,
86 CreateDecodersCB create_decoders_cb,
89 DecoderSelector(const DecoderSelector&) = delete;
90 DecoderSelector& operator=(const DecoderSelector&) = delete;
92 // Aborts any pending decoder selection.
95 // Initialize with stream parameters. Should be called exactly once.
96 void Initialize(StreamTraits* traits,
97 DemuxerStream* stream,
98 CdmContext* cdm_context,
99 WaitingCB waiting_cb);
101 // Selects and initializes a decoder, which will be returned via
102 // |select_decoder_cb| posted to |task_runner|. In the event that a selected
103 // decoder fails to decode, |ResumeDecoderSelection| may be used to get
106 // When the caller determines that decoder selection has succeeded (eg.
107 // because the decoder decoded a frame successfully), it should call
108 // FinalizeDecoderSelection().
110 // |SelectDecoderCB| may be called with an error if no decoders are available.
112 // Must not be called while another selection is pending.
113 void BeginDecoderSelection(SelectDecoderCB select_decoder_cb,
114 typename Decoder::OutputCB output_cb);
116 // When a client was provided with a decoder that fails to decode after
117 // being successfully initialized, it should request a new decoder via
118 // this method rather than |SelectDecoder|. This allows the pipeline to
119 // report the root cause of decoder failure.
120 void ResumeDecoderSelection(SelectDecoderCB select_decoder_cb,
121 typename Decoder::OutputCB output_cb,
122 DecoderStatus&& reinit_cause);
124 // Signals that decoder selection has been completed (successfully). Future
125 // calls to SelectDecoder() will select from the full list of decoders.
126 void FinalizeDecoderSelection();
128 // Adds an additional decoder candidate to be considered when selecting a
129 // decoder. This decoder is inserted ahead of the decoders returned by
130 // |CreateDecodersCB| to give it priority over the default set, though it
131 // may be by deprioritized if |DecoderPriorityCB| considers another decoder a
132 // better candidate. This decoder should be uninitialized.
133 void PrependDecoder(std::unique_ptr<Decoder> decoder);
135 // Overrides the default function for evaluation platform decoder priority.
136 // Useful for writing tests in a platform-agnostic manner.
137 void OverrideDecoderPriorityCBForTesting(DecoderPriorityCB priority_cb);
140 void CreateDecoders();
141 void GetAndInitializeNextDecoder();
142 void OnDecoderInitializeDone(DecoderStatus status);
143 void ReturnSelectionError(DecoderStatus error);
144 void InitializeDecryptingDemuxerStream();
145 void OnDecryptingDemuxerStreamInitializeDone(PipelineStatus status);
146 void RunSelectDecoderCB(DecoderOrError decoder_or_error);
147 void FilterAndSortAvailableDecoders();
148 void SelectDecoderInternal(SelectDecoderCB select_decoder_cb,
149 typename Decoder::OutputCB output_cb,
150 bool needs_new_decoders);
152 scoped_refptr<base::SequencedTaskRunner> task_runner_;
153 SEQUENCE_CHECKER(sequence_checker_);
155 CreateDecodersCB create_decoders_cb_;
156 DecoderPriorityCB decoder_priority_cb_;
157 raw_ptr<MediaLog> media_log_;
159 raw_ptr<StreamTraits, AcrossTasksDanglingUntriaged> traits_ = nullptr;
160 raw_ptr<DemuxerStream, AcrossTasksDanglingUntriaged> stream_ = nullptr;
161 raw_ptr<CdmContext> cdm_context_ = nullptr;
162 WaitingCB waiting_cb_;
164 // Overall decoder selection state.
165 DecoderConfig config_;
166 std::vector<std::unique_ptr<Decoder>> decoders_;
168 // State for a single GetAndInitializeNextDecoder() invocation.
169 SelectDecoderCB select_decoder_cb_;
170 typename Decoder::OutputCB output_cb_;
171 std::unique_ptr<Decoder> decoder_;
172 std::unique_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream_;
174 // Used to keep track of the original failure-to-decode reason so that if
175 // playback fails entirely, we have a root cause to point to, rather than
176 // failing due to running out of more acceptable decoders.
177 absl::optional<DecoderStatus> decode_failure_reinit_cause_ = absl::nullopt;
179 base::WeakPtrFactory<DecoderSelector> weak_this_factory_{this};
182 typedef DecoderSelector<DemuxerStream::VIDEO> VideoDecoderSelector;
183 typedef DecoderSelector<DemuxerStream::AUDIO> AudioDecoderSelector;
187 #endif // MEDIA_FILTERS_DECODER_SELECTOR_H_