libwebm: Googletest integration.

Add basic mux/parse tests and test data.

Change-Id: I3bef014f32ad4898d23bca792fb3fe275fe4e7c9
This commit is contained in:
Tom Finegan 2016-01-11 18:46:55 -08:00
parent 3bec1ba7a1
commit 9299bbb6ed
22 changed files with 1309 additions and 0 deletions

View File

@ -11,6 +11,14 @@ include("${CMAKE_CURRENT_SOURCE_DIR}/build/msvc_runtime.cmake")
set(LIBWEBM_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
# Test configuration flags. Defined here for visibility.
option(ENABLE_TESTS "Enables tests." OFF)
set(GTEST_SRC_DIR "${LIBWEBM_SRC_DIR}/../googletest" CACHE PATH
"Path to Googletest git repository.")
# This directory is where libwebm will build googletest dependencies.
set(GTEST_BUILD_DIR "${CMAKE_BINARY_DIR}/googletest_build")
# Libwebm section.
add_library(webm STATIC
"${LIBWEBM_SRC_DIR}/mkvmuxer.cpp"
@ -65,3 +73,21 @@ add_executable(webm2pes
"${LIBWEBM_SRC_DIR}/webm2pes.h"
"${LIBWEBM_SRC_DIR}/webm2pes_main.cc")
target_link_libraries(webm2pes LINK_PUBLIC webm)
# tests section.
if (ENABLE_TESTS)
add_subdirectory("${GTEST_SRC_DIR}" "${GTEST_BUILD_DIR}")
include_directories("${GTEST_SRC_DIR}/googletest/include")
add_executable(muxer_tests
"${LIBWEBM_SRC_DIR}/testing/muxer_tests.cc"
"${LIBWEBM_SRC_DIR}/testing/test_util.cc"
"${LIBWEBM_SRC_DIR}/testing/test_util.h")
target_link_libraries(muxer_tests LINK_PUBLIC webm gtest)
add_executable(parser_tests
"${LIBWEBM_SRC_DIR}/testing/parser_tests.cc"
"${LIBWEBM_SRC_DIR}/testing/test_util.cc"
"${LIBWEBM_SRC_DIR}/testing/test_util.h")
target_link_libraries(parser_tests LINK_PUBLIC webm gtest)
endif (ENABLE_TESTS)

View File

@ -55,3 +55,28 @@ $ cmake path/to/libwebm -DCMAKE_BUILD_TYPE=relwithdebinfo
And your standard debug build will be produced using:
$ cmake path/to/libwebm -DCMAKE_BUILD_TYPE=debug
Tests
To enable libwebm tests add -DENABLE_TESTS=ON CMake generation command line. For
example:
$ cmake path/to/libwebm -G Xcode -DENABLE_TESTS=ON
Libwebm tests depend on googletest. By default googletest is expected to be a
sibling directory of the Libwebm repository. To change that, update your CMake
command to be similar to the following:
$ cmake path/to/libwebm -G Xcode -DENABLE_TESTS=ON \
-DGTEST_SRC_DIR=/path/to/googletest
The tests rely upon the LIBWEBM_TEST_DATA_PATH environment variable to locate
test input. The following example demonstrates running the muxer tests from the
build directory:
$ LIBWEBM_TEST_DATA_PATH=path/to/libwebm/testing/testdata ./muxer_tests
Note: Libwebm Googletest integration was built with googletest at git revision
ddb8012eb48bc203aa93dcc2b22c1db516302b29.

575
testing/muxer_tests.cc Normal file
View File

@ -0,0 +1,575 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include <array>
#include <cstddef>
#include <initializer_list>
#include <memory>
#include <string>
#include "gtest/gtest.h"
#include "mkvmuxer.hpp"
#include "mkvreader.hpp"
#include "mkvwriter.hpp"
#include "common/libwebm_utils.h"
#include "testing/test_util.h"
using ::mkvmuxer::AudioTrack;
using ::mkvmuxer::Chapter;
using ::mkvmuxer::Frame;
using ::mkvmuxer::MkvWriter;
using ::mkvmuxer::Segment;
using ::mkvmuxer::SegmentInfo;
using ::mkvmuxer::Track;
using ::mkvmuxer::VideoTrack;
namespace libwebm {
namespace test {
// Base class containing boiler plate stuff.
class MuxerTest : public testing::Test {
public:
MuxerTest() {
EXPECT_TRUE(GetTestDataDir().length() > 0);
filename_ = std::tmpnam(nullptr);
temp_file_ = FilePtr(std::fopen(filename_.c_str(), "wb"), FILEDeleter());
EXPECT_TRUE(writer_.Open(filename_.c_str()));
is_writer_open_ = true;
memset(dummy_data_, 0, kFrameLength);
}
~MuxerTest() { CloseWriter(); }
void AddDummyFrameAndFinalize(int track_number) {
EXPECT_TRUE(segment_.AddFrame(&dummy_data_[0], kFrameLength, track_number,
0, false));
EXPECT_TRUE(segment_.Finalize());
}
void AddVideoTrack() {
const int vid_track =
segment_.AddVideoTrack(kWidth, kHeight, kVideoTrackNumber);
EXPECT_EQ(kVideoTrackNumber, vid_track);
VideoTrack* const video =
dynamic_cast<VideoTrack*>(segment_.GetTrackByNumber(vid_track));
ASSERT_TRUE(video != NULL);
video->set_uid(kVideoTrackNumber);
}
void CloseWriter() {
if (is_writer_open_)
writer_.Close();
is_writer_open_ = false;
}
bool SegmentInit(bool output_cues) {
if (!segment_.Init(&writer_))
return false;
SegmentInfo* const info = segment_.GetSegmentInfo();
info->set_writing_app(kAppString);
info->set_muxing_app(kAppString);
segment_.OutputCues(output_cues);
return true;
}
protected:
MkvWriter writer_;
bool is_writer_open_ = false;
Segment segment_;
std::string filename_;
FilePtr temp_file_;
std::uint8_t dummy_data_[kFrameLength];
};
TEST_F(MuxerTest, SegmentInfo) {
EXPECT_TRUE(SegmentInit(false));
SegmentInfo* const info = segment_.GetSegmentInfo();
info->set_timecode_scale(kTimeCodeScale);
info->set_duration(2.345);
EXPECT_STREQ(kAppString, info->muxing_app());
EXPECT_STREQ(kAppString, info->writing_app());
EXPECT_EQ(kTimeCodeScale, info->timecode_scale());
EXPECT_DOUBLE_EQ(2.345, info->duration());
AddVideoTrack();
AddDummyFrameAndFinalize(kVideoTrackNumber);
CloseWriter();
EXPECT_TRUE(CompareFiles(GetTestFilePath("segment_info.webm"), filename_));
}
TEST_F(MuxerTest, AddTracks) {
EXPECT_TRUE(SegmentInit(false));
// Add a Video Track
AddVideoTrack();
VideoTrack* const video =
dynamic_cast<VideoTrack*>(segment_.GetTrackByNumber(kVideoTrackNumber));
ASSERT_TRUE(video != NULL);
EXPECT_EQ(kWidth, video->width());
EXPECT_EQ(kHeight, video->height());
video->set_name("unit_test");
video->set_display_width(kWidth - 10);
video->set_display_height(kHeight - 10);
video->set_frame_rate(0.5);
EXPECT_STREQ("unit_test", video->name());
EXPECT_EQ(kWidth - 10, video->display_width());
EXPECT_EQ(kHeight - 10, video->display_height());
EXPECT_DOUBLE_EQ(0.5, video->frame_rate());
EXPECT_EQ(kVideoTrackNumber, video->uid());
// Add an Audio Track
const int aud_track =
segment_.AddAudioTrack(kSampleRate, kChannels, kAudioTrackNumber);
EXPECT_EQ(kAudioTrackNumber, aud_track);
AudioTrack* const audio =
dynamic_cast<AudioTrack*>(segment_.GetTrackByNumber(aud_track));
EXPECT_EQ(kSampleRate, audio->sample_rate());
EXPECT_EQ(kChannels, audio->channels());
ASSERT_TRUE(audio != NULL);
audio->set_name("unit_test");
audio->set_bit_depth(2);
audio->set_uid(2);
EXPECT_STREQ("unit_test", audio->name());
EXPECT_EQ(2, audio->bit_depth());
EXPECT_EQ(2, audio->uid());
AddDummyFrameAndFinalize(kVideoTrackNumber);
CloseWriter();
EXPECT_TRUE(CompareFiles(GetTestFilePath("tracks.webm"), filename_));
}
TEST_F(MuxerTest, AddChapters) {
EXPECT_TRUE(SegmentInit(false));
AddVideoTrack();
// Add a Chapter
Chapter* chapter = segment_.AddChapter();
EXPECT_TRUE(chapter->set_id("unit_test"));
chapter->set_time(segment_, 0, 1000000000);
EXPECT_TRUE(chapter->add_string("unit_test", "english", "us"));
chapter->set_uid(1);
AddDummyFrameAndFinalize(kVideoTrackNumber);
CloseWriter();
EXPECT_TRUE(CompareFiles(GetTestFilePath("chapters.webm"), filename_));
}
TEST_F(MuxerTest, SimpleBlock) {
EXPECT_TRUE(SegmentInit(false));
AddVideoTrack();
// Valid Frame
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, 0,
false));
// Valid Frame
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
2000000, false));
// Invalid Frame - Non monotonically increasing timestamp
EXPECT_FALSE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
1, false));
// Invalid Frame - Null pointer
EXPECT_FALSE(segment_.AddFrame(NULL, 0, kVideoTrackNumber, 8000000, false));
// Invalid Frame - Invalid track number
EXPECT_FALSE(segment_.AddFrame(NULL, 0, kInvalidTrackNumber, 8000000, false));
segment_.Finalize();
CloseWriter();
EXPECT_TRUE(CompareFiles(GetTestFilePath("simple_block.webm"), filename_));
}
TEST_F(MuxerTest, SimpleBlockWithAddGenericFrame) {
EXPECT_TRUE(SegmentInit(false));
AddVideoTrack();
Frame frame;
frame.Init(dummy_data_, kFrameLength);
frame.set_track_number(kVideoTrackNumber);
frame.set_is_key(false);
// Valid Frame
frame.set_timestamp(0);
EXPECT_TRUE(segment_.AddGenericFrame(&frame));
// Valid Frame
frame.set_timestamp(2000000);
EXPECT_TRUE(segment_.AddGenericFrame(&frame));
// Invalid Frame - Non monotonically increasing timestamp
frame.set_timestamp(1);
EXPECT_FALSE(segment_.AddGenericFrame(&frame));
// Invalid Frame - Invalid track number
frame.set_track_number(kInvalidTrackNumber);
frame.set_timestamp(8000000);
EXPECT_FALSE(segment_.AddGenericFrame(&frame));
segment_.Finalize();
CloseWriter();
EXPECT_TRUE(CompareFiles(GetTestFilePath("simple_block.webm"), filename_));
}
TEST_F(MuxerTest, MetadataBlock) {
EXPECT_TRUE(SegmentInit(false));
Track* const track = segment_.AddTrack(kMetadataTrackNumber);
track->set_uid(kMetadataTrackNumber);
track->set_type(kMetadataTrackType);
track->set_codec_id(kMetadataCodecId);
// Valid Frame
EXPECT_TRUE(segment_.AddMetadata(dummy_data_, kFrameLength,
kMetadataTrackNumber, 0, 2000000));
// Valid Frame
EXPECT_TRUE(segment_.AddMetadata(dummy_data_, kFrameLength,
kMetadataTrackNumber, 2000000, 6000000));
// Invalid Frame - Non monotonically increasing timestamp
EXPECT_FALSE(segment_.AddMetadata(dummy_data_, kFrameLength,
kMetadataTrackNumber, 1, 2000000));
// Invalid Frame - Null pointer
EXPECT_FALSE(segment_.AddMetadata(NULL, 0, kMetadataTrackNumber, 0, 8000000));
// Invalid Frame - Invalid track number
EXPECT_FALSE(segment_.AddMetadata(NULL, 0, kInvalidTrackNumber, 0, 8000000));
segment_.Finalize();
CloseWriter();
EXPECT_TRUE(CompareFiles(GetTestFilePath("metadata_block.webm"), filename_));
}
TEST_F(MuxerTest, TrackType) {
EXPECT_TRUE(SegmentInit(false));
Track* const track = segment_.AddTrack(kMetadataTrackNumber);
track->set_uid(kMetadataTrackNumber);
track->set_codec_id(kMetadataCodecId);
// Invalid Frame - Incomplete track information (Track Type not set).
EXPECT_FALSE(segment_.AddMetadata(dummy_data_, kFrameLength,
kMetadataTrackNumber, 0, 2000000));
track->set_type(kMetadataTrackType);
// Valid Frame
EXPECT_TRUE(segment_.AddMetadata(dummy_data_, kFrameLength,
kMetadataTrackNumber, 0, 2000000));
segment_.Finalize();
CloseWriter();
}
TEST_F(MuxerTest, BlockWithAdditional) {
EXPECT_TRUE(SegmentInit(false));
AddVideoTrack();
// Valid Frame
EXPECT_TRUE(segment_.AddFrameWithAdditional(dummy_data_, kFrameLength,
dummy_data_, kFrameLength, 1,
kVideoTrackNumber, 0, false));
// Valid Frame
EXPECT_TRUE(segment_.AddFrameWithAdditional(
dummy_data_, kFrameLength, dummy_data_, kFrameLength, 1,
kVideoTrackNumber, 2000000, false));
// Invalid Frame - Non monotonically increasing timestamp
EXPECT_FALSE(segment_.AddFrameWithAdditional(dummy_data_, kFrameLength,
dummy_data_, kFrameLength, 1,
kVideoTrackNumber, 1, false));
// Invalid Frame - Null frame pointer
EXPECT_FALSE(
segment_.AddFrameWithAdditional(NULL, 0, dummy_data_, kFrameLength, 1,
kVideoTrackNumber, 3000000, false));
// Invalid Frame - Null additional pointer
EXPECT_FALSE(segment_.AddFrameWithAdditional(dummy_data_, kFrameLength, NULL,
0, 1, kVideoTrackNumber, 4000000,
false));
// Invalid Frame - Invalid track number
EXPECT_FALSE(segment_.AddFrameWithAdditional(
dummy_data_, kFrameLength, dummy_data_, kFrameLength, 1,
kInvalidTrackNumber, 8000000, false));
segment_.Finalize();
CloseWriter();
EXPECT_TRUE(
CompareFiles(GetTestFilePath("block_with_additional.webm"), filename_));
}
TEST_F(MuxerTest, BlockAdditionalWithAddGenericFrame) {
EXPECT_TRUE(SegmentInit(false));
AddVideoTrack();
Frame frame;
frame.Init(dummy_data_, kFrameLength);
frame.AddAdditionalData(dummy_data_, kFrameLength, 1);
frame.set_track_number(kVideoTrackNumber);
frame.set_is_key(false);
// Valid Frame
frame.set_timestamp(0);
EXPECT_TRUE(segment_.AddGenericFrame(&frame));
// Valid Frame
frame.set_timestamp(2000000);
EXPECT_TRUE(segment_.AddGenericFrame(&frame));
// Invalid Frame - Non monotonically increasing timestamp
frame.set_timestamp(1);
EXPECT_FALSE(segment_.AddGenericFrame(&frame));
// Invalid Frame - Invalid track number
frame.set_track_number(kInvalidTrackNumber);
frame.set_timestamp(4000000);
EXPECT_FALSE(segment_.AddGenericFrame(&frame));
segment_.Finalize();
CloseWriter();
EXPECT_TRUE(
CompareFiles(GetTestFilePath("block_with_additional.webm"), filename_));
}
TEST_F(MuxerTest, SegmentDurationComputation) {
EXPECT_TRUE(SegmentInit(false));
AddVideoTrack();
Frame frame;
frame.Init(dummy_data_, kFrameLength);
frame.set_track_number(kVideoTrackNumber);
frame.set_timestamp(0);
frame.set_is_key(false);
EXPECT_TRUE(segment_.AddGenericFrame(&frame));
frame.set_timestamp(2000000);
EXPECT_TRUE(segment_.AddGenericFrame(&frame));
frame.set_timestamp(4000000);
EXPECT_TRUE(segment_.AddGenericFrame(&frame));
frame.set_timestamp(6000000);
frame.set_duration(2000000);
EXPECT_TRUE(segment_.AddGenericFrame(&frame));
segment_.Finalize();
// SegmentInfo's duration is in timecode scale
EXPECT_EQ(8, segment_.GetSegmentInfo()->duration());
CloseWriter();
EXPECT_TRUE(
CompareFiles(GetTestFilePath("segment_duration.webm"), filename_));
}
TEST_F(MuxerTest, ForceNewCluster) {
EXPECT_TRUE(SegmentInit(false));
AddVideoTrack();
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, 0,
false));
segment_.ForceNewClusterOnNextFrame();
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
2000000, false));
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
4000000, false));
segment_.ForceNewClusterOnNextFrame();
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
6000000, false));
segment_.Finalize();
CloseWriter();
EXPECT_TRUE(
CompareFiles(GetTestFilePath("force_new_cluster.webm"), filename_));
}
TEST_F(MuxerTest, OutputCues) {
EXPECT_TRUE(SegmentInit(true));
AddVideoTrack();
EXPECT_TRUE(
segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, 0, true));
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
2000000, false));
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
4000000, false));
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
6000000, true));
EXPECT_TRUE(segment_.AddCuePoint(4000000, kVideoTrackNumber));
segment_.Finalize();
CloseWriter();
EXPECT_TRUE(CompareFiles(GetTestFilePath("output_cues.webm"), filename_));
}
TEST_F(MuxerTest, CuesBeforeClusters) {
EXPECT_TRUE(SegmentInit(true));
AddVideoTrack();
EXPECT_TRUE(
segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, 0, true));
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
2000000, false));
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
4000000, false));
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
6000000, true));
segment_.Finalize();
CloseWriter();
mkvparser::MkvReader reader;
reader.Open(filename_.c_str());
MkvWriter cues_writer;
std::string cues_filename = std::tmpnam(nullptr);
cues_writer.Open(cues_filename.c_str());
EXPECT_TRUE(segment_.CopyAndMoveCuesBeforeClusters(&reader, &cues_writer));
reader.Close();
cues_writer.Close();
EXPECT_TRUE(CompareFiles(GetTestFilePath("cues_before_clusters.webm"),
cues_filename));
}
TEST_F(MuxerTest, MaxClusterSize) {
EXPECT_TRUE(SegmentInit(false));
AddVideoTrack();
segment_.set_max_cluster_size(20);
EXPECT_EQ(20, segment_.max_cluster_size());
EXPECT_TRUE(segment_.AddFrame(dummy_data_, 1, kVideoTrackNumber, 0, false));
EXPECT_TRUE(
segment_.AddFrame(dummy_data_, 1, kVideoTrackNumber, 2000000, false));
EXPECT_TRUE(
segment_.AddFrame(dummy_data_, 1, kVideoTrackNumber, 4000000, false));
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
6000000, false));
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
8000000, false));
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
9000000, false));
segment_.Finalize();
CloseWriter();
EXPECT_TRUE(
CompareFiles(GetTestFilePath("max_cluster_size.webm"), filename_));
}
TEST_F(MuxerTest, MaxClusterDuration) {
EXPECT_TRUE(SegmentInit(false));
AddVideoTrack();
segment_.set_max_cluster_duration(4000000);
EXPECT_EQ(4000000, segment_.max_cluster_duration());
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber, 0,
false));
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
2000000, false));
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
4000000, false));
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
6000000, false));
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
8000000, false));
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kVideoTrackNumber,
9000000, false));
segment_.Finalize();
CloseWriter();
EXPECT_TRUE(
CompareFiles(GetTestFilePath("max_cluster_duration.webm"), filename_));
}
TEST_F(MuxerTest, SetCuesTrackNumber) {
const int kTrackNumber = 10;
EXPECT_TRUE(SegmentInit(true));
const int vid_track = segment_.AddVideoTrack(kWidth, kHeight, kTrackNumber);
EXPECT_EQ(kTrackNumber, vid_track);
segment_.GetTrackByNumber(vid_track)->set_uid(kVideoTrackNumber);
EXPECT_TRUE(segment_.CuesTrack(vid_track));
EXPECT_EQ(vid_track, segment_.cues_track());
EXPECT_TRUE(
segment_.AddFrame(dummy_data_, kFrameLength, kTrackNumber, 0, true));
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kTrackNumber,
2000000, false));
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kTrackNumber,
4000000, false));
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kTrackNumber,
6000000, true));
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kTrackNumber,
8000000, false));
EXPECT_TRUE(segment_.AddFrame(dummy_data_, kFrameLength, kTrackNumber,
9000000, false));
segment_.Finalize();
CloseWriter();
EXPECT_TRUE(
CompareFiles(GetTestFilePath("set_cues_track_number.webm"), filename_));
}
TEST_F(MuxerTest, BlockWithDiscardPadding) {
EXPECT_TRUE(SegmentInit(false));
// Add an Audio Track
const int aud_track =
segment_.AddAudioTrack(kSampleRate, kChannels, kAudioTrackNumber);
EXPECT_EQ(kAudioTrackNumber, aud_track);
AudioTrack* const audio =
dynamic_cast<AudioTrack*>(segment_.GetTrackByNumber(aud_track));
EXPECT_EQ(kSampleRate, audio->sample_rate());
EXPECT_EQ(kChannels, audio->channels());
ASSERT_TRUE(audio != NULL);
audio->set_name("unit_test");
audio->set_bit_depth(2);
audio->set_uid(2);
audio->set_codec_id(kOpusCodecId);
EXPECT_STREQ("unit_test", audio->name());
EXPECT_EQ(2, audio->bit_depth());
EXPECT_EQ(2, audio->uid());
EXPECT_STREQ(kOpusCodecId, audio->codec_id());
int timecode = 1000;
// 12810000 == 0xc37710, should be 0-extended to avoid changing the sign.
// The next two should be written as 1 byte.
std::array<int, 3> values = {{12810000, 127, -128}};
for (const std::int64_t discard_padding : values) {
EXPECT_TRUE(segment_.AddFrameWithDiscardPadding(
dummy_data_, kFrameLength, discard_padding, kAudioTrackNumber, timecode,
true))
<< "discard_padding: " << discard_padding;
timecode += 1000;
}
segment_.Finalize();
CloseWriter();
EXPECT_TRUE(CompareFiles(GetTestFilePath("discard_padding.webm"), filename_));
}
} // namespace test
} // namespace libwebm
int main(int argc, char* argv[]) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

