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 <stdint.h>
9
10 #include <array>
11 #include <cstdio>
12 #include <cstring>
13 #include <iomanip>
14 #include <memory>
15 #include <ostream>
16 #include <string>
17
18 #include "gtest/gtest.h"
19
20 #include "common/file_util.h"
21 #include "common/libwebm_util.h"
22 #include "mkvmuxer/mkvmuxer.h"
23 #include "mkvmuxer/mkvwriter.h"
24 #include "mkvparser/mkvreader.h"
25 #include "testing/test_util.h"
26
27 using mkvmuxer::AudioTrack;
28 using mkvmuxer::Chapter;
29 using mkvmuxer::Frame;
30 using mkvmuxer::MkvWriter;
31 using mkvmuxer::Segment;
32 using mkvmuxer::SegmentInfo;
33 using mkvmuxer::Tag;
34 using mkvmuxer::Track;
35 using mkvmuxer::VideoTrack;
36
37 namespace test {
38
39 // Base class containing boiler plate stuff.
40 class MuxerTest : public testing::Test {
41 public:
MuxerTest()42 MuxerTest() { Init(); }
43
~MuxerTest()44 ~MuxerTest() { CloseWriter(); }
45
46 // Simple init function for use by constructor. Calls made here to allow use
47 // of ASSERT_* macros-- this is necessary here because all failures in Init()
48 // are fatal, but the ASSERT_* gtest macros cannot be used in a constructor.
Init()49 void Init() {
50 ASSERT_TRUE(GetTestDataDir().length() > 0);
51 filename_ = libwebm::GetTempFileName();
52 ASSERT_GT(filename_.length(), 0u);
53 temp_file_ = libwebm::FilePtr(std::fopen(filename_.c_str(), "wb"),
54 libwebm::FILEDeleter());
55 ASSERT_TRUE(temp_file_.get() != nullptr);
56 writer_.reset(new MkvWriter(temp_file_.get()));
57 is_writer_open_ = true;
58 memset(dummy_data_, 0, kFrameLength);
59 }
60
AddDummyFrameAndFinalize(int track_number)61 void AddDummyFrameAndFinalize(int track_number) {
62 EXPECT_TRUE(segment_.AddFrame(&dummy_data_[0], kFrameLength, track_number,
63 0, false));
64 EXPECT_TRUE(segment_.Finalize());
65 }
66
AddVideoTrack()67 void AddVideoTrack() {
68 const int vid_track = static_cast<int>(
69 segment_.AddVideoTrack(kWidth, kHeight, kVideoTrackNumber));
70 ASSERT_EQ(kVideoTrackNumber, vid_track);
71 VideoTrack* const video =
72 dynamic_cast<VideoTrack*>(segment_.GetTrackByNumber(vid_track));
73 ASSERT_TRUE(video != NULL);
74 video->set_uid(kVideoTrackNumber);
75 }
76
AddAudioTrack()77 void AddAudioTrack() {
78 const int aud_track = static_cast<int>(
79 segment_.AddAudioTrack(kSampleRate, kChannels, kAudioTrackNumber));
80 ASSERT_EQ(kAudioTrackNumber, aud_track);
81 AudioTrack* const audio =
82 dynamic_cast<AudioTrack*>(segment_.GetTrackByNumber(aud_track));
83 ASSERT_TRUE(audio != NULL);
84 audio->set_uid(kAudioTrackNumber);
85 audio->set_codec_id(kOpusCodecId);
86 }
87
CloseWriter()88 void CloseWriter() {
89 if (is_writer_open_)
90 writer_->Close();
91 is_writer_open_ = false;
92 }
93
SegmentInit(bool output_cues,bool accurate_cluster_duration,bool fixed_size_cluster_timecode)94 bool SegmentInit(bool output_cues, bool accurate_cluster_duration,
95 bool fixed_size_cluster_timecode) {
96 if (!segment_.Init(writer_.get()))
97 return false;
98 SegmentInfo* const info = segment_.GetSegmentInfo();
99 info->set_writing_app(kAppString);
100 info->set_muxing_app(kAppString);
101 segment_.OutputCues(output_cues);
102 segment_.AccurateClusterDuration(accurate_cluster_duration);
103 segment_.UseFixedSizeClusterTimecode(fixed_size_cluster_timecode);
104 return true;
105 }
106
107 protected:
TearDown()108 virtual void TearDown() {
109 remove(filename_.c_str());
110 testing::Test::TearDown();
111 }
112
113 std::unique_ptr<MkvWriter> writer_;
114 bool is_writer_open_ = false;
115 Segment segment_;
116 std::string filename_;
117 libwebm::FilePtr temp_file_;
118 std::uint8_t dummy_data_[kFrameLength];
119 };
120
TEST_F(MuxerTest,SegmentInfo)121 TEST_F(MuxerTest, SegmentInfo) {
122 EXPECT_TRUE(SegmentInit(false, false, false));
123 SegmentInfo* const info = segment_.GetSegmentInfo();
124 info->set_timecode_scale(kTimeCodeScale);
125 info->set_duration(2.345);
126 EXPECT_STREQ(kAppString, info->muxing_app());
127 EXPECT_STREQ(kAppString, info->writing_app());
128 EXPECT_EQ(static_cast<uint64_t>(kTimeCodeScale), info->timecode_scale());
129 EXPECT_DOUBLE_EQ(2.345, info->duration());
130 AddVideoTrack();
131
132 AddDummyFrameAndFinalize(kVideoTrackNumber);
133 CloseWriter();
134
135 EXPECT_TRUE(CompareFiles(GetTestFilePath("segment_info.webm"), filename_));
136 }
137
TEST_F(MuxerTest,AddTracks)138 TEST_F(MuxerTest, AddTracks) {
139 EXPECT_TRUE(SegmentInit(false, false, false));
140
141 // Add a Video Track
142 AddVideoTrack();
143 VideoTrack* const video =
144 dynamic_cast<VideoTrack*>(segment_.GetTrackByNumber(kVideoTrackNumber));
145 ASSERT_TRUE(video != NULL);
146 EXPECT_EQ(static_cast<uint64_t>(kWidth), video->width());
147 EXPECT_EQ(static_cast<uint64_t>(kHeight), video->height());
148 video->set_name(kTrackName);
149 video->set_display_width(kWidth - 10);
150 video->set_display_height(kHeight - 10);
151 video->set_frame_rate(0.5);
152 EXPECT_STREQ(kTrackName, video->name());
153 const uint64_t kDisplayWidth = kWidth - 10;
154 EXPECT_EQ(kDisplayWidth, video->display_width());
155 const uint64_t kDisplayHeight = kHeight - 10;
156 EXPECT_EQ(kDisplayHeight, video->display_height());
157 EXPECT_DOUBLE_EQ(0.5, video->frame_rate());
158 EXPECT_EQ(static_cast<uint64_t>(kVideoTrackNumber), video->uid());
159
160 // Add an Audio Track
161 const int aud_track = static_cast<int>(
162 segment_.AddAudioTrack(kSampleRate, kChannels, kAudioTrackNumber));
163 EXPECT_EQ(kAudioTrackNumber, aud_track);
164 AudioTrack* const audio =
165 dynamic_cast<AudioTrack*>(segment_.GetTrackByNumber(aud_track));
166 EXPECT_EQ(kSampleRate, audio->sample_rate());
167 EXPECT_EQ(static_cast<uint64_t>(kChannels), audio->channels());
168 ASSERT_TRUE(audio != NULL);
169 audio->set_name(kTrackName);
170 audio->set_bit_depth(kBitDepth);
171 audio->set_uid(kAudioTrackNumber);
172 EXPECT_STREQ(kTrackName, audio->name());
173 EXPECT_EQ(static_cast<uint64_t>(kBitDepth), audio->bit_depth());
174 EXPECT_EQ(static_cast<uint64_t>(kAudioTrackNumber), audio->uid());
175
176 AddDummyFrameAndFinalize(kVideoTrackNumber);
177 CloseWriter();
178
179 EXPECT_TRUE(CompareFiles(GetTestFilePath("tracks.webm"), filename_));
180 }
181
TEST_F(MuxerTest,AddChapters)182 TEST_F(MuxerTest, AddChapters) {
183 EXPECT_TRUE(SegmentInit(false, false, false));
184 AddVideoTrack();
185
186 // Add a Chapter
187 Chapter* chapter = segment_.AddChapter();
188 EXPECT_TRUE(chapter->set_id("unit_test"));
189 chapter->set_time(segment_, 0, 1000000000);
190 EXPECT_TRUE(chapter->add_string("unit_test", "english", "us"));
191 chapter->set_uid(1);
192
193 AddDummyFrameAndFinalize(kVideoTrackNumber);
194 CloseWriter();
195
196 EXPECT_TRUE(CompareFiles(GetTestFilePath("chapters.webm"), filename_));
197 }
198
TEST_F(MuxerTest,SimpleBlock)199 TEST_F(MuxerTest, SimpleBlock) {
200 EXPECT_TRUE(SegmentInit(false, false, false));
201 AddVideoTrack();
202
203 // Valid Frame
204 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, 0,
205 false));
206
207 // Valid Frame
208 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
209 2000000, false));
210
211 // Invalid Frame - Non monotonically increasing timestamp
212 EXPECT_FALSE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
213 1, false));
214
215 // Invalid Frame - Null pointer
216 EXPECT_FALSE(segment_.AddFrame(NULL, 0, kVideoTrackNumber, 8000000, false));
217
218 // Invalid Frame - Invalid track number
219 EXPECT_FALSE(segment_.AddFrame(NULL, 0, kInvalidTrackNumber, 8000000, false));
220
221 segment_.Finalize();
222 CloseWriter();
223
224 EXPECT_TRUE(CompareFiles(GetTestFilePath("simple_block.webm"), filename_));
225 }
226
TEST_F(MuxerTest,SimpleBlockWithAddGenericFrame)227 TEST_F(MuxerTest, SimpleBlockWithAddGenericFrame) {
228 EXPECT_TRUE(SegmentInit(false, false, false));
229 AddVideoTrack();
230
231 Frame frame;
232 frame.Init(dummy_data_, kFrameLength);
233 frame.set_track_number(kVideoTrackNumber);
234 frame.set_is_key(false);
235
236 // Valid Frame
237 frame.set_timestamp(0);
238 EXPECT_TRUE(segment_.AddGenericFrame(&frame));
239
240 // Valid Frame
241 frame.set_timestamp(2000000);
242 EXPECT_TRUE(segment_.AddGenericFrame(&frame));
243
244 // Invalid Frame - Non monotonically increasing timestamp
245 frame.set_timestamp(1);
246 EXPECT_FALSE(segment_.AddGenericFrame(&frame));
247
248 // Invalid Frame - Invalid track number
249 frame.set_track_number(kInvalidTrackNumber);
250 frame.set_timestamp(8000000);
251 EXPECT_FALSE(segment_.AddGenericFrame(&frame));
252
253 segment_.Finalize();
254 CloseWriter();
255
256 EXPECT_TRUE(CompareFiles(GetTestFilePath("simple_block.webm"), filename_));
257 }
258
TEST_F(MuxerTest,MetadataBlock)259 TEST_F(MuxerTest, MetadataBlock) {
260 EXPECT_TRUE(SegmentInit(false, false, false));
261 Track* const track = segment_.AddTrack(kMetadataTrackNumber);
262 track->set_uid(kMetadataTrackNumber);
263 track->set_type(kMetadataTrackType);
264 track->set_codec_id(kMetadataCodecId);
265
266 // Valid Frame
267 EXPECT_TRUE(segment_.AddMetadata(dummy_data_, kFrameLength,
268 kMetadataTrackNumber, 0, 2000000));
269
270 // Valid Frame
271 EXPECT_TRUE(segment_.AddMetadata(dummy_data_, kFrameLength,
272 kMetadataTrackNumber, 2000000, 6000000));
273
274 // Invalid Frame - Non monotonically increasing timestamp
275 EXPECT_FALSE(segment_.AddMetadata(dummy_data_, kFrameLength,
276 kMetadataTrackNumber, 1, 2000000));
277
278 // Invalid Frame - Null pointer
279 EXPECT_FALSE(segment_.AddMetadata(NULL, 0, kMetadataTrackNumber, 0, 8000000));
280
281 // Invalid Frame - Invalid track number
282 EXPECT_FALSE(segment_.AddMetadata(NULL, 0, kInvalidTrackNumber, 0, 8000000));
283
284 segment_.Finalize();
285 CloseWriter();
286
287 EXPECT_TRUE(CompareFiles(GetTestFilePath("metadata_block.webm"), filename_));
288 }
289
TEST_F(MuxerTest,TrackType)290 TEST_F(MuxerTest, TrackType) {
291 EXPECT_TRUE(SegmentInit(false, false, false));
292 Track* const track = segment_.AddTrack(kMetadataTrackNumber);
293 track->set_uid(kMetadataTrackNumber);
294 track->set_codec_id(kMetadataCodecId);
295
296 // Invalid Frame - Incomplete track information (Track Type not set).
297 EXPECT_FALSE(segment_.AddMetadata(dummy_data_, kFrameLength,
298 kMetadataTrackNumber, 0, 2000000));
299
300 track->set_type(kMetadataTrackType);
301
302 // Valid Frame
303 EXPECT_TRUE(segment_.AddMetadata(dummy_data_, kFrameLength,
304 kMetadataTrackNumber, 0, 2000000));
305
306 segment_.Finalize();
307 CloseWriter();
308 }
309
TEST_F(MuxerTest,BlockWithAdditional)310 TEST_F(MuxerTest, BlockWithAdditional) {
311 EXPECT_TRUE(SegmentInit(false, false, false));
312 AddVideoTrack();
313
314 // Valid Frame
315 EXPECT_TRUE(segment_.AddFrameWithAdditional(dummy_data_, kFrameLength,
316 dummy_data_, kFrameLength, 1,
317 kVideoTrackNumber, 0, true));
318
319 // Valid Frame
320 EXPECT_TRUE(segment_.AddFrameWithAdditional(
321 dummy_data_, kFrameLength, dummy_data_, kFrameLength, 1,
322 kVideoTrackNumber, 2000000, false));
323
324 // Invalid Frame - Non monotonically increasing timestamp
325 EXPECT_FALSE(segment_.AddFrameWithAdditional(dummy_data_, kFrameLength,
326 dummy_data_, kFrameLength, 1,
327 kVideoTrackNumber, 1, false));
328
329 // Invalid Frame - Null frame pointer
330 EXPECT_FALSE(
331 segment_.AddFrameWithAdditional(NULL, 0, dummy_data_, kFrameLength, 1,
332 kVideoTrackNumber, 3000000, false));
333
334 // Invalid Frame - Null additional pointer
335 EXPECT_FALSE(segment_.AddFrameWithAdditional(dummy_data_, kFrameLength, NULL,
336 0, 1, kVideoTrackNumber, 4000000,
337 false));
338
339 // Invalid Frame - Invalid track number
340 EXPECT_FALSE(segment_.AddFrameWithAdditional(
341 dummy_data_, kFrameLength, dummy_data_, kFrameLength, 1,
342 kInvalidTrackNumber, 8000000, false));
343
344 segment_.Finalize();
345 CloseWriter();
346
347 EXPECT_TRUE(
348 CompareFiles(GetTestFilePath("block_with_additional.webm"), filename_));
349 }
350
TEST_F(MuxerTest,BlockAdditionalWithAddGenericFrame)351 TEST_F(MuxerTest, BlockAdditionalWithAddGenericFrame) {
352 EXPECT_TRUE(SegmentInit(false, false, false));
353 AddVideoTrack();
354
355 Frame frame;
356 frame.Init(dummy_data_, kFrameLength);
357 frame.AddAdditionalData(dummy_data_, kFrameLength, 1);
358 frame.set_track_number(kVideoTrackNumber);
359 frame.set_is_key(true);
360
361 // Valid Frame
362 frame.set_timestamp(0);
363 EXPECT_TRUE(segment_.AddGenericFrame(&frame));
364
365 // Valid Frame
366 frame.set_timestamp(2000000);
367 frame.set_is_key(false);
368 EXPECT_TRUE(segment_.AddGenericFrame(&frame));
369
370 // Invalid Frame - Non monotonically increasing timestamp
371 frame.set_timestamp(1);
372 EXPECT_FALSE(segment_.AddGenericFrame(&frame));
373
374 // Invalid Frame - Invalid track number
375 frame.set_track_number(kInvalidTrackNumber);
376 frame.set_timestamp(4000000);
377 EXPECT_FALSE(segment_.AddGenericFrame(&frame));
378
379 segment_.Finalize();
380 CloseWriter();
381
382 EXPECT_TRUE(
383 CompareFiles(GetTestFilePath("block_with_additional.webm"), filename_));
384 }
385
TEST_F(MuxerTest,SegmentDurationComputation)386 TEST_F(MuxerTest, SegmentDurationComputation) {
387 EXPECT_TRUE(SegmentInit(false, false, false));
388 AddVideoTrack();
389
390 Frame frame;
391 frame.Init(dummy_data_, kFrameLength);
392 frame.set_track_number(kVideoTrackNumber);
393 frame.set_timestamp(0);
394 frame.set_is_key(false);
395 EXPECT_TRUE(segment_.AddGenericFrame(&frame));
396 frame.set_timestamp(2000000);
397 EXPECT_TRUE(segment_.AddGenericFrame(&frame));
398 frame.set_timestamp(4000000);
399 EXPECT_TRUE(segment_.AddGenericFrame(&frame));
400 frame.set_timestamp(6000000);
401 frame.set_duration(2000000);
402 EXPECT_TRUE(segment_.AddGenericFrame(&frame));
403 segment_.Finalize();
404
405 // SegmentInfo's duration is in timecode scale
406 EXPECT_EQ(8, segment_.GetSegmentInfo()->duration());
407
408 CloseWriter();
409
410 EXPECT_TRUE(
411 CompareFiles(GetTestFilePath("segment_duration.webm"), filename_));
412 }
413
TEST_F(MuxerTest,SetSegmentDuration)414 TEST_F(MuxerTest, SetSegmentDuration) {
415 EXPECT_TRUE(SegmentInit(false, false, false));
416 AddVideoTrack();
417 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, 0,
418 false));
419 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
420 2000000, false));
421
422 segment_.set_duration(10500.0);
423 segment_.Finalize();
424 CloseWriter();
425
426 EXPECT_TRUE(
427 CompareFiles(GetTestFilePath("set_segment_duration.webm"), filename_));
428 }
429
TEST_F(MuxerTest,ForceNewCluster)430 TEST_F(MuxerTest, ForceNewCluster) {
431 EXPECT_TRUE(SegmentInit(false, false, false));
432 AddVideoTrack();
433
434 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, 0,
435 false));
436 segment_.ForceNewClusterOnNextFrame();
437 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
438 2000000, false));
439 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
440 4000000, false));
441 segment_.ForceNewClusterOnNextFrame();
442 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
443 6000000, false));
444 segment_.Finalize();
445
446 CloseWriter();
447
448 EXPECT_TRUE(
449 CompareFiles(GetTestFilePath("force_new_cluster.webm"), filename_));
450 }
451
TEST_F(MuxerTest,OutputCues)452 TEST_F(MuxerTest, OutputCues) {
453 EXPECT_TRUE(SegmentInit(true, false, false));
454 AddVideoTrack();
455
456 EXPECT_TRUE(
457 segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, 0, true));
458 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
459 2000000, false));
460 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
461 4000000, false));
462 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
463 6000000, true));
464 EXPECT_TRUE(segment_.AddCuePoint(4000000, kVideoTrackNumber));
465 segment_.Finalize();
466
467 CloseWriter();
468
469 EXPECT_TRUE(CompareFiles(GetTestFilePath("output_cues.webm"), filename_));
470 }
471
TEST_F(MuxerTest,CuesBeforeClusters)472 TEST_F(MuxerTest, CuesBeforeClusters) {
473 EXPECT_TRUE(SegmentInit(true, false, false));
474 AddVideoTrack();
475
476 EXPECT_TRUE(
477 segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, 0, true));
478 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
479 2000000, false));
480 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
481 4000000, false));
482 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
483 6000000, true));
484 segment_.Finalize();
485 CloseWriter();
486 #ifdef _MSC_VER
487 // Close the output file: the MS run time won't allow mkvparser::MkvReader
488 // to open a file for reading when it's still open for writing.
489 temp_file_.reset();
490 #endif
491 mkvparser::MkvReader reader;
492 ASSERT_EQ(0, reader.Open(filename_.c_str()));
493 MkvWriter cues_writer;
494 std::string cues_filename = libwebm::GetTempFileName();
495 ASSERT_GT(cues_filename.length(), 0u);
496 cues_writer.Open(cues_filename.c_str());
497 EXPECT_TRUE(segment_.CopyAndMoveCuesBeforeClusters(&reader, &cues_writer));
498 reader.Close();
499 cues_writer.Close();
500
501 EXPECT_TRUE(CompareFiles(GetTestFilePath("cues_before_clusters.webm"),
502 cues_filename));
503 MkvParser parser;
504 ASSERT_TRUE(ParseMkvFileReleaseParser(cues_filename, &parser));
505 int64_t cues_offset = 0;
506 ASSERT_TRUE(HasCuePoints(parser.segment, &cues_offset));
507 ASSERT_GT(cues_offset, 0);
508 ASSERT_TRUE(ValidateCues(parser.segment, parser.reader));
509 remove(cues_filename.c_str());
510 }
511
TEST_F(MuxerTest,MaxClusterSize)512 TEST_F(MuxerTest, MaxClusterSize) {
513 EXPECT_TRUE(SegmentInit(false, false, false));
514 AddVideoTrack();
515 const uint64_t kMaxClusterSize = 20;
516 segment_.set_max_cluster_size(kMaxClusterSize);
517 EXPECT_EQ(kMaxClusterSize, segment_.max_cluster_size());
518 EXPECT_TRUE(segment_.AddFrame(dummy_data_, 1, kVideoTrackNumber, 0, false));
519 EXPECT_TRUE(
520 segment_.AddFrame(dummy_data_, 1, kVideoTrackNumber, 2000000, false));
521 EXPECT_TRUE(
522 segment_.AddFrame(dummy_data_, 1, kVideoTrackNumber, 4000000, false));
523 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
524 6000000, false));
525 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
526 8000000, false));
527 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
528 9000000, false));
529 segment_.Finalize();
530
531 CloseWriter();
532
533 EXPECT_TRUE(
534 CompareFiles(GetTestFilePath("max_cluster_size.webm"), filename_));
535 }
536
TEST_F(MuxerTest,MaxClusterDuration)537 TEST_F(MuxerTest, MaxClusterDuration) {
538 EXPECT_TRUE(SegmentInit(false, false, false));
539 AddVideoTrack();
540 const uint64_t kMaxClusterDuration = 4000000;
541 segment_.set_max_cluster_duration(kMaxClusterDuration);
542
543 EXPECT_EQ(kMaxClusterDuration, segment_.max_cluster_duration());
544 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, 0,
545 false));
546 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
547 2000000, false));
548 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
549 4000000, false));
550 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
551 6000000, false));
552 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
553 8000000, false));
554 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
555 9000000, false));
556 segment_.Finalize();
557
558 CloseWriter();
559
560 EXPECT_TRUE(
561 CompareFiles(GetTestFilePath("max_cluster_duration.webm"), filename_));
562 }
563
TEST_F(MuxerTest,SetCuesTrackNumber)564 TEST_F(MuxerTest, SetCuesTrackNumber) {
565 const uint64_t kTrackNumber = 10;
566 EXPECT_TRUE(SegmentInit(true, false, false));
567 const uint64_t vid_track =
568 segment_.AddVideoTrack(kWidth, kHeight, kTrackNumber);
569 EXPECT_EQ(kTrackNumber, vid_track);
570 segment_.GetTrackByNumber(vid_track)->set_uid(kVideoTrackNumber);
571 EXPECT_TRUE(segment_.CuesTrack(vid_track));
572
573 EXPECT_EQ(vid_track, segment_.cues_track());
574 EXPECT_TRUE(
575 segment_.AddFrame(dummy_data_, kFrameLength, kTrackNumber, 0, true));
576 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kTrackNumber,
577 2000000, false));
578 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kTrackNumber,
579 4000000, false));
580 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kTrackNumber,
581 6000000, true));
582 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kTrackNumber,
583 8000000, false));
584 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kTrackNumber,
585 9000000, false));
586 segment_.Finalize();
587
588 CloseWriter();
589
590 EXPECT_TRUE(
591 CompareFiles(GetTestFilePath("set_cues_track_number.webm"), filename_));
592 }
593
TEST_F(MuxerTest,BlockWithDiscardPadding)594 TEST_F(MuxerTest, BlockWithDiscardPadding) {
595 EXPECT_TRUE(SegmentInit(false, false, false));
596 AddAudioTrack();
597
598 int timecode = 1000;
599 // 12810000 == 0xc37710, should be 0-extended to avoid changing the sign.
600 // The next two should be written as 1 byte.
601 std::array<int, 3> values = {{12810000, 127, -128}};
602 for (const std::int64_t discard_padding : values) {
603 EXPECT_TRUE(segment_.AddFrameWithDiscardPadding(
604 dummy_data_, kFrameLength, discard_padding, kAudioTrackNumber, timecode,
605 true))
606 << "discard_padding: " << discard_padding;
607 timecode += 1000;
608 }
609
610 segment_.Finalize();
611
612 CloseWriter();
613
614 EXPECT_TRUE(CompareFiles(GetTestFilePath("discard_padding.webm"), filename_));
615 }
616
TEST_F(MuxerTest,AccurateClusterDuration)617 TEST_F(MuxerTest, AccurateClusterDuration) {
618 EXPECT_TRUE(SegmentInit(false, true, false));
619 AddVideoTrack();
620
621 Frame frame;
622 frame.Init(dummy_data_, kFrameLength);
623 frame.set_track_number(kVideoTrackNumber);
624 frame.set_timestamp(0);
625 frame.set_is_key(true);
626 EXPECT_TRUE(segment_.AddGenericFrame(&frame));
627 segment_.ForceNewClusterOnNextFrame();
628 frame.set_timestamp(2000000);
629 frame.set_is_key(false);
630 EXPECT_TRUE(segment_.AddGenericFrame(&frame));
631 frame.set_timestamp(4000000);
632 EXPECT_TRUE(segment_.AddGenericFrame(&frame));
633 segment_.ForceNewClusterOnNextFrame();
634 frame.set_timestamp(6000000);
635 EXPECT_TRUE(segment_.AddGenericFrame(&frame));
636 segment_.Finalize();
637
638 CloseWriter();
639
640 EXPECT_TRUE(CompareFiles(GetTestFilePath("accurate_cluster_duration.webm"),
641 filename_));
642 }
643
644 // Tests AccurateClusterDuration flag with the duration of the very last block
645 // of the file set explicitly.
TEST_F(MuxerTest,AccurateClusterDurationExplicitLastFrameDuration)646 TEST_F(MuxerTest, AccurateClusterDurationExplicitLastFrameDuration) {
647 EXPECT_TRUE(SegmentInit(false, true, false));
648 AddVideoTrack();
649
650 Frame frame;
651 frame.Init(dummy_data_, kFrameLength);
652 frame.set_track_number(kVideoTrackNumber);
653 frame.set_timestamp(0);
654 frame.set_is_key(true);
655 EXPECT_TRUE(segment_.AddGenericFrame(&frame));
656 segment_.ForceNewClusterOnNextFrame();
657 frame.set_timestamp(2000000);
658 frame.set_is_key(false);
659 EXPECT_TRUE(segment_.AddGenericFrame(&frame));
660 frame.set_timestamp(4000000);
661 EXPECT_TRUE(segment_.AddGenericFrame(&frame));
662 segment_.ForceNewClusterOnNextFrame();
663 frame.set_timestamp(6000000);
664 frame.set_duration(2000000);
665 EXPECT_TRUE(segment_.AddGenericFrame(&frame));
666 segment_.Finalize();
667
668 // SegmentInfo's duration is in timecode scale
669 EXPECT_EQ(8, segment_.GetSegmentInfo()->duration());
670
671 CloseWriter();
672
673 EXPECT_TRUE(CompareFiles(
674 GetTestFilePath("accurate_cluster_duration_last_frame.webm"), filename_));
675 }
676
TEST_F(MuxerTest,AccurateClusterDurationTwoTracks)677 TEST_F(MuxerTest, AccurateClusterDurationTwoTracks) {
678 EXPECT_TRUE(SegmentInit(false, true, false));
679 AddVideoTrack();
680 AddAudioTrack();
681
682 Frame video_frame;
683 video_frame.Init(dummy_data_, kFrameLength);
684 video_frame.set_track_number(kVideoTrackNumber);
685 Frame audio_frame;
686 audio_frame.Init(dummy_data_, kFrameLength);
687 audio_frame.set_track_number(kAudioTrackNumber);
688 std::array<std::uint64_t, 2> cluster_timestamps = {{0, 40000000}};
689 for (const std::uint64_t cluster_timestamp : cluster_timestamps) {
690 // Add video and audio frames with timestamp 0.
691 video_frame.set_timestamp(cluster_timestamp);
692 video_frame.set_is_key(true);
693 EXPECT_TRUE(segment_.AddGenericFrame(&video_frame));
694 audio_frame.set_timestamp(cluster_timestamp);
695 audio_frame.set_is_key(true);
696 EXPECT_TRUE(segment_.AddGenericFrame(&audio_frame));
697
698 // Add 3 consecutive audio frames.
699 std::array<std::uint64_t, 3> audio_timestamps = {
700 {10000000, 20000000, 30000000}};
701 for (const std::uint64_t audio_timestamp : audio_timestamps) {
702 audio_frame.set_timestamp(cluster_timestamp + audio_timestamp);
703 // Explicitly set duration for the very last audio frame.
704 if (cluster_timestamp == 40000000 && audio_timestamp == 30000000) {
705 audio_frame.set_duration(10000000);
706 }
707 EXPECT_TRUE(segment_.AddGenericFrame(&audio_frame));
708 }
709
710 // Add a video frame with timestamp 33ms.
711 video_frame.set_is_key(false);
712 // Explicitly set duration for the very last video frame.
713 if (cluster_timestamp == 40000000) {
714 video_frame.set_duration(7000000);
715 }
716 video_frame.set_timestamp(cluster_timestamp + 33000000);
717 EXPECT_TRUE(segment_.AddGenericFrame(&video_frame));
718 segment_.ForceNewClusterOnNextFrame();
719 }
720 segment_.Finalize();
721
722 // SegmentInfo's duration is in timecode scale
723 EXPECT_EQ(80, segment_.GetSegmentInfo()->duration());
724
725 CloseWriter();
726
727 EXPECT_TRUE(CompareFiles(
728 GetTestFilePath("accurate_cluster_duration_two_tracks.webm"), filename_));
729 }
730
TEST_F(MuxerTest,AccurateClusterDurationWithoutFinalizingCluster)731 TEST_F(MuxerTest, AccurateClusterDurationWithoutFinalizingCluster) {
732 EXPECT_TRUE(SegmentInit(false, true, false));
733 AddVideoTrack();
734
735 // Add a couple of frames and then bail out without finalizing the Segment
736 // (and thereby not finalizing the Cluster). The expectation here is that
737 // there shouldn't be any leaks. The test will fail under valgrind if there's
738 // a leak.
739 Frame video_frame;
740 video_frame.Init(dummy_data_, kFrameLength);
741 video_frame.set_track_number(kVideoTrackNumber);
742 video_frame.set_timestamp(0);
743 video_frame.set_is_key(true);
744 EXPECT_TRUE(segment_.AddGenericFrame(&video_frame));
745 video_frame.set_timestamp(33000000);
746 EXPECT_TRUE(segment_.AddGenericFrame(&video_frame));
747
748 CloseWriter();
749 }
750
TEST_F(MuxerTest,UseFixedSizeClusterTimecode)751 TEST_F(MuxerTest, UseFixedSizeClusterTimecode) {
752 EXPECT_TRUE(SegmentInit(false, false, true));
753 AddVideoTrack();
754
755 Frame frame;
756 frame.Init(dummy_data_, kFrameLength);
757 frame.set_track_number(kVideoTrackNumber);
758 frame.set_timestamp(0);
759 frame.set_is_key(true);
760 EXPECT_TRUE(segment_.AddGenericFrame(&frame));
761 segment_.ForceNewClusterOnNextFrame();
762 frame.set_timestamp(2000000);
763 EXPECT_TRUE(segment_.AddGenericFrame(&frame));
764 segment_.ForceNewClusterOnNextFrame();
765 frame.set_timestamp(4000000);
766 EXPECT_TRUE(segment_.AddGenericFrame(&frame));
767 segment_.Finalize();
768
769 CloseWriter();
770
771 EXPECT_TRUE(CompareFiles(GetTestFilePath("fixed_size_cluster_timecode.webm"),
772 filename_));
773 }
774
TEST_F(MuxerTest,DocTypeWebm)775 TEST_F(MuxerTest, DocTypeWebm) {
776 EXPECT_TRUE(SegmentInit(false, false, false));
777 AddVideoTrack();
778 Track* const vid_track = segment_.GetTrackByNumber(kVideoTrackNumber);
779 vid_track->set_codec_id(kVP9CodecId);
780 AddDummyFrameAndFinalize(kVideoTrackNumber);
781 EXPECT_TRUE(CompareFiles(GetTestFilePath("webm_doctype.webm"), filename_));
782 }
783
TEST_F(MuxerTest,DocTypeMatroska)784 TEST_F(MuxerTest, DocTypeMatroska) {
785 EXPECT_TRUE(SegmentInit(false, false, false));
786 AddVideoTrack();
787 Track* const vid_track = segment_.GetTrackByNumber(kVideoTrackNumber);
788 vid_track->set_codec_id("V_SOMETHING_NOT_IN_WEBM");
789 AddDummyFrameAndFinalize(kVideoTrackNumber);
790 EXPECT_TRUE(CompareFiles(GetTestFilePath("matroska_doctype.mkv"), filename_));
791 }
792
TEST_F(MuxerTest,Colour)793 TEST_F(MuxerTest, Colour) {
794 EXPECT_TRUE(SegmentInit(false, false, false));
795 AddVideoTrack();
796
797 mkvmuxer::PrimaryChromaticity muxer_pc(.1, .2);
798 mkvmuxer::MasteringMetadata muxer_mm;
799 muxer_mm.set_luminance_min(30.0);
800 muxer_mm.set_luminance_max(40.0);
801 ASSERT_TRUE(
802 muxer_mm.SetChromaticity(&muxer_pc, &muxer_pc, &muxer_pc, &muxer_pc));
803
804 mkvmuxer::Colour muxer_colour;
805 muxer_colour.set_matrix_coefficients(mkvmuxer::Colour::kGbr);
806 muxer_colour.set_bits_per_channel(1);
807 muxer_colour.set_chroma_subsampling_horz(2);
808 muxer_colour.set_chroma_subsampling_vert(3);
809 muxer_colour.set_cb_subsampling_horz(4);
810 muxer_colour.set_cb_subsampling_vert(5);
811 muxer_colour.set_chroma_siting_horz(mkvmuxer::Colour::kLeftCollocated);
812 muxer_colour.set_chroma_siting_vert(mkvmuxer::Colour::kTopCollocated);
813 muxer_colour.set_range(mkvmuxer::Colour::kFullRange);
814 muxer_colour.set_transfer_characteristics(mkvmuxer::Colour::kLog);
815 muxer_colour.set_primaries(mkvmuxer::Colour::kSmpteSt4281P);
816 muxer_colour.set_max_cll(11);
817 muxer_colour.set_max_fall(12);
818 ASSERT_TRUE(muxer_colour.SetMasteringMetadata(muxer_mm));
819
820 VideoTrack* const video_track =
821 dynamic_cast<VideoTrack*>(segment_.GetTrackByNumber(kVideoTrackNumber));
822 ASSERT_TRUE(video_track != nullptr);
823 ASSERT_TRUE(video_track->SetColour(muxer_colour));
824 ASSERT_NO_FATAL_FAILURE(AddDummyFrameAndFinalize(kVideoTrackNumber));
825
826 MkvParser parser;
827 ASSERT_TRUE(ParseMkvFileReleaseParser(filename_, &parser));
828
829 const mkvparser::VideoTrack* const parser_track =
830 static_cast<const mkvparser::VideoTrack*>(
831 parser.segment->GetTracks()->GetTrackByIndex(0));
832 const mkvparser::Colour* parser_colour = parser_track->GetColour();
833 ASSERT_TRUE(parser_colour != nullptr);
834 EXPECT_EQ(static_cast<long long>(muxer_colour.matrix_coefficients()),
835 parser_colour->matrix_coefficients);
836 EXPECT_EQ(static_cast<long long>(muxer_colour.bits_per_channel()),
837 parser_colour->bits_per_channel);
838 EXPECT_EQ(static_cast<long long>(muxer_colour.chroma_subsampling_horz()),
839 parser_colour->chroma_subsampling_horz);
840 EXPECT_EQ(static_cast<long long>(muxer_colour.chroma_subsampling_vert()),
841 parser_colour->chroma_subsampling_vert);
842 EXPECT_EQ(static_cast<long long>(muxer_colour.cb_subsampling_horz()),
843 parser_colour->cb_subsampling_horz);
844 EXPECT_EQ(static_cast<long long>(muxer_colour.cb_subsampling_vert()),
845 parser_colour->cb_subsampling_vert);
846 EXPECT_EQ(static_cast<long long>(muxer_colour.chroma_siting_horz()),
847 parser_colour->chroma_siting_horz);
848 EXPECT_EQ(static_cast<long long>(muxer_colour.chroma_siting_vert()),
849 parser_colour->chroma_siting_vert);
850 EXPECT_EQ(static_cast<long long>(muxer_colour.range()), parser_colour->range);
851 EXPECT_EQ(static_cast<long long>(muxer_colour.transfer_characteristics()),
852 parser_colour->transfer_characteristics);
853 EXPECT_EQ(static_cast<long long>(muxer_colour.primaries()),
854 parser_colour->primaries);
855 EXPECT_EQ(static_cast<long long>(muxer_colour.max_cll()),
856 parser_colour->max_cll);
857 EXPECT_EQ(static_cast<long long>(muxer_colour.max_fall()),
858 parser_colour->max_fall);
859
860 const mkvparser::MasteringMetadata* const parser_mm =
861 parser_colour->mastering_metadata;
862 ASSERT_TRUE(parser_mm != nullptr);
863 EXPECT_FLOAT_EQ(muxer_mm.luminance_min(), parser_mm->luminance_min);
864 EXPECT_FLOAT_EQ(muxer_mm.luminance_max(), parser_mm->luminance_max);
865 EXPECT_FLOAT_EQ(muxer_mm.r()->x(), parser_mm->r->x);
866 EXPECT_FLOAT_EQ(muxer_mm.r()->y(), parser_mm->r->y);
867 EXPECT_FLOAT_EQ(muxer_mm.g()->x(), parser_mm->g->x);
868 EXPECT_FLOAT_EQ(muxer_mm.g()->y(), parser_mm->g->y);
869 EXPECT_FLOAT_EQ(muxer_mm.b()->x(), parser_mm->b->x);
870 EXPECT_FLOAT_EQ(muxer_mm.b()->y(), parser_mm->b->y);
871 EXPECT_FLOAT_EQ(muxer_mm.white_point()->x(), parser_mm->white_point->x);
872 EXPECT_FLOAT_EQ(muxer_mm.white_point()->y(), parser_mm->white_point->y);
873 EXPECT_TRUE(CompareFiles(GetTestFilePath("colour.webm"), filename_));
874 }
875
TEST_F(MuxerTest,ColourPartial)876 TEST_F(MuxerTest, ColourPartial) {
877 EXPECT_TRUE(SegmentInit(false, false, false));
878 AddVideoTrack();
879 mkvmuxer::Colour muxer_colour;
880 muxer_colour.set_matrix_coefficients(
881 mkvmuxer::Colour::kBt2020NonConstantLuminance);
882
883 VideoTrack* const video_track =
884 dynamic_cast<VideoTrack*>(segment_.GetTrackByNumber(kVideoTrackNumber));
885 ASSERT_TRUE(video_track != nullptr);
886 ASSERT_TRUE(video_track->SetColour(muxer_colour));
887 ASSERT_NO_FATAL_FAILURE(AddDummyFrameAndFinalize(kVideoTrackNumber));
888
889 MkvParser parser;
890 ASSERT_TRUE(ParseMkvFileReleaseParser(filename_, &parser));
891
892 const mkvparser::VideoTrack* const parser_track =
893 static_cast<const mkvparser::VideoTrack*>(
894 parser.segment->GetTracks()->GetTrackByIndex(0));
895 const mkvparser::Colour* parser_colour = parser_track->GetColour();
896 EXPECT_EQ(static_cast<long long>(muxer_colour.matrix_coefficients()),
897 parser_colour->matrix_coefficients);
898 }
899
TEST_F(MuxerTest,Projection)900 TEST_F(MuxerTest, Projection) {
901 EXPECT_TRUE(SegmentInit(false, false, false));
902 AddVideoTrack();
903
904 mkvmuxer::Projection muxer_proj;
905 muxer_proj.set_type(mkvmuxer::Projection::kRectangular);
906 muxer_proj.set_pose_yaw(1);
907 muxer_proj.set_pose_pitch(2);
908 muxer_proj.set_pose_roll(3);
909 const uint8_t muxer_proj_private[1] = {4};
910 const uint64_t muxer_proj_private_length = 1;
911 ASSERT_TRUE(muxer_proj.SetProjectionPrivate(&muxer_proj_private[0],
912 muxer_proj_private_length));
913
914 VideoTrack* const video_track =
915 static_cast<VideoTrack*>(segment_.GetTrackByNumber(kVideoTrackNumber));
916 ASSERT_TRUE(video_track != nullptr);
917 ASSERT_TRUE(video_track->SetProjection(muxer_proj));
918 ASSERT_NO_FATAL_FAILURE(AddDummyFrameAndFinalize(kVideoTrackNumber));
919
920 MkvParser parser;
921 ASSERT_TRUE(ParseMkvFileReleaseParser(filename_, &parser));
922
923 const mkvparser::VideoTrack* const parser_track =
924 static_cast<const mkvparser::VideoTrack*>(
925 parser.segment->GetTracks()->GetTrackByIndex(0));
926
927 const mkvparser::Projection* const parser_proj =
928 parser_track->GetProjection();
929 ASSERT_TRUE(parser_proj != nullptr);
930 EXPECT_FLOAT_EQ(muxer_proj.pose_yaw(), parser_proj->pose_yaw);
931 EXPECT_FLOAT_EQ(muxer_proj.pose_pitch(), parser_proj->pose_pitch);
932 EXPECT_FLOAT_EQ(muxer_proj.pose_roll(), parser_proj->pose_roll);
933 ASSERT_TRUE(parser_proj->private_data != nullptr);
934 EXPECT_EQ(static_cast<size_t>(muxer_proj.private_data_length()),
935 parser_proj->private_data_length);
936
937 EXPECT_EQ(muxer_proj.private_data()[0], parser_proj->private_data[0]);
938 typedef mkvparser::Projection::ProjectionType ParserProjType;
939 EXPECT_EQ(static_cast<ParserProjType>(muxer_proj.type()), parser_proj->type);
940 EXPECT_TRUE(CompareFiles(GetTestFilePath("projection.webm"), filename_));
941 }
942
TEST_F(MuxerTest,EstimateDuration)943 TEST_F(MuxerTest, EstimateDuration) {
944 EXPECT_TRUE(SegmentInit(false, false, false));
945 segment_.set_estimate_file_duration(true);
946 AddVideoTrack();
947 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, 0,
948 false));
949 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
950 2000000, false));
951 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
952 4000000, false));
953 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
954 6000000, false));
955 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
956 8000000, false));
957 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
958 9000000, false));
959 segment_.Finalize();
960
961 CloseWriter();
962
963 EXPECT_TRUE(
964 CompareFiles(GetTestFilePath("estimate_duration.webm"), filename_));
965 }
966
TEST_F(MuxerTest,SetPixelWidthPixelHeight)967 TEST_F(MuxerTest, SetPixelWidthPixelHeight) {
968 EXPECT_TRUE(SegmentInit(false, false, false));
969 AddVideoTrack();
970 VideoTrack* const video_track =
971 static_cast<VideoTrack*>(segment_.GetTrackByNumber(kVideoTrackNumber));
972 ASSERT_TRUE(video_track != nullptr);
973 video_track->set_pixel_width(500);
974 video_track->set_pixel_height(650);
975
976 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, 0,
977 false));
978 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
979 2000000, false));
980
981 segment_.Finalize();
982 CloseWriter();
983
984 EXPECT_TRUE(CompareFiles(GetTestFilePath("set_pixelwidth_pixelheight.webm"),
985 filename_));
986 }
987
TEST_F(MuxerTest,LongTagString)988 TEST_F(MuxerTest, LongTagString) {
989 EXPECT_TRUE(SegmentInit(false, false, false));
990 AddVideoTrack();
991 Tag* const tag = segment_.AddTag();
992 // 160 needs two bytes when varint encoded.
993 const std::string dummy_string(160, '0');
994 tag->add_simple_tag("long_tag", dummy_string.c_str());
995
996 EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, 0,
997 false));
998
999 segment_.Finalize();
1000 CloseWriter();
1001
1002 EXPECT_TRUE(CompareFiles(GetTestFilePath("long_tag_string.webm"), filename_));
1003 }
1004
1005 } // namespace test
1006
main(int argc,char * argv[])1007 int main(int argc, char* argv[]) {
1008 ::testing::InitGoogleTest(&argc, argv);
1009 return RUN_ALL_TESTS();
1010 }
1011