libwebm: Googletest integration.
Add basic mux/parse tests and test data. Change-Id: I3bef014f32ad4898d23bca792fb3fe275fe4e7c9
This commit is contained in:
parent
3bec1ba7a1
commit
9299bbb6ed
@ -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)
|
||||
|
@ -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
575
testing/muxer_tests.cc
Normal 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
572
testing/parser_tests.cc
Normal 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
54
testing/test_util.cc
Normal 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
57
testing/test_util.h
Normal 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_
|
BIN
testing/testdata/bbb_480p_vp9_opus_1second.webm
vendored
Normal file
BIN
testing/testdata/bbb_480p_vp9_opus_1second.webm
vendored
Normal file
Binary file not shown.
BIN
testing/testdata/block_with_additional.webm
vendored
Normal file
BIN
testing/testdata/block_with_additional.webm
vendored
Normal file
Binary file not shown.
BIN
testing/testdata/chapters.webm
vendored
Normal file
BIN
testing/testdata/chapters.webm
vendored
Normal file
Binary file not shown.
BIN
testing/testdata/cues_before_clusters.webm
vendored
Normal file
BIN
testing/testdata/cues_before_clusters.webm
vendored
Normal file
Binary file not shown.
BIN
testing/testdata/discard_padding.webm
vendored
Normal file
BIN
testing/testdata/discard_padding.webm
vendored
Normal file
Binary file not shown.
BIN
testing/testdata/force_new_cluster.webm
vendored
Normal file
BIN
testing/testdata/force_new_cluster.webm
vendored
Normal file
Binary file not shown.
BIN
testing/testdata/max_cluster_duration.webm
vendored
Normal file
BIN
testing/testdata/max_cluster_duration.webm
vendored
Normal file
Binary file not shown.
BIN
testing/testdata/max_cluster_size.webm
vendored
Normal file
BIN
testing/testdata/max_cluster_size.webm
vendored
Normal file
Binary file not shown.
BIN
testing/testdata/metadata_block.webm
vendored
Normal file
BIN
testing/testdata/metadata_block.webm
vendored
Normal file
Binary file not shown.
BIN
testing/testdata/output_cues.webm
vendored
Normal file
BIN
testing/testdata/output_cues.webm
vendored
Normal file
Binary file not shown.
BIN
testing/testdata/segment_duration.webm
vendored
Normal file
BIN
testing/testdata/segment_duration.webm
vendored
Normal file
Binary file not shown.
BIN
testing/testdata/segment_info.webm
vendored
Normal file
BIN
testing/testdata/segment_info.webm
vendored
Normal file
Binary file not shown.
BIN
testing/testdata/set_cues_track_number.webm
vendored
Normal file
BIN
testing/testdata/set_cues_track_number.webm
vendored
Normal file
Binary file not shown.
BIN
testing/testdata/simple_block.webm
vendored
Normal file
BIN
testing/testdata/simple_block.webm
vendored
Normal file
Binary file not shown.
BIN
testing/testdata/test_stereo_left_right.webm
vendored
Normal file
BIN
testing/testdata/test_stereo_left_right.webm
vendored
Normal file
Binary file not shown.
BIN
testing/testdata/tracks.webm
vendored
Normal file
BIN
testing/testdata/tracks.webm
vendored
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user