Shaka Packager SDK
media_handler.h
1 // Copyright 2017 Google Inc. 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_encrypted = false;
58  int64_t start_timestamp = -1;
59  int64_t duration = 0;
60  // This is only available if key rotation is enabled. Note that we may have
61  // a |key_rotation_encryption_config| even if the segment is not encrypted,
62  // which is the case for clear lead.
63  std::shared_ptr<EncryptionConfig> key_rotation_encryption_config;
64 };
65 
66 // TODO(kqyang): Should we use protobuf?
67 struct StreamData {
68  size_t stream_index = static_cast<size_t>(-1);
69  StreamDataType stream_data_type = StreamDataType::kUnknown;
70 
71  std::shared_ptr<const StreamInfo> stream_info;
72  std::shared_ptr<const MediaSample> media_sample;
73  std::shared_ptr<const TextSample> text_sample;
74  std::shared_ptr<const SegmentInfo> segment_info;
75  std::shared_ptr<const Scte35Event> scte35_event;
76  std::shared_ptr<const CueEvent> cue_event;
77 
78  static std::unique_ptr<StreamData> FromStreamInfo(
79  size_t stream_index,
80  std::shared_ptr<const StreamInfo> stream_info) {
81  std::unique_ptr<StreamData> stream_data(new StreamData);
82  stream_data->stream_index = stream_index;
83  stream_data->stream_data_type = StreamDataType::kStreamInfo;
84  stream_data->stream_info = std::move(stream_info);
85  return stream_data;
86  }
87 
88  static std::unique_ptr<StreamData> FromMediaSample(
89  size_t stream_index,
90  std::shared_ptr<const MediaSample> media_sample) {
91  std::unique_ptr<StreamData> stream_data(new StreamData);
92  stream_data->stream_index = stream_index;
93  stream_data->stream_data_type = StreamDataType::kMediaSample;
94  stream_data->media_sample = std::move(media_sample);
95  return stream_data;
96  }
97 
98  static std::unique_ptr<StreamData> FromTextSample(
99  size_t stream_index,
100  std::shared_ptr<const TextSample> text_sample) {
101  std::unique_ptr<StreamData> stream_data(new StreamData);
102  stream_data->stream_index = stream_index;
103  stream_data->stream_data_type = StreamDataType::kTextSample;
104  stream_data->text_sample = std::move(text_sample);
105  return stream_data;
106  }
107 
108  static std::unique_ptr<StreamData> FromSegmentInfo(
109  size_t stream_index,
110  std::shared_ptr<const SegmentInfo> segment_info) {
111  std::unique_ptr<StreamData> stream_data(new StreamData);
112  stream_data->stream_index = stream_index;
113  stream_data->stream_data_type = StreamDataType::kSegmentInfo;
114  stream_data->segment_info = std::move(segment_info);
115  return stream_data;
116  }
117 
118  static std::unique_ptr<StreamData> FromScte35Event(
119  size_t stream_index,
120  std::shared_ptr<const Scte35Event> scte35_event) {
121  std::unique_ptr<StreamData> stream_data(new StreamData);
122  stream_data->stream_index = stream_index;
123  stream_data->stream_data_type = StreamDataType::kScte35Event;
124  stream_data->scte35_event = std::move(scte35_event);
125  return stream_data;
126  }
127 
128  static std::unique_ptr<StreamData> FromCueEvent(
129  size_t stream_index,
130  std::shared_ptr<const CueEvent> cue_event) {
131  std::unique_ptr<StreamData> stream_data(new StreamData);
132  stream_data->stream_index = stream_index;
133  stream_data->stream_data_type = StreamDataType::kCueEvent;
134  stream_data->cue_event = std::move(cue_event);
135  return stream_data;
136  }
137 };
138 
155  public:
156  MediaHandler() = default;
157  virtual ~MediaHandler() = default;
158 
160  Status SetHandler(size_t output_stream_index,
161  std::shared_ptr<MediaHandler> handler);
162 
164  Status AddHandler(std::shared_ptr<MediaHandler> handler) {
165  return SetHandler(next_output_stream_index_, handler);
166  }
167 
170  Status Initialize();
171 
173  bool IsConnected() { return num_input_streams_ > 0; }
174 
175  static Status Chain(
176  std::initializer_list<std::shared_ptr<MediaHandler>> list);
177 
178  protected:
181  virtual Status InitializeInternal() = 0;
182 
187  virtual Status Process(std::unique_ptr<StreamData> stream_data) = 0;
188 
190  virtual Status OnFlushRequest(size_t input_stream_index);
191 
193  virtual bool ValidateOutputStreamIndex(size_t stream_index) const;
194 
197  Status Dispatch(std::unique_ptr<StreamData> stream_data) const;
198 
201  size_t stream_index,
202  std::shared_ptr<const StreamInfo> stream_info) const {
203  return Dispatch(
204  StreamData::FromStreamInfo(stream_index, std::move(stream_info)));
205  }
206 
209  size_t stream_index,
210  std::shared_ptr<const MediaSample> media_sample) const {
211  return Dispatch(
212  StreamData::FromMediaSample(stream_index, std::move(media_sample)));
213  }
214 
216  // DispatchTextSample should only be override for testing.
218  size_t stream_index,
219  std::shared_ptr<const TextSample> text_sample) const {
220  return Dispatch(
221  StreamData::FromTextSample(stream_index, std::move(text_sample)));
222  }
223 
226  size_t stream_index,
227  std::shared_ptr<const SegmentInfo> segment_info) const {
228  return Dispatch(
229  StreamData::FromSegmentInfo(stream_index, std::move(segment_info)));
230  }
231 
234  size_t stream_index,
235  std::shared_ptr<const Scte35Event> scte35_event) const {
236  return Dispatch(
237  StreamData::FromScte35Event(stream_index, std::move(scte35_event)));
238  }
239 
241  Status DispatchCueEvent(size_t stream_index,
242  std::shared_ptr<const CueEvent> cue_event) const {
243  return Dispatch(
244  StreamData::FromCueEvent(stream_index, std::move(cue_event)));
245  }
246 
248  Status FlushDownstream(size_t output_stream_index);
249 
251  Status FlushAllDownstreams();
252 
253  bool initialized() { return initialized_; }
254  size_t num_input_streams() const { return num_input_streams_; }
255  size_t next_output_stream_index() const { return next_output_stream_index_; }
256  const std::map<size_t, std::pair<std::shared_ptr<MediaHandler>, size_t>>&
257  output_handlers() {
258  return output_handlers_;
259  }
260 
261  private:
262  MediaHandler(const MediaHandler&) = delete;
263  MediaHandler& operator=(const MediaHandler&) = delete;
264 
265  bool initialized_ = false;
266  // Number of input streams.
267  size_t num_input_streams_ = 0;
268  // The next available output stream index, used by AddHandler.
269  size_t next_output_stream_index_ = 0;
270  // output stream index -> {output handler, output handler input stream index}
271  // map.
272  std::map<size_t, std::pair<std::shared_ptr<MediaHandler>, size_t>>
273  output_handlers_;
274 };
275 
276 } // namespace media
277 } // namespace shaka
278 
279 #endif // PACKAGER_MEDIA_BASE_MEDIA_HANDLER_H_
Status DispatchStreamInfo(size_t stream_index, std::shared_ptr< const StreamInfo > stream_info) const
Dispatch the stream info to downstream handlers.
bool IsConnected()
Validate if the handler is connected to its upstream handler.
All the methods that are virtual are virtual for mocking.
Status DispatchTextSample(size_t stream_index, std::shared_ptr< const TextSample > text_sample) const
Dispatch the text sample to downstream handlers.
Status AddHandler(std::shared_ptr< MediaHandler > handler)
Connect downstream handler to the next available output stream index.
Status DispatchSegmentInfo(size_t stream_index, std::shared_ptr< const SegmentInfo > segment_info) const
Dispatch the segment info to downstream handlers.
Status DispatchCueEvent(size_t stream_index, std::shared_ptr< const CueEvent > cue_event) const
Dispatch the cue event 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 DispatchMediaSample(size_t stream_index, std::shared_ptr< const MediaSample > media_sample) const
Dispatch the media sample to downstream handlers.