Shaka Packager SDK
Loading...
Searching...
No Matches
media_handler.h
1// Copyright 2017 Google LLC. All rights reserved.
2//
3// Use of this source code is governed by a BSD-style
4// license that can be found in the LICENSE file or at
5// https://developers.google.com/open-source/licenses/bsd
6
7#ifndef PACKAGER_MEDIA_BASE_MEDIA_HANDLER_H_
8#define PACKAGER_MEDIA_BASE_MEDIA_HANDLER_H_
9
10#include <cstddef>
11#include <cstdint>
12#include <map>
13#include <memory>
14#include <string>
15#include <utility>
16#include <vector>
17
18#include <packager/media/base/encryption_config.h>
19#include <packager/media/base/media_sample.h>
20#include <packager/media/base/stream_info.h>
21#include <packager/media/base/text_sample.h>
22#include <packager/status.h>
23
24namespace shaka {
25namespace media {
26
27enum class StreamDataType {
28 kUnknown,
29 kStreamInfo,
30 kMediaSample,
31 kTextSample,
32 kSegmentInfo,
33 kScte35Event,
34 kCueEvent,
35};
36
37std::string StreamDataTypeToString(StreamDataType type);
38
39// Scte35Event represents cuepoint markers in input streams. It will be used
40// to represent out of band cuepoint markers too.
42 std::string id;
43 // Segmentation type id from SCTE35 segmentation descriptor.
44 int type = 0;
45 double start_time_in_seconds = 0;
46 double duration_in_seconds = 0;
47 std::string cue_data;
48};
49
50enum class CueEventType { kCueIn, kCueOut, kCuePoint };
51
52// In server-based model, Chunking Handler consolidates SCTE-35 events and
53// generates CueEvent before an ad is about to be inserted.
54struct CueEvent {
55 CueEventType type = CueEventType::kCuePoint;
56 double time_in_seconds;
57 std::string cue_data;
58};
59
61 bool is_subsegment = false;
62 bool is_chunk = false;
63 bool is_final_chunk_in_seg = false;
64 bool is_encrypted = false;
65 int64_t start_timestamp = -1;
66 int64_t duration = 0;
67 int64_t segment_number = 1;
68 // This is only available if key rotation is enabled. Note that we may have
69 // a |key_rotation_encryption_config| even if the segment is not encrypted,
70 // which is the case for clear lead.
71 std::shared_ptr<EncryptionConfig> key_rotation_encryption_config;
72};
73
74// TODO(kqyang): Should we use protobuf?
75struct StreamData {
76 size_t stream_index = static_cast<size_t>(-1);
77 StreamDataType stream_data_type = StreamDataType::kUnknown;
78
79 std::shared_ptr<const StreamInfo> stream_info;
80 std::shared_ptr<const MediaSample> media_sample;
81 std::shared_ptr<const TextSample> text_sample;
82 std::shared_ptr<const SegmentInfo> segment_info;
83 std::shared_ptr<const Scte35Event> scte35_event;
84 std::shared_ptr<const CueEvent> cue_event;
85
86 static std::unique_ptr<StreamData> FromStreamInfo(
87 size_t stream_index,
88 std::shared_ptr<const StreamInfo> stream_info) {
89 std::unique_ptr<StreamData> stream_data(new StreamData);
90 stream_data->stream_index = stream_index;
91 stream_data->stream_data_type = StreamDataType::kStreamInfo;
92 stream_data->stream_info = std::move(stream_info);
93 return stream_data;
94 }
95
96 static std::unique_ptr<StreamData> FromMediaSample(
97 size_t stream_index,
98 std::shared_ptr<const MediaSample> media_sample) {
99 std::unique_ptr<StreamData> stream_data(new StreamData);
100 stream_data->stream_index = stream_index;
101 stream_data->stream_data_type = StreamDataType::kMediaSample;
102 stream_data->media_sample = std::move(media_sample);
103 return stream_data;
104 }
105
106 static std::unique_ptr<StreamData> FromTextSample(
107 size_t stream_index,
108 std::shared_ptr<const TextSample> text_sample) {
109 std::unique_ptr<StreamData> stream_data(new StreamData);
110 stream_data->stream_index = stream_index;
111 stream_data->stream_data_type = StreamDataType::kTextSample;
112 stream_data->text_sample = std::move(text_sample);
113 return stream_data;
114 }
115
116 static std::unique_ptr<StreamData> FromSegmentInfo(
117 size_t stream_index,
118 std::shared_ptr<const SegmentInfo> segment_info) {
119 std::unique_ptr<StreamData> stream_data(new StreamData);
120 stream_data->stream_index = stream_index;
121 stream_data->stream_data_type = StreamDataType::kSegmentInfo;
122 stream_data->segment_info = std::move(segment_info);
123 return stream_data;
124 }
125
126 static std::unique_ptr<StreamData> FromScte35Event(
127 size_t stream_index,
128 std::shared_ptr<const Scte35Event> scte35_event) {
129 std::unique_ptr<StreamData> stream_data(new StreamData);
130 stream_data->stream_index = stream_index;
131 stream_data->stream_data_type = StreamDataType::kScte35Event;
132 stream_data->scte35_event = std::move(scte35_event);
133 return stream_data;
134 }
135
136 static std::unique_ptr<StreamData> FromCueEvent(
137 size_t stream_index,
138 std::shared_ptr<const CueEvent> cue_event) {
139 std::unique_ptr<StreamData> stream_data(new StreamData);
140 stream_data->stream_index = stream_index;
141 stream_data->stream_data_type = StreamDataType::kCueEvent;
142 stream_data->cue_event = std::move(cue_event);
143 return stream_data;
144 }
145};
146
163 public:
164 MediaHandler() = default;
165 virtual ~MediaHandler() = default;
166
168 Status SetHandler(size_t output_stream_index,
169 std::shared_ptr<MediaHandler> handler);
170
172 Status AddHandler(std::shared_ptr<MediaHandler> handler) {
173 return SetHandler(next_output_stream_index_, handler);
174 }
175
178 Status Initialize();
179
181 bool IsConnected() { return num_input_streams_ > 0; }
182
183 static Status Chain(const std::vector<std::shared_ptr<MediaHandler>>& list);
184
185 protected:
188 virtual Status InitializeInternal() = 0;
189
194 virtual Status Process(std::unique_ptr<StreamData> stream_data) = 0;
195
197 virtual Status OnFlushRequest(size_t input_stream_index);
198
200 virtual bool ValidateOutputStreamIndex(size_t stream_index) const;
201
204 Status Dispatch(std::unique_ptr<StreamData> stream_data) const;
205
208 size_t stream_index,
209 std::shared_ptr<const StreamInfo> stream_info) const {
210 return Dispatch(
211 StreamData::FromStreamInfo(stream_index, std::move(stream_info)));
212 }
213
216 size_t stream_index,
217 std::shared_ptr<const MediaSample> media_sample) const {
218 return Dispatch(
219 StreamData::FromMediaSample(stream_index, std::move(media_sample)));
220 }
221
223 // DispatchTextSample should only be override for testing.
225 size_t stream_index,
226 std::shared_ptr<const TextSample> text_sample) const {
227 return Dispatch(
228 StreamData::FromTextSample(stream_index, std::move(text_sample)));
229 }
230
233 size_t stream_index,
234 std::shared_ptr<const SegmentInfo> segment_info) const {
235 return Dispatch(
236 StreamData::FromSegmentInfo(stream_index, std::move(segment_info)));
237 }
238
241 size_t stream_index,
242 std::shared_ptr<const Scte35Event> scte35_event) const {
243 return Dispatch(
244 StreamData::FromScte35Event(stream_index, std::move(scte35_event)));
245 }
246
248 Status DispatchCueEvent(size_t stream_index,
249 std::shared_ptr<const CueEvent> cue_event) const {
250 return Dispatch(
251 StreamData::FromCueEvent(stream_index, std::move(cue_event)));
252 }
253
255 Status FlushDownstream(size_t output_stream_index);
256
258 Status FlushAllDownstreams();
259
260 bool initialized() { return initialized_; }
261 size_t num_input_streams() const { return num_input_streams_; }
262 size_t next_output_stream_index() const { return next_output_stream_index_; }
263 const std::map<size_t, std::pair<std::shared_ptr<MediaHandler>, size_t>>&
264 output_handlers() {
265 return output_handlers_;
266 }
267
268 private:
269 MediaHandler(const MediaHandler&) = delete;
270 MediaHandler& operator=(const MediaHandler&) = delete;
271
272 bool initialized_ = false;
273 // Number of input streams.
274 size_t num_input_streams_ = 0;
275 // The next available output stream index, used by AddHandler.
276 size_t next_output_stream_index_ = 0;
277 // output stream index -> {output handler, output handler input stream index}
278 // map.
279 std::map<size_t, std::pair<std::shared_ptr<MediaHandler>, size_t>>
280 output_handlers_;
281};
282
283} // namespace media
284} // namespace shaka
285
286#endif // PACKAGER_MEDIA_BASE_MEDIA_HANDLER_H_
Status DispatchCueEvent(size_t stream_index, std::shared_ptr< const CueEvent > cue_event) const
Dispatch the cue event to downstream handlers.
virtual Status InitializeInternal()=0
bool IsConnected()
Validate if the handler is connected to its upstream handler.
Status SetHandler(size_t output_stream_index, std::shared_ptr< MediaHandler > handler)
Connect downstream handler at the specified output stream index.
Status DispatchSegmentInfo(size_t stream_index, std::shared_ptr< const SegmentInfo > segment_info) const
Dispatch the segment info to downstream handlers.
virtual Status OnFlushRequest(size_t input_stream_index)
Event handler for flush request at the specific input stream index.
Status DispatchMediaSample(size_t stream_index, std::shared_ptr< const MediaSample > media_sample) const
Dispatch the media sample to downstream handlers.
Status DispatchTextSample(size_t stream_index, std::shared_ptr< const TextSample > text_sample) const
Dispatch the text sample to downstream handlers.
Status DispatchScte35Event(size_t stream_index, std::shared_ptr< const Scte35Event > scte35_event) const
Dispatch the scte35 event to downstream handlers.
Status FlushAllDownstreams()
Flush all connected downstream handlers.
virtual bool ValidateOutputStreamIndex(size_t stream_index) const
Validate if the stream at the specified index actually exists.
virtual Status Process(std::unique_ptr< StreamData > stream_data)=0
Status DispatchStreamInfo(size_t stream_index, std::shared_ptr< const StreamInfo > stream_info) const
Dispatch the stream info to downstream handlers.
Status FlushDownstream(size_t output_stream_index)
Flush the downstream connected at the specified output stream index.
Status AddHandler(std::shared_ptr< MediaHandler > handler)
Connect downstream handler to the next available output stream index.
Status Dispatch(std::unique_ptr< StreamData > stream_data) const
All the methods that are virtual are virtual for mocking.