1 // Copyright (c) 2016 The WebM project authors. All Rights Reserved.
2 //
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the LICENSE file in the root of the source
5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS. All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree.
8 #include "src/segment_parser.h"
9
10 #include <cstdint>
11
12 #include "gmock/gmock.h"
13 #include "gtest/gtest.h"
14
15 #include "test_utils/element_parser_test.h"
16 #include "webm/id.h"
17 #include "webm/status.h"
18
19 using testing::_;
20 using testing::DoAll;
21 using testing::InSequence;
22 using testing::NotNull;
23 using testing::Return;
24 using testing::SetArgPointee;
25
26 using webm::Action;
27 using webm::Ancestory;
28 using webm::ElementMetadata;
29 using webm::ElementParserTest;
30 using webm::Id;
31 using webm::SegmentParser;
32 using webm::Status;
33
34 namespace {
35
36 class SegmentParserTest
37 : public ElementParserTest<SegmentParser, Id::kSegment> {};
38
TEST_F(SegmentParserTest,EmptyParse)39 TEST_F(SegmentParserTest, EmptyParse) {
40 {
41 InSequence dummy;
42
43 EXPECT_CALL(callback_, OnSegmentBegin(metadata_, NotNull())).Times(1);
44 EXPECT_CALL(callback_, OnSegmentEnd(metadata_)).Times(1);
45 }
46
47 ParseAndVerify();
48 }
49
TEST_F(SegmentParserTest,DefaultActionIsRead)50 TEST_F(SegmentParserTest, DefaultActionIsRead) {
51 {
52 InSequence dummy;
53
54 // This intentionally does not set the action and relies on the parser using
55 // a default action value of kRead.
56 EXPECT_CALL(callback_, OnSegmentBegin(metadata_, NotNull()))
57 .WillOnce(Return(Status(Status::kOkCompleted)));
58 EXPECT_CALL(callback_, OnSegmentEnd(metadata_)).Times(1);
59 }
60
61 ParseAndVerify();
62 }
63
TEST_F(SegmentParserTest,EmptyParseWithDelayedStart)64 TEST_F(SegmentParserTest, EmptyParseWithDelayedStart) {
65 {
66 InSequence dummy;
67
68 EXPECT_CALL(callback_, OnSegmentBegin(metadata_, NotNull()))
69 .WillOnce(Return(Status(Status::kOkPartial)))
70 .WillOnce(DoAll(SetArgPointee<1>(Action::kRead),
71 Return(Status(Status::kOkCompleted))));
72
73 EXPECT_CALL(callback_, OnSegmentEnd(metadata_)).Times(1);
74 }
75
76 IncrementalParseAndVerify();
77 }
78
TEST_F(SegmentParserTest,DefaultValues)79 TEST_F(SegmentParserTest, DefaultValues) {
80 SetReaderData({
81 0x11, 0x4D, 0x9B, 0x74, // ID = 0x114D9B74 (SeekHead).
82 0x80, // Size = 0.
83
84 0x15, 0x49, 0xA9, 0x66, // ID = 0x1549A966 (Info).
85 0x80, // Size = 0.
86
87 0x1F, 0x43, 0xB6, 0x75, // ID = 0x1F43B675 (Cluster).
88 0x80, // Size = 0.
89
90 0x16, 0x54, 0xAE, 0x6B, // ID = 0x1654AE6B (Tracks).
91 0x80, // Size = 0.
92
93 0x1C, 0x53, 0xBB, 0x6B, // ID = 0x1C53BB6B (Cues).
94 0x80, // Size = 0.
95
96 0x10, 0x43, 0xA7, 0x70, // ID = 0x1043A770 (Chapters).
97 0x80, // Size = 0.
98
99 0x12, 0x54, 0xC3, 0x67, // ID = 0x1254C367 (Tags).
100 0x80, // Size = 0.
101 });
102
103 {
104 InSequence dummy;
105
106 EXPECT_CALL(callback_, OnSegmentBegin(metadata_, NotNull())).Times(1);
107
108 ElementMetadata metadata = {Id::kInfo, 5, 0, 5};
109 EXPECT_CALL(callback_, OnInfo(metadata, _)).Times(1);
110
111 metadata = {Id::kCluster, 5, 0, 10};
112 EXPECT_CALL(callback_, OnClusterBegin(metadata, _, NotNull())).Times(1);
113 EXPECT_CALL(callback_, OnClusterEnd(metadata, _)).Times(1);
114
115 EXPECT_CALL(callback_, OnSegmentEnd(metadata_)).Times(1);
116 }
117
118 ParseAndVerify();
119 }
120
TEST_F(SegmentParserTest,RepeatedValues)121 TEST_F(SegmentParserTest, RepeatedValues) {
122 SetReaderData({
123 // Mutliple SeekHead elements.
124 0x11, 0x4D, 0x9B, 0x74, // ID = 0x114D9B74 (SeekHead).
125 0x8D, // Size = 13.
126
127 0x4D, 0xBB, // ID = 0x4DBB (Seek).
128 0x10, 0x00, 0x00, 0x07, // Size = 7.
129
130 0x53, 0xAC, // ID = 0x53AC (SeekPosition).
131 0x10, 0x00, 0x00, 0x01, // Size = 1.
132 0x01, // Body (value = 1).
133
134 0x11, 0x4D, 0x9B, 0x74, // ID = 0x114D9B74 (SeekHead).
135 0x8D, // Size = 13.
136
137 0x4D, 0xBB, // ID = 0x4DBB (Seek).
138 0x10, 0x00, 0x00, 0x07, // Size = 7.
139
140 0x53, 0xAC, // ID = 0x53AC (SeekPosition).
141 0x10, 0x00, 0x00, 0x01, // Size = 1.
142 0x02, // Body (value = 2).
143
144 // Multiple Info elements.
145 0x15, 0x49, 0xA9, 0x66, // ID = 0x1549A966 (Info).
146 0x88, // Size = 8.
147
148 0x2A, 0xD7, 0xB1, // ID = 0x2AD7B1 (TimecodeScale).
149 0x10, 0x00, 0x00, 0x01, // Size = 1.
150 0x01, // Body (value = 1).
151
152 0x15, 0x49, 0xA9, 0x66, // ID = 0x1549A966 (Info).
153 0x88, // Size = 8.
154
155 0x2A, 0xD7, 0xB1, // ID = 0x2AD7B1 (TimecodeScale).
156 0x10, 0x00, 0x00, 0x01, // Size = 1.
157 0x02, // Body (value = 2).
158
159 // Multiple Cluster elements.
160 0x1F, 0x43, 0xB6, 0x75, // ID = 0x1F43B675 (Cluster).
161 0x86, // Size = 6.
162
163 0xE7, // ID = 0xE7 (Timecode).
164 0x10, 0x00, 0x00, 0x01, // Size = 1.
165 0x01, // Body (value = 1).
166
167 0x1F, 0x43, 0xB6, 0x75, // ID = 0x1F43B675 (Cluster).
168 0x86, // Size = 6.
169
170 0xE7, // ID = 0xE7 (Timecode).
171 0x10, 0x00, 0x00, 0x01, // Size = 1.
172 0x02, // Body (value = 2).
173
174 // Multiple Tracks elements.
175 0x16, 0x54, 0xAE, 0x6B, // ID = 0x1654AE6B (Tracks).
176 0x8B, // Size = 11.
177
178 0xAE, // ID = 0xAE (TrackEntry).
179 0x10, 0x00, 0x00, 0x06, // Size = 6.
180
181 0xD7, // ID = 0xD7 (TrackNumber).
182 0x10, 0x00, 0x00, 0x01, // Size = 1.
183 0x01, // Body (value = 1).
184
185 0x16, 0x54, 0xAE, 0x6B, // ID = 0x1654AE6B (Tracks).
186 0x8B, // Size = 11.
187
188 0xAE, // ID = 0xAE (TrackEntry).
189 0x10, 0x00, 0x00, 0x06, // Size = 6.
190
191 0xD7, // ID = 0xD7 (TrackNumber).
192 0x10, 0x00, 0x00, 0x01, // Size = 1.
193 0x02, // Body (value = 2).
194
195 // Single Cues element.
196 0x1C, 0x53, 0xBB, 0x6B, // ID = 0x1C53BB6B (Cues).
197 0x8B, // Size = 11.
198
199 0xBB, // ID = 0xBB (CuePoint).
200 0x10, 0x00, 0x00, 0x06, // Size = 6.
201
202 0xB3, // ID = 0xB3 (CueTime).
203 0x10, 0x00, 0x00, 0x01, // Size = 1.
204 0x01, // Body (value = 1).
205
206 // Single Chapters element.
207 0x10, 0x43, 0xA7, 0x70, // ID = 0x1043A770 (Chapters).
208 0x8D, // Size = 13.
209
210 0x45, 0xB9, // ID = 0x45B9 (EditionEntry).
211 0x10, 0x00, 0x00, 0x07, // Size = 7.
212
213 0x45, 0xBC, // ID = 0x45BC (EditionUID).
214 0x10, 0x00, 0x00, 0x01, // Size = 1.
215 0x01, // Body (value = 1).
216
217 // Multiple Tags elements.
218 0x12, 0x54, 0xC3, 0x67, // ID = 0x1254C367 (Tags).
219 0x93, // Size = 19.
220
221 0x73, 0x73, // ID = 0x7373 (Tag).
222 0x10, 0x00, 0x00, 0x0D, // Size = 13.
223
224 0x63, 0xC0, // ID = 0x63C0 (Targets).
225 0x10, 0x00, 0x00, 0x07, // Size = 7.
226
227 0x68, 0xCA, // ID = 0x68CA (TargetTypeValue).
228 0x10, 0x00, 0x00, 0x01, // Size = 1.
229 0x01, // Body (value = 1).
230
231 0x12, 0x54, 0xC3, 0x67, // ID = 0x1254C367 (Tags).
232 0x93, // Size = 19.
233
234 0x73, 0x73, // ID = 0x7373 (Tag).
235 0x10, 0x00, 0x00, 0x0D, // Size = 13.
236
237 0x63, 0xC0, // ID = 0x63C0 (Targets).
238 0x10, 0x00, 0x00, 0x07, // Size = 7.
239
240 0x68, 0xCA, // ID = 0x68CA (TargetTypeValue).
241 0x10, 0x00, 0x00, 0x01, // Size = 1.
242 0x02, // Body (value = 2).
243 });
244
245 {
246 InSequence dummy;
247
248 EXPECT_CALL(callback_, OnSegmentBegin(metadata_, NotNull())).Times(1);
249
250 EXPECT_CALL(callback_, OnSeek(_, _)).Times(2);
251
252 EXPECT_CALL(callback_, OnInfo(_, _)).Times(2);
253
254 EXPECT_CALL(callback_, OnClusterBegin(_, _, NotNull())).Times(1);
255 EXPECT_CALL(callback_, OnClusterEnd(_, _)).Times(1);
256
257 EXPECT_CALL(callback_, OnClusterBegin(_, _, NotNull())).Times(1);
258 EXPECT_CALL(callback_, OnClusterEnd(_, _)).Times(1);
259
260 EXPECT_CALL(callback_, OnTrackEntry(_, _)).Times(2);
261
262 EXPECT_CALL(callback_, OnCuePoint(_, _)).Times(1);
263
264 EXPECT_CALL(callback_, OnEditionEntry(_, _)).Times(1);
265
266 EXPECT_CALL(callback_, OnTag(_, _)).Times(2);
267
268 EXPECT_CALL(callback_, OnSegmentEnd(metadata_)).Times(1);
269 }
270
271 ParseAndVerify();
272 }
273
TEST_F(SegmentParserTest,Skip)274 TEST_F(SegmentParserTest, Skip) {
275 SetReaderData({
276 0x1F, 0x43, 0xB6, 0x75, // ID = 0x1F43B675 (Cluster).
277 0x80, // Size = 0.
278 });
279
280 {
281 InSequence dummy;
282
283 EXPECT_CALL(callback_, OnSegmentBegin(metadata_, NotNull()))
284 .WillOnce(Return(Status(Status::kOkPartial)))
285 .WillOnce(DoAll(SetArgPointee<1>(Action::kSkip),
286 Return(Status(Status::kOkCompleted))));
287
288 EXPECT_CALL(callback_, OnClusterBegin(_, _, _)).Times(0);
289 EXPECT_CALL(callback_, OnClusterEnd(_, _)).Times(0);
290
291 EXPECT_CALL(callback_, OnSegmentEnd(_)).Times(0);
292 }
293
294 IncrementalParseAndVerify();
295 }
296
TEST_F(SegmentParserTest,Seek)297 TEST_F(SegmentParserTest, Seek) {
298 SetReaderData({
299 // We start the reader at the beginning of a FlagInterlaced element
300 // (skipping its ID and size, as they're passed into InitAfterSeek).
301 // FlagInterlaced, StereoMode, and AlphaMode are all part of the Video
302 // element, with the ancestory: Segment -> Tracks -> TrackEntry -> Video.
303 0x01, // Body (value = 1).
304
305 0x53, 0xB8, // ID = 0x53B8 (StereoMode).
306 0x10, 0x00, 0x00, 0x01, // Size = 1.
307 0x02, // Body (value = 2).
308
309 0x53, 0xC0, // ID = 0x53C0 (AlphaMode).
310 0x10, 0x00, 0x00, 0x01, // Size = 1.
311 0x03, // Body (value = 3).
312
313 // Single Cues element.
314 0x1C, 0x53, 0xBB, 0x6B, // ID = 0x1C53BB6B (Cues).
315 0x8B, // Size = 11.
316
317 0xBB, // ID = 0xBB (CuePoint).
318 0x10, 0x00, 0x00, 0x06, // Size = 6.
319
320 0xB3, // ID = 0xB3 (CueTime).
321 0x10, 0x00, 0x00, 0x01, // Size = 1.
322 0x01, // Body (value = 1).
323 });
324
325 const ElementMetadata flag_interlaced_metadata = {Id::kFlagInterlaced, 0, 1,
326 0};
327
328 EXPECT_CALL(callback_, OnSegmentBegin(_, _)).Times(0);
329 {
330 InSequence dummy;
331
332 EXPECT_CALL(callback_, OnElementBegin(flag_interlaced_metadata, NotNull()))
333 .Times(1);
334
335 ElementMetadata metadata = {Id::kStereoMode, 6, 1, 1};
336 EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
337
338 metadata = {Id::kAlphaMode, 6, 1, 8};
339 EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
340
341 EXPECT_CALL(callback_, OnTrackEntry(_, _)).Times(1);
342
343 metadata = {Id::kCues, 5, 11, 15};
344 EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
345
346 metadata = {Id::kCuePoint, 5, 6, 20};
347 EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
348
349 metadata = {Id::kCueTime, 5, 1, 25};
350 EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
351
352 EXPECT_CALL(callback_, OnCuePoint(_, _)).Times(1);
353
354 EXPECT_CALL(callback_, OnSegmentEnd(_)).Times(1);
355 }
356
357 Ancestory ancestory;
358 ASSERT_TRUE(Ancestory::ById(flag_interlaced_metadata.id, &ancestory));
359 ancestory = ancestory.next(); // Skip the Segment ancestor.
360
361 parser_.InitAfterSeek(ancestory, flag_interlaced_metadata);
362
363 std::uint64_t num_bytes_read = 0;
364 const Status status = parser_.Feed(&callback_, &reader_, &num_bytes_read);
365 EXPECT_EQ(Status::kOkCompleted, status.code);
366 EXPECT_EQ(reader_.size(), num_bytes_read);
367 }
368
369 } // namespace
370