1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
media / filters / decoder_selector.h [blame]
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_FILTERS_DECODER_SELECTOR_H_
#define MEDIA_FILTERS_DECODER_SELECTOR_H_
#include <memory>
#include <vector>
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "media/base/demuxer_stream.h"
#include "media/base/pipeline_status.h"
#include "media/base/waiting.h"
#include "media/filters/decoder_stream_traits.h"
namespace base {
class SequencedTaskRunner;
}
namespace media {
class CdmContext;
class DecryptingDemuxerStream;
class MediaLog;
// DecoderSelector handles construction and initialization of Decoders for a
// DemuxerStream, and maintains the state required for decoder fallback.
// The template parameter |StreamType| is the type of stream we will be
// selecting a decoder for.
template<DemuxerStream::Type StreamType>
class MEDIA_EXPORT DecoderSelector {
public:
typedef DecoderStreamTraits<StreamType> StreamTraits;
typedef typename StreamTraits::DecoderType Decoder;
typedef typename StreamTraits::DecoderConfigType DecoderConfig;
using DecoderOrError = DecoderStatus::Or<std::unique_ptr<Decoder>>;
// Callback to create a list of decoders to select from.
// TODO(xhwang): Use a DecoderFactory to create decoders one by one as needed,
// instead of creating a list of decoders all at once.
using CreateDecodersCB =
base::RepeatingCallback<std::vector<std::unique_ptr<Decoder>>()>;
// Emits the result of a single call to SelectDecoder(). Parameters are
// 1: The initialized Decoder. nullptr if selection failed.
// 2: The initialized DecryptingDemuxerStream, if one was created. This
// happens at most once for a DecoderSelector instance.
// The caller owns the Decoder and DecryptingDemuxerStream.
//
// The caller should call DecryptingDemuxerStream::Reset() before
// calling Decoder::Reset() to release any pending decryption or read.
using SelectDecoderCB =
base::OnceCallback<void(DecoderOrError,
std::unique_ptr<DecryptingDemuxerStream>)>;
DecoderSelector() = delete;
// `enable_priority_based_selection` allows the DecoderSelector to change the
// order of which decoders are tried from FIFO order to an order based on
// characteristics of each decoder and config (resolution, platform, etc).
DecoderSelector(scoped_refptr<base::SequencedTaskRunner> task_runner,
CreateDecodersCB create_decoders_cb,
MediaLog* media_log,
bool enable_priority_based_selection = false);
DecoderSelector(const DecoderSelector&) = delete;
DecoderSelector& operator=(const DecoderSelector&) = delete;
// Aborts any pending decoder selection.
~DecoderSelector();
// Initialize with stream parameters. Should be called exactly once.
void Initialize(StreamTraits* traits,
DemuxerStream* stream,
CdmContext* cdm_context,
WaitingCB waiting_cb);
// Selects and initializes a decoder, which will be returned via
// |select_decoder_cb| posted to |task_runner|. In the event that a selected
// decoder fails to decode, |ResumeDecoderSelection| may be used to get
// another one.
//
// When the caller determines that decoder selection has succeeded (eg.
// because the decoder decoded a frame successfully), it should call
// FinalizeDecoderSelection().
//
// |SelectDecoderCB| may be called with an error if no decoders are available.
//
// Must not be called while another selection is pending.
void BeginDecoderSelection(SelectDecoderCB select_decoder_cb,
typename Decoder::OutputCB output_cb);
// When a client was provided with a decoder that fails to decode after
// being successfully initialized, it should request a new decoder via
// this method rather than |SelectDecoder|. This allows the pipeline to
// report the root cause of decoder failure.
void ResumeDecoderSelection(SelectDecoderCB select_decoder_cb,
typename Decoder::OutputCB output_cb,
DecoderStatus&& reinit_cause);
// Signals that decoder selection has been completed (successfully). Future
// calls to SelectDecoder() will select from the full list of decoders.
void FinalizeDecoderSelection();
// Adds an additional decoder candidate to be considered when selecting a
// decoder. This decoder is inserted ahead of the decoders returned by
// |CreateDecodersCB| to give it priority over the default set, though it
// may be by deprioritized if |DecoderPriorityCB| considers another decoder a
// better candidate. This decoder should be uninitialized.
void PrependDecoder(std::unique_ptr<Decoder> decoder);
private:
void CreateDecoders();
void GetAndInitializeNextDecoder();
void OnDecoderInitializeDone(DecoderStatus status);
void ReturnSelectionError(DecoderStatus error);
void InitializeDecryptingDemuxerStream();
void OnDecryptingDemuxerStreamInitializeDone(PipelineStatus status);
void RunSelectDecoderCB(DecoderOrError decoder_or_error);
void FilterAndSortAvailableDecoders();
void SelectDecoderInternal(SelectDecoderCB select_decoder_cb,
typename Decoder::OutputCB output_cb,
bool needs_new_decoders);
scoped_refptr<base::SequencedTaskRunner> task_runner_;
SEQUENCE_CHECKER(sequence_checker_);
CreateDecodersCB create_decoders_cb_;
raw_ptr<MediaLog> media_log_;
raw_ptr<StreamTraits, AcrossTasksDanglingUntriaged> traits_ = nullptr;
raw_ptr<DemuxerStream, AcrossTasksDanglingUntriaged> stream_ = nullptr;
raw_ptr<CdmContext> cdm_context_ = nullptr;
WaitingCB waiting_cb_;
// Overall decoder selection state.
DecoderConfig config_;
std::vector<std::unique_ptr<Decoder>> decoders_;
// State for a single GetAndInitializeNextDecoder() invocation.
SelectDecoderCB select_decoder_cb_;
typename Decoder::OutputCB output_cb_;
std::unique_ptr<Decoder> decoder_;
std::unique_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream_;
// Used to keep track of the original failure-to-decode reason so that if
// playback fails entirely, we have a root cause to point to, rather than
// failing due to running out of more acceptable decoders.
std::optional<DecoderStatus> decode_failure_reinit_cause_ = std::nullopt;
const bool enable_priority_based_selection_;
// Indicates that the first decoder in `decoders_` is a platform decoder and
// should maintain its place when FilterAndSortAvailableDecoders() runs.
bool prefer_prepended_platform_decoder_ = false;
base::WeakPtrFactory<DecoderSelector> weak_this_factory_{this};
};
typedef DecoderSelector<DemuxerStream::VIDEO> VideoDecoderSelector;
typedef DecoderSelector<DemuxerStream::AUDIO> AudioDecoderSelector;
} // namespace media
#endif // MEDIA_FILTERS_DECODER_SELECTOR_H_