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 // Scte35Event represents cuepoint markers in input streams. It will be used
33 // to represent out of band cuepoint markers too.
34 struct Scte35Event {
35  std::string id;
36  // Segmentation type id from SCTE35 segmentation descriptor.
37  int type = 0;
38  double start_time_in_seconds = 0;
39  double duration_in_seconds = 0;
40  std::string cue_data;
41 };
42 
43 enum class CueEventType { kCueIn, kCueOut, kCuePoint };
44 
45 // In server-based model, Chunking Handler consolidates SCTE-35 events and
46 // generates CueEvent before an ad is about to be inserted.
47 struct CueEvent {
48  CueEventType type = CueEventType::kCuePoint;
49  double time_in_seconds;
50  std::string cue_data;
51 };
52 
53 struct SegmentInfo {
54  bool is_subsegment = false;
55  bool is_encrypted = false;
56  int64_t start_timestamp = -1;
57  int64_t duration = 0;
58  // This is only available if key rotation is enabled. Note that we may have
59  // a |key_rotation_encryption_config| even if the segment is not encrypted,
60  // which is the case for clear lead.
61  std::shared_ptr<EncryptionConfig> key_rotation_encryption_config;
62 };
63 
64 // TODO(kqyang): Should we use protobuf?
65 struct StreamData {
66  size_t stream_index = static_cast<size_t>(-1);
67  StreamDataType stream_data_type = StreamDataType::kUnknown;
68 
69  std::shared_ptr<const StreamInfo> stream_info;
70  std::shared_ptr<const MediaSample> media_sample;
71  std::shared_ptr<const TextSample> text_sample;
72  std::shared_ptr<const SegmentInfo> segment_info;
73  std::shared_ptr<const Scte35Event> scte35_event;
74  std::shared_ptr<const CueEvent> cue_event;
75 
76  static std::unique_ptr<StreamData> FromStreamInfo(
77  size_t stream_index, std::shared_ptr<const StreamInfo> stream_info) {
78  std::unique_ptr<StreamData> stream_data(new StreamData);
79  stream_data->stream_index = stream_index;
80  stream_data->stream_data_type = StreamDataType::kStreamInfo;
81  stream_data->stream_info = std::move(stream_info);
82  return stream_data;
83  }
84 
85  static std::unique_ptr<StreamData> FromMediaSample(
86  size_t stream_index, std::shared_ptr<const MediaSample> media_sample) {
87  std::unique_ptr<StreamData> stream_data(new StreamData);
88  stream_data->stream_index = stream_index;
89  stream_data->stream_data_type = StreamDataType::kMediaSample;
90  stream_data->media_sample = std::move(media_sample);
91  return stream_data;
92  }
93 
94  static std::unique_ptr<StreamData> FromTextSample(
95  size_t stream_index, std::shared_ptr<const TextSample> text_sample) {
96  std::unique_ptr<StreamData> stream_data(new StreamData);
97  stream_data->stream_index = stream_index;
98  stream_data->stream_data_type = StreamDataType::kTextSample;
99  stream_data->text_sample = std::move(text_sample);
100  return stream_data;
101  }
102 
103  static std::unique_ptr<StreamData> FromSegmentInfo(
104  size_t stream_index, std::shared_ptr<const SegmentInfo> segment_info) {
105  std::unique_ptr<StreamData> stream_data(new StreamData);
106  stream_data->stream_index = stream_index;
107  stream_data->stream_data_type = StreamDataType::kSegmentInfo;
108  stream_data->segment_info = std::move(segment_info);
109  return stream_data;
110  }
111 
112  static std::unique_ptr<StreamData> FromScte35Event(
113  size_t stream_index,
114  std::shared_ptr<const Scte35Event> scte35_event) {
115  std::unique_ptr<StreamData> stream_data(new StreamData);
116  stream_data->stream_index = stream_index;
117  stream_data->stream_data_type = StreamDataType::kScte35Event;
118  stream_data->scte35_event = std::move(scte35_event);
119  return stream_data;
120  }
121 
122  static std::unique_ptr<StreamData> FromCueEvent(
123  size_t stream_index,
124  std::shared_ptr<const CueEvent> cue_event) {
125  std::unique_ptr<StreamData> stream_data(new StreamData);
126  stream_data->stream_index = stream_index;
127  stream_data->stream_data_type = StreamDataType::kCueEvent;
128  stream_data->cue_event = std::move(cue_event);
129  return stream_data;
130  }
131 };
132 
149  public:
150  MediaHandler() = default;
151  virtual ~MediaHandler() = default;
152 
154  Status SetHandler(size_t output_stream_index,
155  std::shared_ptr<MediaHandler> handler);
156 
158  Status AddHandler(std::shared_ptr<MediaHandler> handler) {
159  return SetHandler(next_output_stream_index_, handler);
160  }
161 
164  Status Initialize();
165 
167  bool IsConnected() { return num_input_streams_ > 0; }
168 
169  protected:
172  virtual Status InitializeInternal() = 0;
173 
178  virtual Status Process(std::unique_ptr<StreamData> stream_data) = 0;
179 
181  virtual Status OnFlushRequest(size_t input_stream_index);
182 
184  virtual bool ValidateOutputStreamIndex(size_t stream_index) const;
185 
188  Status Dispatch(std::unique_ptr<StreamData> stream_data) const;
189 
192  size_t stream_index,
193  std::shared_ptr<const StreamInfo> stream_info) const {
194  return Dispatch(
195  StreamData::FromStreamInfo(stream_index, std::move(stream_info)));
196  }
197 
200  size_t stream_index,
201  std::shared_ptr<const MediaSample> media_sample) const {
202  return Dispatch(
203  StreamData::FromMediaSample(stream_index, std::move(media_sample)));
204  }
205 
207  // DispatchTextSample should only be override for testing.
209  size_t stream_index,
210  std::shared_ptr<const TextSample> text_sample) const {
211  return Dispatch(
212  StreamData::FromTextSample(stream_index, std::move(text_sample)));
213  }
214 
217  size_t stream_index,
218  std::shared_ptr<const SegmentInfo> segment_info) const {
219  return Dispatch(
220  StreamData::FromSegmentInfo(stream_index, std::move(segment_info)));
221  }
222 
225  size_t stream_index,
226  std::shared_ptr<const Scte35Event> scte35_event) const {
227  return Dispatch(
228  StreamData::FromScte35Event(stream_index, std::move(scte35_event)));
229  }
230 
232  Status DispatchCueEvent(size_t stream_index,
233  std::shared_ptr<const CueEvent> cue_event) const {
234  return Dispatch(
235  StreamData::FromCueEvent(stream_index, std::move(cue_event)));
236  }
237 
239  Status FlushDownstream(size_t output_stream_index);
240 
242  Status FlushAllDownstreams();
243 
244  bool initialized() { return initialized_; }
245  size_t num_input_streams() const { return num_input_streams_; }
246  size_t next_output_stream_index() const { return next_output_stream_index_; }
247  const std::map<size_t, std::pair<std::shared_ptr<MediaHandler>, size_t>>&
248  output_handlers() {
249  return output_handlers_;
250  }
251 
252  private:
253  MediaHandler(const MediaHandler&) = delete;
254  MediaHandler& operator=(const MediaHandler&) = delete;
255 
256  bool initialized_ = false;
257  // Number of input streams.
258  size_t num_input_streams_ = 0;
259  // The next available output stream index, used by AddHandler.
260  size_t next_output_stream_index_ = 0;
261  // output stream index -> {output handler, output handler input stream index}
262  // map.
263  std::map<size_t, std::pair<std::shared_ptr<MediaHandler>, size_t>>
264  output_handlers_;
265 };
266 
267 } // namespace media
268 } // namespace shaka
269 
270 #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.