Shaka Packager SDK
segmenter_test_base.cc
1 // Copyright 2015 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/formats/webm/segmenter_test_base.h>
8 
9 #include <absl/log/check.h>
10 
11 #include <packager/file/memory_file.h>
12 #include <packager/media/formats/webm/webm_constants.h>
13 #include <packager/version/version.h>
14 
15 namespace shaka {
16 namespace media {
17 namespace {
18 
19 // The contents of a frame does not mater.
20 const uint8_t kTestMediaSampleData[] = {0xde, 0xad, 0xbe, 0xef, 0x00};
21 const uint8_t kTestMediaSampleSideData[] = {
22  // First 8 bytes of side_data is the BlockAddID element in big endian.
23  0x12, 0x34, 0x56, 0x78, 0x9a, 0x00, 0x00, 0x00,
24  0x73, 0x69, 0x64, 0x65, 0x00};
25 
26 const int kTrackId = 1;
27 const int64_t kDurationInSeconds = 8;
28 const Codec kCodec = kCodecVP8;
29 const std::string kCodecString = "vp8";
30 const std::string kLanguage = "en";
31 const uint16_t kWidth = 100;
32 const uint16_t kHeight = 100;
33 const uint16_t kPixelWidth = 100;
34 const uint16_t kPixelHeight = 100;
35 const uint8_t kColorPrimaries = 0;
36 const uint8_t kMatrixCoefficients = 0;
37 const uint8_t kTransferCharacteristics = 0;
38 const int16_t kTrickPlayFactor = 1;
39 const uint8_t kNaluLengthSize = 0;
40 
41 } // namespace
42 
43 SegmentTestBase::SegmentTestBase() {}
44 
45 void SegmentTestBase::SetUp() {
46  SetPackagerVersionForTesting("test");
47 
48  output_file_name_ = std::string(kMemoryFilePrefix) + "output-file.webm";
49  cur_timestamp_ = 0;
50 }
51 
52 void SegmentTestBase::TearDown() {
54 }
55 
56 std::shared_ptr<MediaSample> SegmentTestBase::CreateSample(
57  KeyFrameFlag key_frame_flag,
58  int64_t duration,
59  SideDataFlag side_data_flag) {
60  std::shared_ptr<MediaSample> sample;
61  const bool is_key_frame = key_frame_flag == kKeyFrame;
62  if (side_data_flag == kGenerateSideData) {
63  sample = MediaSample::CopyFrom(
64  kTestMediaSampleData, sizeof(kTestMediaSampleData),
65  kTestMediaSampleSideData, sizeof(kTestMediaSampleSideData),
66  is_key_frame);
67  } else {
68  sample = MediaSample::CopyFrom(kTestMediaSampleData,
69  sizeof(kTestMediaSampleData), is_key_frame);
70  }
71  sample->set_dts(cur_timestamp_);
72  sample->set_pts(cur_timestamp_);
73  sample->set_duration(duration);
74 
75  cur_timestamp_ += duration;
76  return sample;
77 }
78 
80  MuxerOptions ret;
81  ret.output_file_name = output_file_name_;
82  // Use memory files for temp storage. Normally this would be a bad idea
83  // since it wouldn't support large files, but for tests the files are small.
84  ret.temp_dir = std::string(kMemoryFilePrefix) + "temp/";
85  return ret;
86 }
87 
89  int32_t time_scale) const {
90  return new VideoStreamInfo(
91  kTrackId, time_scale, kDurationInSeconds * time_scale, kCodec,
92  H26xStreamFormat::kUnSpecified, kCodecString, NULL, 0, kWidth, kHeight,
93  kPixelWidth, kPixelHeight, kColorPrimaries, kMatrixCoefficients,
94  kTransferCharacteristics, kTrickPlayFactor, kNaluLengthSize, kLanguage,
95  false);
96 }
97 
98 std::string SegmentTestBase::OutputFileName() const {
99  return output_file_name_;
100 }
101 
102 SegmentTestBase::ClusterParser::ClusterParser() {}
103 
104 SegmentTestBase::ClusterParser::~ClusterParser() {}
105 
106 void SegmentTestBase::ClusterParser::PopulateFromCluster(
107  const std::string& file_name) {
108  frame_timecodes_.clear();
109  std::string file_contents;
110  ASSERT_TRUE(File::ReadFileToString(file_name.c_str(), &file_contents));
111 
112  const uint8_t* data = reinterpret_cast<const uint8_t*>(file_contents.c_str());
113  const size_t size = file_contents.size();
114  WebMListParser cluster_parser(kWebMIdCluster, this);
115  size_t position = 0;
116  while (position < size) {
117  int read = cluster_parser.Parse(data + position,
118  static_cast<int>(size - position));
119  ASSERT_LT(0, read);
120 
121  cluster_parser.Reset();
122  position += read;
123  }
124 }
125 
126 void SegmentTestBase::ClusterParser::PopulateFromSegment(
127  const std::string& file_name) {
128  frame_timecodes_.clear();
129  std::string file_contents;
130  ASSERT_TRUE(File::ReadFileToString(file_name.c_str(), &file_contents));
131 
132  const uint8_t* data = reinterpret_cast<const uint8_t*>(file_contents.c_str());
133  const size_t size = file_contents.size();
134  WebMListParser header_parser(kWebMIdEBMLHeader, this);
135  int offset = header_parser.Parse(data, static_cast<int>(size));
136  ASSERT_LT(0, offset);
137 
138  WebMListParser segment_parser(kWebMIdSegment, this);
139  ASSERT_LT(
140  0, segment_parser.Parse(data + offset, static_cast<int>(size) - offset));
141 }
142 
143 size_t SegmentTestBase::ClusterParser::GetFrameCountForCluster(
144  size_t cluster_index) const {
145  DCHECK_LT(cluster_index, frame_timecodes_.size());
146  return frame_timecodes_[cluster_index].size();
147 }
148 
149 int64_t SegmentTestBase::ClusterParser::GetFrameTimecode(
150  size_t cluster_index,
151  size_t frame_index) const {
152  DCHECK_LT(cluster_index, frame_timecodes_.size());
153  DCHECK_LT(frame_index, frame_timecodes_[cluster_index].size());
154  return frame_timecodes_[cluster_index][frame_index];
155 }
156 
157 size_t SegmentTestBase::ClusterParser::cluster_count() const {
158  return frame_timecodes_.size();
159 }
160 
161 WebMParserClient* SegmentTestBase::ClusterParser::OnListStart(int id) {
162  if (id == kWebMIdCluster) {
163  if (in_cluster_)
164  return NULL;
165 
166  frame_timecodes_.emplace_back();
167  cluster_timecode_ = -1;
168  in_cluster_ = true;
169  }
170 
171  return this;
172 }
173 
174 bool SegmentTestBase::ClusterParser::OnListEnd(int id) {
175  if (id == kWebMIdCluster) {
176  if (!in_cluster_)
177  return false;
178  in_cluster_ = false;
179  }
180 
181  return true;
182 }
183 
184 bool SegmentTestBase::ClusterParser::OnUInt(int id, int64_t val) {
185  if (id == kWebMIdTimecode)
186  cluster_timecode_ = val;
187  return true;
188 }
189 
190 bool SegmentTestBase::ClusterParser::OnFloat(int /*id*/, double /*val*/) {
191  return true;
192 }
193 
194 bool SegmentTestBase::ClusterParser::OnBinary(int id,
195  const uint8_t* data,
196  int /*size*/) {
197  if (in_cluster_ && (id == kWebMIdSimpleBlock || id == kWebMIdBlock)) {
198  if (cluster_timecode_ == -1) {
199  LOG(WARNING) << "Cluster timecode not yet available";
200  return false;
201  }
202  int timecode = data[1] << 8 | data[2];
203  frame_timecodes_.back().push_back(cluster_timecode_ + timecode);
204  }
205 
206  return true;
207 }
208 
209 bool SegmentTestBase::ClusterParser::OnString(int /*id*/,
210  const std::string& /*str*/) {
211  return true;
212 }
213 
214 } // namespace media
215 } // namespace shaka
static void DeleteAll()
Definition: memory_file.cc:190
static std::shared_ptr< MediaSample > CopyFrom(const uint8_t *data, size_t size, bool is_key_frame)
Definition: media_sample.cc:43
VideoStreamInfo * CreateVideoStreamInfo(int32_t time_scale) const
Creates a video stream info object for testing.
MuxerOptions CreateMuxerOptions() const
Creates a Muxer options object for testing.
std::string OutputFileName() const
Gets the file name of the current output file.
std::shared_ptr< MediaSample > CreateSample(KeyFrameFlag key_frame_flag, int64_t duration, SideDataFlag side_data_flag)
Creates a new media sample.
Holds video stream information.
All the methods that are virtual are virtual for mocking.
Definition: crypto_flags.cc:66
This structure contains the list of configuration options for Muxer.
Definition: muxer_options.h:19
std::string temp_dir
Specify temporary directory for intermediate files.
Definition: muxer_options.h:42