572
testing/parser_tests.cc Normal file
View File

@ -0,0 +1,572 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "gtest/gtest.h"
#include <array>
#include <cstdint>
#include <string>
#include "mkvparser.hpp"
#include "mkvreader.hpp"
#include "testing/test_util.h"
using ::mkvparser::AudioTrack;
using ::mkvparser::Block;
using ::mkvparser::BlockEntry;
using ::mkvparser::BlockGroup;
using ::mkvparser::Cluster;
using ::mkvparser::CuePoint;
using ::mkvparser::Cues;
using ::mkvparser::MkvReader;
using ::mkvparser::Segment;
using ::mkvparser::SegmentInfo;
using ::mkvparser::Track;
using ::mkvparser::Tracks;
using ::mkvparser::VideoTrack;
namespace libwebm {
namespace test {
// Base class containing boiler plate stuff.
class ParserTest : public testing::Test {
public:
ParserTest() : is_reader_open_(false), segment_(NULL) {
memset(dummy_data_, -1, kFrameLength);
memset(gold_frame_, 0, kFrameLength);
}
virtual ~ParserTest() {
CloseReader();
if (segment_ != NULL) {
delete segment_;
segment_ = NULL;
}
}
void CloseReader() {
if (is_reader_open_) {
reader_.Close();
}
is_reader_open_ = false;
}
bool CreateAndLoadSegment(const std::string& filename,
int expected_doc_type_ver) {
filename_ = GetTestFilePath(filename);
if (reader_.Open(filename_.c_str())) {
return false;
}
is_reader_open_ = true;
pos_ = 0;
mkvparser::EBMLHeader ebml_header;
ebml_header.Parse(&reader_, pos_);
EXPECT_EQ(1, ebml_header.m_version);
EXPECT_EQ(1, ebml_header.m_readVersion);
EXPECT_STREQ("webm", ebml_header.m_docType);
EXPECT_EQ(expected_doc_type_ver, ebml_header.m_docTypeVersion);
EXPECT_EQ(2, ebml_header.m_docTypeReadVersion);
if (mkvparser::Segment::CreateInstance(&reader_, pos_, segment_)) {
return false;
}
return !HasFailure() && segment_->Load() >= 0;
}
bool CreateAndLoadSegment(const std::string& filename) {
return CreateAndLoadSegment(filename, 2);
}
void CompareBlockContents(const Cluster* const cluster,
const Block* const block, std::uint64_t timestamp,
int track_number, bool is_key, int frame_count) {
ASSERT_TRUE(block != NULL);
EXPECT_EQ(track_number, block->GetTrackNumber());
EXPECT_EQ(timestamp, block->GetTime(cluster));
EXPECT_EQ(is_key, block->IsKey());
EXPECT_EQ(frame_count, block->GetFrameCount());
const Block::Frame& frame = block->GetFrame(0);
EXPECT_EQ(kFrameLength, frame.len);
std::memset(dummy_data_, -1, kFrameLength);
frame.Read(&reader_, dummy_data_);
EXPECT_EQ(0, memcmp(gold_frame_, dummy_data_, kFrameLength));
}
void CompareCuePointContents(const Track* const track,
const CuePoint* const cue_point,
std::uint64_t timestamp, int track_number,
std::uint64_t pos) {
ASSERT_TRUE(cue_point != NULL);
EXPECT_EQ(timestamp, cue_point->GetTime(segment_));
const CuePoint::TrackPosition* const track_position =
cue_point->Find(track);
EXPECT_EQ(track_number, track_position->m_track);
EXPECT_EQ(pos, track_position->m_pos);
}
protected:
MkvReader reader_;
bool is_reader_open_;
Segment* segment_;
std::string filename_;
std::int64_t pos_;
std::uint8_t dummy_data_[kFrameLength];
std::uint8_t gold_frame_[kFrameLength];
};
TEST_F(ParserTest, SegmentInfo) {
ASSERT_TRUE(CreateAndLoadSegment("segment_info.webm"));
const SegmentInfo* const info = segment_->GetInfo();
EXPECT_EQ(kTimeCodeScale, info->GetTimeCodeScale());
EXPECT_STREQ(kAppString, info->GetMuxingAppAsUTF8());
EXPECT_STREQ(kAppString, info->GetWritingAppAsUTF8());
}
TEST_F(ParserTest, TrackEntries) {
ASSERT_TRUE(CreateAndLoadSegment("tracks.webm"));
const Tracks* const tracks = segment_->GetTracks();
EXPECT_EQ(2, tracks->GetTracksCount());
for (int i = 0; i < 2; ++i) {
const Track* const track = tracks->GetTrackByIndex(i);
ASSERT_TRUE(track != NULL);
EXPECT_STREQ(kTrackName, track->GetNameAsUTF8());
if (track->GetType() == Track::kVideo) {
const VideoTrack* const video_track =
dynamic_cast<const VideoTrack*>(track);
EXPECT_EQ(kWidth, video_track->GetWidth());
EXPECT_EQ(kHeight, video_track->GetHeight());
EXPECT_STREQ(kVP8CodecId, video_track->GetCodecId());
EXPECT_DOUBLE_EQ(kVideoFrameRate, video_track->GetFrameRate());
EXPECT_EQ(1, video_track->GetUid());
} else if (track->GetType() == Track::kAudio) {
const AudioTrack* const audio_track =
dynamic_cast<const AudioTrack*>(track);
EXPECT_EQ(kSampleRate, audio_track->GetSamplingRate());
EXPECT_EQ(kChannels, audio_track->GetChannels());
EXPECT_EQ(kBitDepth, audio_track->GetBitDepth());
EXPECT_STREQ(kVorbisCodecId, audio_track->GetCodecId());
EXPECT_EQ(2, audio_track->GetUid());
}
}
}
TEST_F(ParserTest, SimpleBlock) {
ASSERT_TRUE(CreateAndLoadSegment("simple_block.webm"));
EXPECT_EQ(1, segment_->GetTracks()->GetTracksCount());
// Get the cluster
const Cluster* cluster = segment_->GetFirst();
ASSERT_TRUE(cluster != NULL);
EXPECT_FALSE(cluster->EOS());
// Get the first block
const BlockEntry* block_entry;
EXPECT_EQ(0, cluster->GetFirst(block_entry));
ASSERT_TRUE(block_entry != NULL);
EXPECT_FALSE(block_entry->EOS());
CompareBlockContents(cluster, block_entry->GetBlock(), 0, kVideoTrackNumber,
false, 1);
// Get the second block
EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry));
ASSERT_TRUE(block_entry != NULL);
EXPECT_FALSE(block_entry->EOS());
CompareBlockContents(cluster, block_entry->GetBlock(), 2000000,
kVideoTrackNumber, false, 1);
// End of Stream
EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry));
ASSERT_EQ(NULL, block_entry);
cluster = segment_->GetNext(cluster);
EXPECT_TRUE(cluster->EOS());
}
TEST_F(ParserTest, MultipleClusters) {
ASSERT_TRUE(CreateAndLoadSegment("force_new_cluster.webm"));
EXPECT_EQ(1, segment_->GetTracks()->GetTracksCount());
// Get the first cluster
const Cluster* cluster = segment_->GetFirst();
ASSERT_TRUE(cluster != NULL);
EXPECT_FALSE(cluster->EOS());
// Get the first block
const BlockEntry* block_entry;
EXPECT_EQ(0, cluster->GetFirst(block_entry));
ASSERT_TRUE(block_entry != NULL);
EXPECT_FALSE(block_entry->EOS());
CompareBlockContents(cluster, block_entry->GetBlock(), 0, kVideoTrackNumber,
false, 1);
// Get the second cluster
EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry));
EXPECT_EQ(NULL, block_entry);
cluster = segment_->GetNext(cluster);
ASSERT_TRUE(cluster != NULL);
EXPECT_FALSE(cluster->EOS());
// Get the second block
EXPECT_EQ(0, cluster->GetFirst(block_entry));
ASSERT_TRUE(block_entry != NULL);
EXPECT_FALSE(block_entry->EOS());
CompareBlockContents(cluster, block_entry->GetBlock(), 2000000,
kVideoTrackNumber, false, 1);
// Get the third block
EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry));
ASSERT_TRUE(block_entry != NULL);
EXPECT_FALSE(block_entry->EOS());
CompareBlockContents(cluster, block_entry->GetBlock(), 4000000,
kVideoTrackNumber, false, 1);
// Get the third cluster
EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry));
EXPECT_EQ(NULL, block_entry);
cluster = segment_->GetNext(cluster);
ASSERT_TRUE(cluster != NULL);
EXPECT_FALSE(cluster->EOS());
// Get the fourth block
EXPECT_EQ(0, cluster->GetFirst(block_entry));
ASSERT_TRUE(block_entry != NULL);
EXPECT_FALSE(block_entry->EOS());
CompareBlockContents(cluster, block_entry->GetBlock(), 6000000,
kVideoTrackNumber, false, 1);
// End of Stream
EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry));
EXPECT_EQ(NULL, block_entry);
cluster = segment_->GetNext(cluster);
EXPECT_TRUE(cluster->EOS());
}
TEST_F(ParserTest, BlockGroup) {
ASSERT_TRUE(CreateAndLoadSegment("metadata_block.webm"));
EXPECT_EQ(1, segment_->GetTracks()->GetTracksCount());
// Get the cluster
const Cluster* cluster = segment_->GetFirst();
ASSERT_TRUE(cluster != NULL);
EXPECT_FALSE(cluster->EOS());
// Get the first block
const BlockEntry* block_entry;
EXPECT_EQ(0, cluster->GetFirst(block_entry));
ASSERT_TRUE(block_entry != NULL);
EXPECT_FALSE(block_entry->EOS());
EXPECT_EQ(BlockEntry::Kind::kBlockGroup, block_entry->GetKind());
const BlockGroup* block_group = static_cast<const BlockGroup*>(block_entry);
EXPECT_EQ(2, block_group->GetDurationTimeCode());
CompareBlockContents(cluster, block_group->GetBlock(), 0,
kMetadataTrackNumber, true, 1);
// Get the second block
EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry));
ASSERT_TRUE(block_entry != NULL);
EXPECT_FALSE(block_entry->EOS());
EXPECT_EQ(BlockEntry::Kind::kBlockGroup, block_entry->GetKind());
block_group = static_cast<const BlockGroup*>(block_entry);
EXPECT_EQ(6, block_group->GetDurationTimeCode());
CompareBlockContents(cluster, block_group->GetBlock(), 2000000,
kMetadataTrackNumber, true, 1);
// End of Stream
EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry));
EXPECT_EQ(NULL, block_entry);
cluster = segment_->GetNext(cluster);
EXPECT_TRUE(cluster->EOS());
}
TEST_F(ParserTest, Cues) {
ASSERT_TRUE(CreateAndLoadSegment("output_cues.webm"));
EXPECT_EQ(1, segment_->GetTracks()->GetTracksCount());
const Track* const track = segment_->GetTracks()->GetTrackByIndex(0);
const Cues* const cues = segment_->GetCues();
ASSERT_TRUE(cues != NULL);
while (!cues->DoneParsing()) {
cues->LoadCuePoint();
}
EXPECT_EQ(3, cues->GetCount());
// Get first Cue Point
const CuePoint* cue_point = cues->GetFirst();
CompareCuePointContents(track, cue_point, 0, kVideoTrackNumber, 206);
// Get second Cue Point
cue_point = cues->GetNext(cue_point);
CompareCuePointContents(track, cue_point, 6000000, kVideoTrackNumber, 269);
// Get third (also last) Cue Point
cue_point = cues->GetNext(cue_point);
const CuePoint* last_cue_point = cues->GetLast();
EXPECT_TRUE(cue_point == last_cue_point);
CompareCuePointContents(track, cue_point, 4000000, kVideoTrackNumber, 269);
}
TEST_F(ParserTest, CuesBeforeClusters) {
ASSERT_TRUE(CreateAndLoadSegment("cues_before_clusters.webm"));
EXPECT_EQ(1, segment_->GetTracks()->GetTracksCount());
const Track* const track = segment_->GetTracks()->GetTrackByIndex(0);
const Cues* const cues = segment_->GetCues();
ASSERT_TRUE(cues != NULL);
while (!cues->DoneParsing()) {
cues->LoadCuePoint();
}
EXPECT_EQ(2, cues->GetCount());
// Get first Cue Point
const CuePoint* cue_point = cues->GetFirst();
CompareCuePointContents(track, cue_point, 0, kVideoTrackNumber, 238);
// Get second (also last) Cue Point
cue_point = cues->GetNext(cue_point);
const CuePoint* last_cue_point = cues->GetLast();
EXPECT_TRUE(cue_point == last_cue_point);
CompareCuePointContents(track, cue_point, 6000000, kVideoTrackNumber, 301);
}
TEST_F(ParserTest, CuesTrackNumber) {
ASSERT_TRUE(CreateAndLoadSegment("set_cues_track_number.webm"));
EXPECT_EQ(1, segment_->GetTracks()->GetTracksCount());
const Track* const track = segment_->GetTracks()->GetTrackByIndex(0);
const Cues* const cues = segment_->GetCues();
ASSERT_TRUE(cues != NULL);
while (!cues->DoneParsing()) {
cues->LoadCuePoint();
}
EXPECT_EQ(2, cues->GetCount());
// Get first Cue Point
const CuePoint* cue_point = cues->GetFirst();
CompareCuePointContents(track, cue_point, 0, 10, 206);
// Get second (also last) Cue Point
cue_point = cues->GetNext(cue_point);
const CuePoint* last_cue_point = cues->GetLast();
EXPECT_TRUE(cue_point == last_cue_point);
CompareCuePointContents(track, cue_point, 6000000, 10, 269);
}
TEST_F(ParserTest, Opus) {
ASSERT_TRUE(CreateAndLoadSegment("bbb_480p_vp9_opus_1second.webm", 4));
EXPECT_EQ(2, segment_->GetTracks()->GetTracksCount());
// --------------------------------------------------------------------------
// Track Header validation.
const Tracks* const tracks = segment_->GetTracks();
EXPECT_EQ(2, tracks->GetTracksCount());
for (int i = 0; i < 2; ++i) {
const Track* const track = tracks->GetTrackByIndex(i);
ASSERT_TRUE(track != NULL);
EXPECT_EQ(NULL, track->GetNameAsUTF8());
EXPECT_STREQ("und", track->GetLanguage());
EXPECT_EQ(i + 1, track->GetNumber());
EXPECT_FALSE(track->GetLacing());
if (track->GetType() == Track::kVideo) {
const VideoTrack* const video_track =
dynamic_cast<const VideoTrack*>(track);
EXPECT_EQ(854, video_track->GetWidth());
EXPECT_EQ(480, video_track->GetHeight());
EXPECT_STREQ(kVP9CodecId, video_track->GetCodecId());
EXPECT_DOUBLE_EQ(0., video_track->GetFrameRate());
EXPECT_EQ(41666666, video_track->GetDefaultDuration()); // 24.000
EXPECT_EQ(kVideoTrackNumber, video_track->GetUid());
EXPECT_EQ(0, video_track->GetCodecDelay());
EXPECT_EQ(0, video_track->GetSeekPreRoll());
size_t video_codec_private_size;
EXPECT_EQ(NULL, video_track->GetCodecPrivate(video_codec_private_size));
EXPECT_EQ(0, video_codec_private_size);
} else if (track->GetType() == Track::kAudio) {
const AudioTrack* const audio_track =
dynamic_cast<const AudioTrack*>(track);
EXPECT_EQ(48000, audio_track->GetSamplingRate());
EXPECT_EQ(6, audio_track->GetChannels());
EXPECT_EQ(32, audio_track->GetBitDepth());
EXPECT_STREQ(kOpusCodecId, audio_track->GetCodecId());
EXPECT_EQ(kAudioTrackNumber, audio_track->GetUid());
EXPECT_EQ(0, audio_track->GetDefaultDuration());
EXPECT_EQ(kOpusCodecDelay, audio_track->GetCodecDelay());
EXPECT_EQ(kOpusSeekPreroll, audio_track->GetSeekPreRoll());
size_t audio_codec_private_size;
EXPECT_TRUE(audio_track->GetCodecPrivate(audio_codec_private_size) !=
NULL);
EXPECT_GE(audio_codec_private_size, kOpusPrivateDataSizeMinimum);
}
}
// --------------------------------------------------------------------------
// Parse the file to do block-level validation.
const Cluster* cluster = segment_->GetFirst();
ASSERT_TRUE(cluster != NULL);
EXPECT_FALSE(cluster->EOS());
for (; cluster != NULL && !cluster->EOS();
cluster = segment_->GetNext(cluster)) {
// Get the first block
const BlockEntry* block_entry;
EXPECT_EQ(0, cluster->GetFirst(block_entry));
ASSERT_TRUE(block_entry != NULL);
EXPECT_FALSE(block_entry->EOS());
while (block_entry != NULL && !block_entry->EOS()) {
const Block* const block = block_entry->GetBlock();
ASSERT_TRUE(block != NULL);
EXPECT_FALSE(block->IsInvisible());
EXPECT_EQ(Block::kLacingNone, block->GetLacing());
const std::uint32_t track_number =
static_cast<std::uint32_t>(block->GetTrackNumber());
const Track* const track = tracks->GetTrackByNumber(track_number);
ASSERT_TRUE(track != NULL);
EXPECT_EQ(track->GetNumber(), block->GetTrackNumber());
EXPECT_EQ(0, track->GetContentEncodingCount()); // no encryption
const std::int64_t track_type = track->GetType();
EXPECT_TRUE(track_type == Track::kVideo || track_type == Track::kAudio);
if (track_type == Track::kVideo) {
EXPECT_EQ(BlockEntry::kBlockSimple, block_entry->GetKind());
EXPECT_EQ(0, block->GetDiscardPadding());
} else {
EXPECT_TRUE(block->IsKey());
const std::int64_t kLastAudioTimecode = 1001;
const std::int64_t timecode = block->GetTimeCode(cluster);
// Only the final Opus block should have discard padding.
if (timecode == kLastAudioTimecode) {
EXPECT_EQ(BlockEntry::kBlockGroup, block_entry->GetKind());
EXPECT_EQ(13500000, block->GetDiscardPadding());
} else {
EXPECT_EQ(BlockEntry::kBlockSimple, block_entry->GetKind());
EXPECT_EQ(0, block->GetDiscardPadding());
}
}
const int frame_count = block->GetFrameCount();
const Block::Frame& frame = block->GetFrame(0);
EXPECT_EQ(1, frame_count);
EXPECT_GT(frame.len, 0);
EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry));
}
}
ASSERT_TRUE(cluster != NULL);
EXPECT_TRUE(cluster->EOS());
}
TEST_F(ParserTest, DiscardPadding) {
// Test an artificial file with some extreme DiscardPadding values.
const std::string file = "discard_padding.webm";
ASSERT_TRUE(CreateAndLoadSegment(file, 4));
EXPECT_EQ(1, segment_->GetTracks()->GetTracksCount());
// --------------------------------------------------------------------------
// Track Header validation.
const Tracks* const tracks = segment_->GetTracks();
EXPECT_EQ(1, tracks->GetTracksCount());
const Track* const track = tracks->GetTrackByIndex(0);
ASSERT_TRUE(track != NULL);
EXPECT_STREQ("unit_test", track->GetNameAsUTF8());
EXPECT_EQ(NULL, track->GetLanguage());
EXPECT_EQ(kAudioTrackNumber, track->GetNumber());
EXPECT_TRUE(track->GetLacing());
EXPECT_EQ(Track::kAudio, track->GetType());
const AudioTrack* const audio_track = dynamic_cast<const AudioTrack*>(track);
EXPECT_EQ(30, audio_track->GetSamplingRate());
EXPECT_EQ(2, audio_track->GetChannels());
EXPECT_EQ(2, audio_track->GetBitDepth());
EXPECT_STREQ(kOpusCodecId, audio_track->GetCodecId());
EXPECT_EQ(kAudioTrackNumber, audio_track->GetUid());
EXPECT_EQ(0, audio_track->GetDefaultDuration());
EXPECT_EQ(0, audio_track->GetCodecDelay());
EXPECT_EQ(0, audio_track->GetSeekPreRoll());
size_t audio_codec_private_size;
EXPECT_EQ(NULL, audio_track->GetCodecPrivate(audio_codec_private_size));
EXPECT_EQ(0, audio_codec_private_size);
// --------------------------------------------------------------------------
// Parse the file to do block-level validation.
const Cluster* cluster = segment_->GetFirst();
ASSERT_TRUE(cluster != NULL);
EXPECT_FALSE(cluster->EOS());
EXPECT_EQ(1, segment_->GetCount());
// Get the first block
const BlockEntry* block_entry;
EXPECT_EQ(0, cluster->GetFirst(block_entry));
ASSERT_TRUE(block_entry != NULL);
EXPECT_FALSE(block_entry->EOS());
const std::array<int, 3> discard_padding = {{12810000, 127, -128}};
int index = 0;
while (block_entry != NULL && !block_entry->EOS()) {
const Block* const block = block_entry->GetBlock();
ASSERT_TRUE(block != NULL);
EXPECT_FALSE(block->IsInvisible());
EXPECT_EQ(Block::kLacingNone, block->GetLacing());
const std::uint32_t track_number =
static_cast<std::uint32_t>(block->GetTrackNumber());
const Track* const track = tracks->GetTrackByNumber(track_number);
ASSERT_TRUE(track != NULL);
EXPECT_EQ(track->GetNumber(), block->GetTrackNumber());
EXPECT_EQ(0, track->GetContentEncodingCount()); // no encryption
const std::int64_t track_type = track->GetType();
EXPECT_EQ(Track::kAudio, track_type);
EXPECT_TRUE(block->IsKey());
// All blocks have DiscardPadding.
EXPECT_EQ(BlockEntry::kBlockGroup, block_entry->GetKind());
ASSERT_LT(index, discard_padding.size());
EXPECT_EQ(discard_padding[index], block->GetDiscardPadding());
++index;
const int frame_count = block->GetFrameCount();
const Block::Frame& frame = block->GetFrame(0);
EXPECT_EQ(1, frame_count);
EXPECT_GT(frame.len, 0);
EXPECT_EQ(0, cluster->GetNext(block_entry, block_entry));
}
cluster = segment_->GetNext(cluster);
ASSERT_TRUE(cluster != NULL);
EXPECT_TRUE(cluster->EOS());
}
TEST_F(ParserTest, StereoModeParsedCorrectly) {
ASSERT_TRUE(CreateAndLoadSegment("test_stereo_left_right.webm"));
EXPECT_EQ(1, segment_->GetTracks()->GetTracksCount());
const VideoTrack* const video_track = dynamic_cast<const VideoTrack*>(
segment_->GetTracks()->GetTrackByIndex(0));
EXPECT_EQ(1, video_track->GetStereoMode());
EXPECT_EQ(256, video_track->GetWidth());
EXPECT_EQ(144, video_track->GetHeight());
EXPECT_EQ(128, video_track->GetDisplayWidth());
EXPECT_EQ(144, video_track->GetDisplayHeight());
}
} // namespace test
} // namespace libwebm
int main(int argc, char* argv[]) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

