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