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 <map>
11#include <memory>
12#include <utility>
13
14#include <packager/media/base/media_sample.h>
15#include <packager/media/base/stream_info.h>
16#include <packager/media/base/text_sample.h>
17#include <packager/status.h>
18
19namespace shaka {
20namespace media {
21
22enum class StreamDataType {
23 kUnknown,
24 kStreamInfo,
25 kMediaSample,
26 kTextSample,
27 kSegmentInfo,
28 kScte35Event,
29 kCueEvent,
30};
31
32std::string StreamDataTypeToString(StreamDataType type);
33
34// Scte35Event represents cuepoint markers in input streams. It will be used
35// to represent out of band cuepoint markers too.
37 std::string id;
38 // Segmentation type id from SCTE35 segmentation descriptor.
39 int type = 0;
40 double start_time_in_seconds = 0;
41 double duration_in_seconds = 0;
42 std::string cue_data;
43};
44
45enum class CueEventType { kCueIn, kCueOut, kCuePoint };
46
47// In server-based model, Chunking Handler consolidates SCTE-35 events and
48// generates CueEvent before an ad is about to be inserted.
49struct CueEvent {
50 CueEventType type = CueEventType::kCuePoint;
51 double time_in_seconds;
52 std::string cue_data;
53};
54
56 bool is_subsegment = false;
57 bool is_chunk = false;
58 bool is_final_chunk_in_seg = false;
59 bool is_encrypted = false;
60 int64_t start_timestamp = -1;
61 int64_t duration = 0;
62 int64_t segment_number = 1;
63 // This is only available if key rotation is enabled. Note that we may have
64 // a |key_rotation_encryption_config| even if the segment is not encrypted,
65 // which is the case for clear lead.
66 std::shared_ptr<EncryptionConfig> key_rotation_encryption_config;
67};
68
69// TODO(kqyang): Should we use protobuf?
70struct StreamData {
71 size_t stream_index = static_cast<size_t>(-1);
72 StreamDataType stream_data_type = StreamDataType::kUnknown;
73
74 std::shared_ptr<const StreamInfo> stream_info;
75 std::shared_ptr<const MediaSample> media_sample;
76 std::shared_ptr<const TextSample> text_sample;
77 std::shared_ptr<const SegmentInfo> segment_info;
78 std::shared_ptr<const Scte35Event> scte35_event;
79 std::shared_ptr<const CueEvent> cue_event;
80
81 static std::unique_ptr<StreamData> FromStreamInfo(
82 size_t stream_index,
83 std::shared_ptr<const StreamInfo> stream_info) {
84 std::unique_ptr<StreamData> stream_data(new StreamData);
85 stream_data->stream_index = stream_index;
86 stream_data->stream_data_type = StreamDataType::kStreamInfo;
87 stream_data->stream_info = std::move(stream_info);
88 return stream_data;
89 }
90
91 static std::unique_ptr<StreamData> FromMediaSample(
92 size_t stream_index,
93 std::shared_ptr<const MediaSample> media_sample) {
94 std::unique_ptr<StreamData> stream_data(new StreamData);
95 stream_data->stream_index = stream_index;
96 stream_data->stream_data_type = StreamDataType::kMediaSample;
97 stream_data->media_sample = std::move(media_sample);
98 return stream_data;
99 }
100
101 static std::unique_ptr<StreamData> FromTextSample(
102 size_t stream_index,
103 std::shared_ptr<const TextSample> text_sample) {
104 std::unique_ptr<StreamData> stream_data(new StreamData);
105 stream_data->stream_index = stream_index;
106 stream_data->stream_data_type = StreamDataType::kTextSample;
107 stream_data->text_sample = std::move(text_sample);
108 return stream_data;
109 }
110
111 static std::unique_ptr<StreamData> FromSegmentInfo(
112 size_t stream_index,
113 std::shared_ptr<const SegmentInfo> segment_info) {
114 std::unique_ptr<StreamData> stream_data(new StreamData);
115 stream_data->stream_index = stream_index;
116 stream_data->stream_data_type = StreamDataType::kSegmentInfo;
117 stream_data->segment_info = std::move(segment_info);
118 return stream_data;
119 }
120
121 static std::unique_ptr<StreamData> FromScte35Event(
122 size_t stream_index,
123 std::shared_ptr<const Scte35Event> scte35_event) {
124 std::unique_ptr<StreamData> stream_data(new StreamData);
125 stream_data->stream_index = stream_index;
126 stream_data->stream_data_type = StreamDataType::kScte35Event;
127 stream_data->scte35_event = std::move(scte35_event);
128 return stream_data;
129 }
130
131 static std::unique_ptr<StreamData> FromCueEvent(
132 size_t stream_index,
133 std::shared_ptr<const CueEvent> cue_event) {
134 std::unique_ptr<StreamData> stream_data(new StreamData);
135 stream_data->stream_index = stream_index;
136 stream_data->stream_data_type = StreamDataType::kCueEvent;
137 stream_data->cue_event = std::move(cue_event);
138 return stream_data;
139 }
140};
141
158 public:
159 MediaHandler() = default;
160 virtual ~MediaHandler() = default;
161
163 Status SetHandler(size_t output_stream_index,
164 std::shared_ptr<MediaHandler> handler);
165
167 Status AddHandler(std::shared_ptr<MediaHandler> handler) {
168 return SetHandler(next_output_stream_index_, handler);
169 }
170
173 Status Initialize();
174
176 bool IsConnected() { return num_input_streams_ > 0; }
177
178 static Status Chain(const std::vector<std::shared_ptr<MediaHandler>>& list);
179
180 protected:
183 virtual Status InitializeInternal() = 0;
184
189 virtual Status Process(std::unique_ptr<StreamData> stream_data) = 0;
190
192 virtual Status OnFlushRequest(size_t input_stream_index);
193
195 virtual bool ValidateOutputStreamIndex(size_t stream_index) const;
196
199 Status Dispatch(std::unique_ptr<StreamData> stream_data) const;
200
203 size_t stream_index,
204 std::shared_ptr<const StreamInfo> stream_info) const {
205 return Dispatch(
206 StreamData::FromStreamInfo(stream_index, std::move(stream_info)));
207 }
208
211 size_t stream_index,
212 std::shared_ptr<const MediaSample> media_sample) const {
213 return Dispatch(
214 StreamData::FromMediaSample(stream_index, std::move(media_sample)));
215 }
216
218 // DispatchTextSample should only be override for testing.
220 size_t stream_index,
221 std::shared_ptr<const TextSample> text_sample) const {
222 return Dispatch(
223 StreamData::FromTextSample(stream_index, std::move(text_sample)));
224 }
225
228 size_t stream_index,
229 std::shared_ptr<const SegmentInfo> segment_info) const {
230 return Dispatch(
231 StreamData::FromSegmentInfo(stream_index, std::move(segment_info)));
232 }
233
236 size_t stream_index,
237 std::shared_ptr<const Scte35Event> scte35_event) const {
238 return Dispatch(
239 StreamData::FromScte35Event(stream_index, std::move(scte35_event)));
240 }
241
243 Status DispatchCueEvent(size_t stream_index,
244 std::shared_ptr<const CueEvent> cue_event) const {
245 return Dispatch(
246 StreamData::FromCueEvent(stream_index, std::move(cue_event)));
247 }
248
250 Status FlushDownstream(size_t output_stream_index);
251
253 Status FlushAllDownstreams();
254
255 bool initialized() { return initialized_; }
256 size_t num_input_streams() const { return num_input_streams_; }
257 size_t next_output_stream_index() const { return next_output_stream_index_; }
258 const std::map<size_t, std::pair<std::shared_ptr<MediaHandler>, size_t>>&
259 output_handlers() {
260 return output_handlers_;
261 }
262
263 private:
264 MediaHandler(const MediaHandler&) = delete;
265 MediaHandler& operator=(const MediaHandler&) = delete;
266
267 bool initialized_ = false;
268 // Number of input streams.
269 size_t num_input_streams_ = 0;
270 // The next available output stream index, used by AddHandler.
271 size_t next_output_stream_index_ = 0;
272 // output stream index -> {output handler, output handler input stream index}
273 // map.
274 std::map<size_t, std::pair<std::shared_ptr<MediaHandler>, size_t>>
275 output_handlers_;
276};
277
278} // namespace media
279} // namespace shaka
280
281#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.