54
testing/test_util.cc Normal file
View File

@ -0,0 +1,54 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "testing/test_util.h"
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <memory>
#include <string>
#include "common/libwebm_utils.h"
namespace libwebm {
namespace test {
std::string GetTestDataDir() { return std::getenv("LIBWEBM_TEST_DATA_PATH"); }
std::string GetTestFilePath(const std::string& name) {
const std::string libwebm_testdata_dir = GetTestDataDir();
return libwebm_testdata_dir + "/" + name;
}
bool CompareFiles(const std::string& file1, const std::string& file2) {
const std::size_t kBlockSize = 4096;
std::uint8_t buf1[kBlockSize] = {0};
std::uint8_t buf2[kBlockSize] = {0};
FilePtr f1 = FilePtr(std::fopen(file1.c_str(), "rb"), FILEDeleter());
FilePtr f2 = FilePtr(std::fopen(file2.c_str(), "rb"), FILEDeleter());
if (!f1.get() || !f2.get()) {
// Files cannot match if one or both couldn't be opened.
return false;
}
do {
const std::size_t r1 = std::fread(buf1, 1, kBlockSize, f1.get());
const std::size_t r2 = std::fread(buf2, 1, kBlockSize, f2.get());
if (r1 != r2 || memcmp(buf1, buf2, r1)) {
return 0; // Files are not equal
}
} while (!std::feof(f1.get()) && !std::feof(f2.get()));
return std::feof(f1.get()) && std::feof(f2.get());
}
} // namespace test
} // namespace libwebm

