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