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  int64_t start_time = 0;
39  int64_t duration = 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  int64_t timestamp = 0;
49  CueEventType type = CueEventType::kCuePoint;
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);
189 
192  size_t stream_index, std::shared_ptr<const StreamInfo> stream_info) {
193  return Dispatch(StreamData::FromStreamInfo(stream_index, stream_info));
194  }
195 
198  size_t stream_index, std::shared_ptr<const MediaSample> media_sample) {
199  return Dispatch(StreamData::FromMediaSample(stream_index, media_sample));
200  }
201 
203  // DispatchTextSample should only be override for testing.
205  size_t stream_index, std::shared_ptr<const TextSample> text_sample) {
206  return Dispatch(StreamData::FromTextSample(stream_index, text_sample));
207  }
208 
211  size_t stream_index, std::shared_ptr<const SegmentInfo> segment_info) {
212  return Dispatch(StreamData::FromSegmentInfo(stream_index, segment_info));
213  }
214 
216  Status DispatchScte35Event(size_t stream_index,
217  std::shared_ptr<const Scte35Event> scte35_event) {
218  return Dispatch(StreamData::FromScte35Event(stream_index, scte35_event));
219  }
220 
222  Status DispatchCueEvent(size_t stream_index,
223  std::shared_ptr<const CueEvent> cue_event) {
224  return Dispatch(StreamData::FromCueEvent(stream_index, cue_event));
225  }
226 
228  Status FlushDownstream(size_t output_stream_index);
229 
231  Status FlushAllDownstreams();
232 
233  bool initialized() { return initialized_; }
234  size_t num_input_streams() const { return num_input_streams_; }
235  size_t next_output_stream_index() const { return next_output_stream_index_; }
236  const std::map<size_t, std::pair<std::shared_ptr<MediaHandler>, size_t>>&
237  output_handlers() {
238  return output_handlers_;
239  }
240 
241  private:
242  MediaHandler(const MediaHandler&) = delete;
243  MediaHandler& operator=(const MediaHandler&) = delete;
244 
245  bool initialized_ = false;
246  // Number of input streams.
247  size_t num_input_streams_ = 0;
248  // The next available output stream index, used by AddHandler.
249  size_t next_output_stream_index_ = 0;
250  // output stream index -> {output handler, output handler input stream index}
251  // map.
252  std::map<size_t, std::pair<std::shared_ptr<MediaHandler>, size_t>>
253  output_handlers_;
254 };
255 
256 } // namespace media
257 } // namespace shaka
258 
259 #endif // PACKAGER_MEDIA_BASE_MEDIA_HANDLER_H_
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)
Dispatch the text sample to downsream handlers.
Status DispatchScte35Event(size_t stream_index, std::shared_ptr< const Scte35Event > scte35_event)
Dispatch the scte35 event to downstream handlers.
Status AddHandler(std::shared_ptr< MediaHandler > handler)
Connect downstream handler to the next availble output stream index.
Status DispatchStreamInfo(size_t stream_index, std::shared_ptr< const StreamInfo > stream_info)
Dispatch the stream info to downstream handlers.
Status DispatchMediaSample(size_t stream_index, std::shared_ptr< const MediaSample > media_sample)
Dispatch the media sample to downstream handlers.
Status DispatchCueEvent(size_t stream_index, std::shared_ptr< const CueEvent > cue_event)
Dispatch the cue event to downstream handlers.
Status DispatchSegmentInfo(size_t stream_index, std::shared_ptr< const SegmentInfo > segment_info)
Dispatch the segment info to downstream handlers.