-
Notifications
You must be signed in to change notification settings - Fork 511
/
media_handler.h
279 lines (237 loc) · 10.1 KB
/
media_handler.h
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
// Copyright 2017 Google Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#ifndef PACKAGER_MEDIA_BASE_MEDIA_HANDLER_H_
#define PACKAGER_MEDIA_BASE_MEDIA_HANDLER_H_
#include <map>
#include <memory>
#include <utility>
#include "packager/media/base/media_sample.h"
#include "packager/media/base/stream_info.h"
#include "packager/media/base/text_sample.h"
#include "packager/status.h"
namespace shaka {
namespace media {
enum class StreamDataType {
kUnknown,
kStreamInfo,
kMediaSample,
kTextSample,
kSegmentInfo,
kScte35Event,
kCueEvent,
};
std::string StreamDataTypeToString(StreamDataType type);
// Scte35Event represents cuepoint markers in input streams. It will be used
// to represent out of band cuepoint markers too.
struct Scte35Event {
std::string id;
// Segmentation type id from SCTE35 segmentation descriptor.
int type = 0;
double start_time_in_seconds = 0;
double duration_in_seconds = 0;
std::string cue_data;
};
enum class CueEventType { kCueIn, kCueOut, kCuePoint };
// In server-based model, Chunking Handler consolidates SCTE-35 events and
// generates CueEvent before an ad is about to be inserted.
struct CueEvent {
CueEventType type = CueEventType::kCuePoint;
double time_in_seconds;
std::string cue_data;
};
struct SegmentInfo {
bool is_subsegment = false;
bool is_encrypted = false;
int64_t start_timestamp = -1;
int64_t duration = 0;
// This is only available if key rotation is enabled. Note that we may have
// a |key_rotation_encryption_config| even if the segment is not encrypted,
// which is the case for clear lead.
std::shared_ptr<EncryptionConfig> key_rotation_encryption_config;
};
// TODO(kqyang): Should we use protobuf?
struct StreamData {
size_t stream_index = static_cast<size_t>(-1);
StreamDataType stream_data_type = StreamDataType::kUnknown;
std::shared_ptr<const StreamInfo> stream_info;
std::shared_ptr<const MediaSample> media_sample;
std::shared_ptr<const TextSample> text_sample;
std::shared_ptr<const SegmentInfo> segment_info;
std::shared_ptr<const Scte35Event> scte35_event;
std::shared_ptr<const CueEvent> cue_event;
static std::unique_ptr<StreamData> FromStreamInfo(
size_t stream_index,
std::shared_ptr<const StreamInfo> stream_info) {
std::unique_ptr<StreamData> stream_data(new StreamData);
stream_data->stream_index = stream_index;
stream_data->stream_data_type = StreamDataType::kStreamInfo;
stream_data->stream_info = std::move(stream_info);
return stream_data;
}
static std::unique_ptr<StreamData> FromMediaSample(
size_t stream_index,
std::shared_ptr<const MediaSample> media_sample) {
std::unique_ptr<StreamData> stream_data(new StreamData);
stream_data->stream_index = stream_index;
stream_data->stream_data_type = StreamDataType::kMediaSample;
stream_data->media_sample = std::move(media_sample);
return stream_data;
}
static std::unique_ptr<StreamData> FromTextSample(
size_t stream_index,
std::shared_ptr<const TextSample> text_sample) {
std::unique_ptr<StreamData> stream_data(new StreamData);
stream_data->stream_index = stream_index;
stream_data->stream_data_type = StreamDataType::kTextSample;
stream_data->text_sample = std::move(text_sample);
return stream_data;
}
static std::unique_ptr<StreamData> FromSegmentInfo(
size_t stream_index,
std::shared_ptr<const SegmentInfo> segment_info) {
std::unique_ptr<StreamData> stream_data(new StreamData);
stream_data->stream_index = stream_index;
stream_data->stream_data_type = StreamDataType::kSegmentInfo;
stream_data->segment_info = std::move(segment_info);
return stream_data;
}
static std::unique_ptr<StreamData> FromScte35Event(
size_t stream_index,
std::shared_ptr<const Scte35Event> scte35_event) {
std::unique_ptr<StreamData> stream_data(new StreamData);
stream_data->stream_index = stream_index;
stream_data->stream_data_type = StreamDataType::kScte35Event;
stream_data->scte35_event = std::move(scte35_event);
return stream_data;
}
static std::unique_ptr<StreamData> FromCueEvent(
size_t stream_index,
std::shared_ptr<const CueEvent> cue_event) {
std::unique_ptr<StreamData> stream_data(new StreamData);
stream_data->stream_index = stream_index;
stream_data->stream_data_type = StreamDataType::kCueEvent;
stream_data->cue_event = std::move(cue_event);
return stream_data;
}
};
/// MediaHandler is the base media processing unit. Media handlers transform
/// the input streams and propagate the outputs to downstream media handlers.
/// There are three different types of media handlers:
/// 1) Single input single output
/// This is the most basic handler. It only supports one input and one
/// output with both index as 0.
/// 2) Multiple inputs multiple outputs
/// The number of outputs must be equal to the number of inputs. The
/// output stream at a specific index comes from the input stream at the
/// same index. Different streams usually share a common resource, although
/// they may be independent. One example of this is encryption handler.
/// 3) Single input multiple outputs
/// The input stream is split into multiple output streams. One example
/// of this is the replicator media handler.
/// Other types of media handlers are disallowed and not supported.
class MediaHandler {
public:
MediaHandler() = default;
virtual ~MediaHandler() = default;
/// Connect downstream handler at the specified output stream index.
Status SetHandler(size_t output_stream_index,
std::shared_ptr<MediaHandler> handler);
/// Connect downstream handler to the next available output stream index.
Status AddHandler(std::shared_ptr<MediaHandler> handler) {
return SetHandler(next_output_stream_index_, handler);
}
/// Initialize the handler and downstream handlers. Note that it should be
/// called after setting up the graph before running the graph.
Status Initialize();
/// Validate if the handler is connected to its upstream handler.
bool IsConnected() { return num_input_streams_ > 0; }
static Status Chain(
std::initializer_list<std::shared_ptr<MediaHandler>> list);
protected:
/// Internal implementation of initialize. Note that it should only initialize
/// the MediaHandler itself. Downstream handlers are handled in Initialize().
virtual Status InitializeInternal() = 0;
/// Process the incoming stream data. Note that (1) stream_data.stream_index
/// should be the input stream index; (2) The implementation needs to call
/// DispatchXxx to dispatch the processed stream data to the downstream
/// handlers after finishing processing if needed.
virtual Status Process(std::unique_ptr<StreamData> stream_data) = 0;
/// Event handler for flush request at the specific input stream index.
virtual Status OnFlushRequest(size_t input_stream_index);
/// Validate if the stream at the specified index actually exists.
virtual bool ValidateOutputStreamIndex(size_t stream_index) const;
/// Dispatch the stream data to downstream handlers. Note that
/// stream_data.stream_index should be the output stream index.
Status Dispatch(std::unique_ptr<StreamData> stream_data) const;
/// Dispatch the stream info to downstream handlers.
Status DispatchStreamInfo(
size_t stream_index,
std::shared_ptr<const StreamInfo> stream_info) const {
return Dispatch(
StreamData::FromStreamInfo(stream_index, std::move(stream_info)));
}
/// Dispatch the media sample to downstream handlers.
Status DispatchMediaSample(
size_t stream_index,
std::shared_ptr<const MediaSample> media_sample) const {
return Dispatch(
StreamData::FromMediaSample(stream_index, std::move(media_sample)));
}
/// Dispatch the text sample to downstream handlers.
// DispatchTextSample should only be override for testing.
Status DispatchTextSample(
size_t stream_index,
std::shared_ptr<const TextSample> text_sample) const {
return Dispatch(
StreamData::FromTextSample(stream_index, std::move(text_sample)));
}
/// Dispatch the segment info to downstream handlers.
Status DispatchSegmentInfo(
size_t stream_index,
std::shared_ptr<const SegmentInfo> segment_info) const {
return Dispatch(
StreamData::FromSegmentInfo(stream_index, std::move(segment_info)));
}
/// Dispatch the scte35 event to downstream handlers.
Status DispatchScte35Event(
size_t stream_index,
std::shared_ptr<const Scte35Event> scte35_event) const {
return Dispatch(
StreamData::FromScte35Event(stream_index, std::move(scte35_event)));
}
/// Dispatch the cue event to downstream handlers.
Status DispatchCueEvent(size_t stream_index,
std::shared_ptr<const CueEvent> cue_event) const {
return Dispatch(
StreamData::FromCueEvent(stream_index, std::move(cue_event)));
}
/// Flush the downstream connected at the specified output stream index.
Status FlushDownstream(size_t output_stream_index);
/// Flush all connected downstream handlers.
Status FlushAllDownstreams();
bool initialized() { return initialized_; }
size_t num_input_streams() const { return num_input_streams_; }
size_t next_output_stream_index() const { return next_output_stream_index_; }
const std::map<size_t, std::pair<std::shared_ptr<MediaHandler>, size_t>>&
output_handlers() {
return output_handlers_;
}
private:
MediaHandler(const MediaHandler&) = delete;
MediaHandler& operator=(const MediaHandler&) = delete;
bool initialized_ = false;
// Number of input streams.
size_t num_input_streams_ = 0;
// The next available output stream index, used by AddHandler.
size_t next_output_stream_index_ = 0;
// output stream index -> {output handler, output handler input stream index}
// map.
std::map<size_t, std::pair<std::shared_ptr<MediaHandler>, size_t>>
output_handlers_;
};
} // namespace media
} // namespace shaka
#endif // PACKAGER_MEDIA_BASE_MEDIA_HANDLER_H_