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(const std::vector<std::shared_ptr<MediaHandler>>& list);
176 
177  protected:
180  virtual Status InitializeInternal() = 0;
181 
186  virtual Status Process(std::unique_ptr<StreamData> stream_data) = 0;
187 
189  virtual Status OnFlushRequest(size_t input_stream_index);
190 
192  virtual bool ValidateOutputStreamIndex(size_t stream_index) const;
193 
196  Status Dispatch(std::unique_ptr<StreamData> stream_data) const;
197 
200  size_t stream_index,
201  std::shared_ptr<const StreamInfo> stream_info) const {
202  return Dispatch(
203  StreamData::FromStreamInfo(stream_index, std::move(stream_info)));
204  }
205 
208  size_t stream_index,
209  std::shared_ptr<const MediaSample> media_sample) const {
210  return Dispatch(
211  StreamData::FromMediaSample(stream_index, std::move(media_sample)));
212  }
213 
215  // DispatchTextSample should only be override for testing.
217  size_t stream_index,
218  std::shared_ptr<const TextSample> text_sample) const {
219  return Dispatch(
220  StreamData::FromTextSample(stream_index, std::move(text_sample)));
221  }
222 
225  size_t stream_index,
226  std::shared_ptr<const SegmentInfo> segment_info) const {
227  return Dispatch(
228  StreamData::FromSegmentInfo(stream_index, std::move(segment_info)));
229  }
230 
233  size_t stream_index,
234  std::shared_ptr<const Scte35Event> scte35_event) const {
235  return Dispatch(
236  StreamData::FromScte35Event(stream_index, std::move(scte35_event)));
237  }
238 
240  Status DispatchCueEvent(size_t stream_index,
241  std::shared_ptr<const CueEvent> cue_event) const {
242  return Dispatch(
243  StreamData::FromCueEvent(stream_index, std::move(cue_event)));
244  }
245 
247  Status FlushDownstream(size_t output_stream_index);
248 
251 
252  bool initialized() { return initialized_; }
253  size_t num_input_streams() const { return num_input_streams_; }
254  size_t next_output_stream_index() const { return next_output_stream_index_; }
255  const std::map<size_t, std::pair<std::shared_ptr<MediaHandler>, size_t>>&
256  output_handlers() {
257  return output_handlers_;
258  }
259 
260  private:
261  MediaHandler(const MediaHandler&) = delete;
262  MediaHandler& operator=(const MediaHandler&) = delete;
263 
264  bool initialized_ = false;
265  // Number of input streams.
266  size_t num_input_streams_ = 0;
267  // The next available output stream index, used by AddHandler.
268  size_t next_output_stream_index_ = 0;
269  // output stream index -> {output handler, output handler input stream index}
270  // map.
271  std::map<size_t, std::pair<std::shared_ptr<MediaHandler>, size_t>>
272  output_handlers_;
273 };
274 
275 } // namespace media
276 } // namespace shaka
277 
278 #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.