Shaka Packager SDK
media_handler_test_base.cc
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 #include <packager/media/base/media_handler_test_base.h>
8 
9 #include <absl/log/check.h>
10 
11 #include <packager/macros/compiler.h>
12 #include <packager/media/base/audio_stream_info.h>
13 #include <packager/media/base/text_stream_info.h>
14 #include <packager/media/base/video_stream_info.h>
15 #include <packager/status/status_test_util.h>
16 
17 namespace {
18 
19 const int kTrackId = 1;
20 const int64_t kDuration = 10000;
21 const char kCodecString[] = "codec string";
22 const uint8_t kSampleBits = 1;
23 const uint8_t kNumChannels = 2;
24 const uint32_t kSamplingFrequency = 48000;
25 const uint64_t kSeekPrerollNs = 12345;
26 const uint64_t kCodecDelayNs = 56789;
27 const uint32_t kMaxBitrate = 13579;
28 const uint32_t kAvgBitrate = 13000;
29 const char kLanguage[] = "eng";
30 const uint32_t kWidth = 10u;
31 const uint32_t kHeight = 20u;
32 const uint32_t kPixelWidth = 2u;
33 const uint32_t kPixelHeight = 3u;
34 const uint8_t kColorPrimaries = 0;
35 const uint8_t kMatrixCoefficients = 0;
36 const uint8_t kTransferCharacteristics = 0;
37 
38 const int16_t kTrickPlayFactor = 0;
39 const uint8_t kNaluLengthSize = 1u;
40 const bool kEncrypted = true;
41 
42 // Use H264 code config.
43 const uint8_t kCodecConfig[]{
44  // clang-format off
45  // Header
46  0x01, 0x64, 0x00, 0x1e, 0xff,
47  // SPS count (ignore top three bits)
48  0xe1,
49  // SPS
50  0x00, 0x19, // Size
51  0x67, 0x64, 0x00, 0x1e, 0xac, 0xd9, 0x40, 0xa0, 0x2f, 0xf9, 0x70, 0x11,
52  0x00, 0x00, 0x03, 0x03, 0xe9, 0x00, 0x00, 0xea, 0x60, 0x0f, 0x16, 0x2d,
53  0x96,
54  // PPS count
55  0x01,
56  // PPS
57  0x00, 0x06, // Size
58  0x68, 0xeb, 0xe3, 0xcb, 0x22, 0xc0,
59  // clang-format on
60 };
61 
62 // Mock data, we don't really care about what is inside.
63 const uint8_t kData[]{
64  0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
65 };
66 
67 } // namespace
68 
69 namespace shaka {
70 namespace media {
71 
72 std::string BoolToString(bool value) {
73  return value ? "true" : "false";
74 }
75 
76 bool TryMatchStreamDataType(const StreamDataType& actual,
77  const StreamDataType& expected,
78  ::testing::MatchResultListener* listener) {
79  if (actual != expected) {
80  std::string expected_as_string = StreamDataTypeToString(expected);
81  std::string actual_as_string = StreamDataTypeToString(actual);
82 
83  *listener << "which is " << actual_as_string << " (expected "
84  << expected_as_string << ")";
85  return false;
86  }
87 
88  return true;
89 }
90 
91 bool TryMatchStreamType(const StreamType& actual,
92  const StreamType& expected,
93  ::testing::MatchResultListener* listener) {
94  if (actual != expected) {
95  std::string expected_as_string = StreamTypeToString(expected);
96  std::string actual_as_string = StreamTypeToString(actual);
97 
98  *listener << "which is " << actual_as_string << " (expected "
99  << expected_as_string << ")";
100  return false;
101  }
102 
103  return true;
104 }
105 
106 std::string ToPrettyString(const std::string& str) {
107  std::string out;
108 
109  // Opening quotation.
110  out.push_back('"');
111 
112  for (char c : str) {
113  if (isspace(c)) {
114  // Make all white space characters spaces to avoid print issues in
115  // the terminal.
116  out.push_back(' ');
117  } else if (isalnum(c)) {
118  // If the character is alpha-numeric, then print it as is. Just using
119  // these characters, it should be enough to understand the string.
120  out.push_back(c);
121  } else {
122  // Replace all other characters with '.'. This is to avoid print issues
123  // (e.g. \n) or readability issues (e.g. ").
124  out.push_back('.');
125  }
126  }
127 
128  // Closing quotation.
129  out.push_back('"');
130 
131  return out;
132 }
133 
134 bool FakeInputMediaHandler::ValidateOutputStreamIndex(size_t index) const {
135  UNUSED(index);
136  return true;
137 }
138 
139 Status FakeInputMediaHandler::InitializeInternal() {
140  return Status::OK;
141 }
142 
143 Status FakeInputMediaHandler::Process(std::unique_ptr<StreamData> stream_data) {
144  UNUSED(stream_data);
145  return Status(error::INTERNAL_ERROR,
146  "FakeInputMediaHandler should never be a downstream handler.");
147 }
148 
149 Status MockOutputMediaHandler::InitializeInternal() {
150  return Status::OK;
151 }
152 
153 Status MockOutputMediaHandler::Process(
154  std::unique_ptr<StreamData> stream_data) {
155  OnProcess(stream_data.get());
156  return Status::OK;
157 }
158 
159 Status MockOutputMediaHandler::OnFlushRequest(size_t index) {
160  OnFlush(index);
161  return Status::OK;
162 }
163 
164 Status CachingMediaHandler::InitializeInternal() {
165  return Status::OK;
166 }
167 
168 Status CachingMediaHandler::Process(std::unique_ptr<StreamData> stream_data) {
169  stream_data_vector_.push_back(std::move(stream_data));
170  return Status::OK;
171 }
172 
173 Status CachingMediaHandler::OnFlushRequest(size_t input_stream_index) {
174  UNUSED(input_stream_index);
175  return Status::OK;
176 }
177 
178 bool CachingMediaHandler::ValidateOutputStreamIndex(size_t stream_index) const {
179  UNUSED(stream_index);
180  return true;
181 }
182 
183 bool MediaHandlerTestBase::IsVideoCodec(Codec codec) const {
184  return codec >= kCodecVideo && codec < kCodecVideoMaxPlusOne;
185 }
186 
187 std::unique_ptr<StreamInfo> MediaHandlerTestBase::GetVideoStreamInfo(
188  int32_t time_scale) const {
189  return GetVideoStreamInfo(time_scale, kCodecVP9, kWidth, kHeight);
190 }
191 
192 std::unique_ptr<StreamInfo> MediaHandlerTestBase::GetVideoStreamInfo(
193  int32_t time_scale,
194  uint32_t width,
195  uint32_t height) const {
196  return GetVideoStreamInfo(time_scale, kCodecVP9, width, height);
197 }
198 
199 std::unique_ptr<StreamInfo> MediaHandlerTestBase::GetVideoStreamInfo(
200  int32_t time_scale,
201  Codec codec) const {
202  return GetVideoStreamInfo(time_scale, codec, kWidth, kHeight);
203 }
204 
205 std::unique_ptr<StreamInfo> MediaHandlerTestBase::GetVideoStreamInfo(
206  int32_t time_scale,
207  Codec codec,
208  uint32_t width,
209  uint32_t height) const {
210  return std::unique_ptr<VideoStreamInfo>(new VideoStreamInfo(
211  kTrackId, time_scale, kDuration, codec, H26xStreamFormat::kUnSpecified,
212  kCodecString, kCodecConfig, sizeof(kCodecConfig), width, height,
213  kPixelWidth, kPixelHeight, kColorPrimaries, kMatrixCoefficients,
214  kTransferCharacteristics, kTrickPlayFactor, kNaluLengthSize, kLanguage,
215  !kEncrypted));
216 }
217 
218 std::unique_ptr<StreamInfo> MediaHandlerTestBase::GetAudioStreamInfo(
219  int32_t time_scale) const {
220  return GetAudioStreamInfo(time_scale, kCodecAAC);
221 }
222 
223 std::unique_ptr<StreamInfo> MediaHandlerTestBase::GetAudioStreamInfo(
224  int32_t time_scale,
225  Codec codec) const {
226  return std::unique_ptr<AudioStreamInfo>(new AudioStreamInfo(
227  kTrackId, time_scale, kDuration, codec, kCodecString, kCodecConfig,
228  sizeof(kCodecConfig), kSampleBits, kNumChannels, kSamplingFrequency,
229  kSeekPrerollNs, kCodecDelayNs, kMaxBitrate, kAvgBitrate, kLanguage,
230  !kEncrypted));
231 }
232 
233 std::shared_ptr<MediaSample> MediaHandlerTestBase::GetMediaSample(
234  int64_t timestamp,
235  int64_t duration,
236  bool is_keyframe) const {
237  return GetMediaSample(timestamp, duration, is_keyframe, kData, sizeof(kData));
238 }
239 
240 std::shared_ptr<MediaSample> MediaHandlerTestBase::GetMediaSample(
241  int64_t timestamp,
242  int64_t duration,
243  bool is_keyframe,
244  const uint8_t* data,
245  size_t data_length) const {
246  std::shared_ptr<MediaSample> sample =
247  MediaSample::CopyFrom(data, data_length, nullptr, 0, is_keyframe);
248  sample->set_dts(timestamp);
249  sample->set_pts(timestamp);
250  sample->set_duration(duration);
251 
252  return sample;
253 }
254 
255 std::unique_ptr<SegmentInfo> MediaHandlerTestBase::GetSegmentInfo(
256  int64_t start_timestamp,
257  int64_t duration,
258  bool is_subsegment,
259  int64_t segment_number) const {
260  std::unique_ptr<SegmentInfo> info(new SegmentInfo);
261  info->start_timestamp = start_timestamp;
262  info->duration = duration;
263  info->is_subsegment = is_subsegment;
264  info->segment_number = segment_number;
265 
266  return info;
267 }
268 
269 std::unique_ptr<StreamInfo> MediaHandlerTestBase::GetTextStreamInfo(
270  int32_t timescale) const {
271  // None of this information is actually used by the text out handler.
272  // The stream info is just needed to signal the start of the stream.
273  return std::unique_ptr<StreamInfo>(
274  new TextStreamInfo(0, timescale, 0, kUnknownCodec, "", "", 0, 0, ""));
275 }
276 
277 std::unique_ptr<TextSample> MediaHandlerTestBase::GetTextSample(
278  const std::string& id,
279  int64_t start,
280  int64_t end,
281  const std::string& payload) const {
282  return std::unique_ptr<TextSample>{
283  new TextSample(id, start, end, {}, TextFragment{{}, payload})};
284 }
285 
286 std::unique_ptr<CueEvent> MediaHandlerTestBase::GetCueEvent(
287  double time_in_seconds) const {
288  std::unique_ptr<CueEvent> event(new CueEvent);
289  event->time_in_seconds = time_in_seconds;
290 
291  return event;
292 }
293 
294 Status MediaHandlerTestBase::SetUpAndInitializeGraph(
295  std::shared_ptr<MediaHandler> handler,
296  size_t input_count,
297  size_t output_count) {
298  DCHECK(handler);
299  DCHECK_EQ(nullptr, handler_);
300  DCHECK(inputs_.empty());
301  DCHECK(outputs_.empty());
302 
303  handler_ = std::move(handler);
304 
305  Status status;
306 
307  // Add and connect all the requested inputs.
308  for (size_t i = 0; i < input_count; i++) {
309  inputs_.emplace_back(new FakeInputMediaHandler);
310  }
311 
312  for (auto& input : inputs_) {
313  status.Update(input->AddHandler(handler_));
314  }
315 
316  if (!status.ok()) {
317  return status;
318  }
319 
320  // Add and connect all the requested outputs.
321  for (size_t i = 0; i < output_count; i++) {
322  outputs_.emplace_back(new testing::NiceMock<MockOutputMediaHandler>);
323  }
324 
325  for (auto& output : outputs_) {
326  status.Update(handler_->AddHandler(output));
327  }
328 
329  if (!status.ok()) {
330  return status;
331  }
332 
333  // Initialize the graph.
334  for (auto& input : inputs_) {
335  status.Update(input->Initialize());
336  }
337 
338  // In the case that there are no inputs, the start of the graph
339  // is at |handler_| so it needs to be initialized or else the graph
340  // won't be initialized.
341  if (inputs_.empty()) {
342  status.Update(handler_->Initialize());
343  }
344 
345  return status;
346 }
347 
348 FakeInputMediaHandler* MediaHandlerTestBase::Input(size_t index) {
349  DCHECK_LT(index, inputs_.size());
350  return inputs_[index].get();
351 }
352 
353 MockOutputMediaHandler* MediaHandlerTestBase::Output(size_t index) {
354  DCHECK_LT(index, outputs_.size());
355  return outputs_[index].get();
356 }
357 
358 MediaHandlerGraphTestBase::MediaHandlerGraphTestBase()
359  : next_handler_(new CachingMediaHandler),
360  some_handler_(new CachingMediaHandler) {}
361 
362 void MediaHandlerGraphTestBase::SetUpGraph(
363  size_t num_inputs,
364  size_t num_outputs,
365  std::shared_ptr<MediaHandler> handler) {
366  // Input handler is not really used anywhere else except to validate number of
367  // allowed inputs for the handler to be tested.
368  auto input_handler = std::make_shared<CachingMediaHandler>();
369  for (size_t i = 0; i < num_inputs; ++i)
370  ASSERT_OK(input_handler->SetHandler(i, handler));
371  // All outputs are routed to |next_handler_|.
372  for (size_t i = 0; i < num_outputs; ++i)
373  ASSERT_OK(handler->SetHandler(i, next_handler_));
374 }
375 
376 const std::vector<std::unique_ptr<StreamData>>&
377 MediaHandlerGraphTestBase::GetOutputStreamDataVector() const {
378  return next_handler_->Cache();
379 }
380 
381 void MediaHandlerGraphTestBase::ClearOutputStreamDataVector() {
382  next_handler_->Clear();
383 }
384 
385 } // namespace media
386 } // namespace shaka
static std::shared_ptr< MediaSample > CopyFrom(const uint8_t *data, size_t size, bool is_key_frame)
Definition: media_sample.cc:43
All the methods that are virtual are virtual for mocking.
Definition: crypto_flags.cc:66