Shaka Packager SDK
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 
19 namespace shaka {
20 namespace media {
21 
22 enum class StreamDataType {
23  kUnknown,
24  kStreamInfo,
25  kMediaSample,
26  kTextSample,
27  kSegmentInfo,
28  kScte35Event,
29  kCueEvent,
30 };
31 
32 std::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.
36 struct Scte35Event {
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 
45 enum 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.
49 struct CueEvent {
50  CueEventType type = CueEventType::kCuePoint;
51  double time_in_seconds;
52  std::string cue_data;
53 };
54 
55 struct SegmentInfo {
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?
70 struct 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.
Definition: crypto_flags.cc:66