57
testing/test_util.h Normal file
View File

@ -0,0 +1,57 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#ifndef LIBWEBM_TESTING_TEST_UTIL_H_
#define LIBWEBM_TESTING_TEST_UTIL_H_
#include <cstdint>
#include <string>
namespace libwebm {
namespace test {
// constants for muxer and parser tests
const char kAppString[] = "mkvmuxer_unit_tests";
const char kOpusCodecId[] = "A_OPUS";
const char kVorbisCodecId[] = "A_VORBIS";
const int kAudioTrackNumber = 2;
const int kBitDepth = 2;
const int kChannels = 2;
const double kDuration = 2.345;
const int kFrameLength = 10;
const int kHeight = 180;
const int kInvalidTrackNumber = 100;
const std::uint64_t kOpusCodecDelay = 6500000;
const std::size_t kOpusPrivateDataSizeMinimum = 19;
const std::uint64_t kOpusSeekPreroll = 80000000;
const char kMetadataCodecId[] = "D_WEBVTT/METADATA";
const int kMetadataTrackNumber = 3;
const int kMetadataTrackType = 0x21;
const int kSampleRate = 30;
const int kTimeCodeScale = 1000;
const char kTrackName[] = "unit_test";
const char kVP8CodecId[] = "V_VP8";
const char kVP9CodecId[] = "V_VP9";
const double kVideoFrameRate = 0.5;
const int kVideoTrackNumber = 1;
const int kWidth = 320;
// Returns the path to the test data directory by reading and returning the
// contents the LIBWEBM_TESTDATA_DIR environment variable.
std::string GetTestDataDir();
// Returns the absolute path to the file of |name| in LIBWEBM_TESTDATA_DIR.
std::string GetTestFilePath(const std::string& name);
// Byte-wise comparison of two files |file1| and |file2|. Returns true if the
// files match exactly, false otherwise.
bool CompareFiles(const std::string& file1, const std::string& file2);
} // namespace test
} // namespace libwebm
#endif // LIBWEBM_TESTING_TEST_UTIL_H_

Binary file not shown.

Binary file not shown.

BIN
testing/testdata/chapters.webm vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
testing/testdata/discard_padding.webm vendored Normal file

Binary file not shown.

BIN
testing/testdata/force_new_cluster.webm vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
testing/testdata/max_cluster_size.webm vendored Normal file

Binary file not shown.

BIN
testing/testdata/metadata_block.webm vendored Normal file

Binary file not shown.

BIN
testing/testdata/output_cues.webm vendored Normal file

Binary file not shown.

BIN
testing/testdata/segment_duration.webm vendored Normal file

Binary file not shown.

BIN
testing/testdata/segment_info.webm vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
testing/testdata/simple_block.webm vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
testing/testdata/tracks.webm vendored Normal file

Binary file not shown.