From ff8c2b6af7b3c92b96a9db264dbf076cb83b04a9 Mon Sep 17 00:00:00 2001 From: Tom Finegan Date: Wed, 17 Aug 2016 14:12:12 -0700 Subject: [PATCH] parser_tests: Move cue validation to test_util. And tidy it up a bit. Change-Id: I68e7f16ad2aa922fdb064802e8986a6955364c32 --- testing/parser_tests.cc | 72 ++------------------------------ testing/test_util.cc | 91 +++++++++++++++++++++++++++++++++++++++++ testing/test_util.h | 11 +++++ 3 files changed, 105 insertions(+), 69 deletions(-) diff --git a/testing/parser_tests.cc b/testing/parser_tests.cc index 1523504..b27f63a 100644 --- a/testing/parser_tests.cc +++ b/testing/parser_tests.cc @@ -111,72 +111,6 @@ class ParserTest : public testing::Test { EXPECT_EQ(static_cast(pos), track_position->m_pos); } - bool ValidateCues() { - const mkvparser::SeekHead* const seek_head = segment_->GetSeekHead(); - if (!seek_head) { // This likely means there are no cues. So don't fail. - return true; - } - long long cues_offset = -1; // NOLINT - for (int i = 0; i < seek_head->GetCount(); ++i) { - const mkvparser::SeekHead::Entry* const entry = seek_head->GetEntry(i); - if (entry->id == 0xC53BB6B) { // Cues ID as stored in Entry class. - cues_offset = entry->pos; - } - } - - if (cues_offset == -1) { // No Cues found. So don't fail. - return true; - } - - // Parse Cues. - long long cues_pos; // NOLINT - long cues_len; // NOLINT - if (segment_->ParseCues(cues_offset, cues_pos, cues_len)) { - fprintf(stderr, "Error: Parsing Cues failed.\n"); - return false; - } - - // Get a pointer to the video track if it exists. Otherwise, we assume - // that Cues are based on the first track (which is true for all our test - // files). - const mkvparser::Tracks* const tracks = segment_->GetTracks(); - const mkvparser::Track* cues_track = tracks->GetTrackByIndex(0); - for (int i = 1; i < static_cast(tracks->GetTracksCount()); ++i) { - const mkvparser::Track* const track = tracks->GetTrackByIndex(i); - if (track->GetType() == mkvparser::Track::kVideo) { - cues_track = track; - break; - } - } - - // Iterate through Cues and verify if they are pointing to the correct - // Cluster position. - const mkvparser::Cues* const cues = segment_->GetCues(); - const mkvparser::CuePoint* cue_point = NULL; - while (cues->LoadCuePoint()) { - if (!cue_point) { - cue_point = cues->GetFirst(); - } else { - cue_point = cues->GetNext(cue_point); - } - const mkvparser::CuePoint::TrackPosition* const track_position = - cue_point->Find(cues_track); - const long long cluster_pos = track_position->m_pos + // NOLINT - segment_->m_start; - - // If a cluster does not begin at |cluster_pos|, then the file is - // incorrect. - long length; // NOLINT - const long long id = // NOLINT - mkvparser::ReadUInt(&reader_, cluster_pos, length); - if (id != 0xF43B675) { // ID of Cluster as stored in Cluster class. - fprintf(stderr, "Error: One or more Cues are invalid.\n"); - return false; - } - } - return true; - } - protected: MkvReader reader_; bool is_reader_open_; @@ -383,7 +317,7 @@ TEST_F(ParserTest, Cues) { EXPECT_TRUE(cue_point == last_cue_point); CompareCuePointContents(track, cue_point, 4000000, kVideoTrackNumber, 269); - EXPECT_TRUE(ValidateCues()); + EXPECT_TRUE(ValidateCues(segment_, &reader_)); } TEST_F(ParserTest, CuesBeforeClusters) { @@ -409,7 +343,7 @@ TEST_F(ParserTest, CuesBeforeClusters) { EXPECT_TRUE(cue_point == last_cue_point); CompareCuePointContents(track, cue_point, 6000000, kVideoTrackNumber, 301); - EXPECT_TRUE(ValidateCues()); + EXPECT_TRUE(ValidateCues(segment_, &reader_)); } TEST_F(ParserTest, CuesTrackNumber) { @@ -435,7 +369,7 @@ TEST_F(ParserTest, CuesTrackNumber) { EXPECT_TRUE(cue_point == last_cue_point); CompareCuePointContents(track, cue_point, 6000000, 10, 269); - EXPECT_TRUE(ValidateCues()); + EXPECT_TRUE(ValidateCues(segment_, &reader_)); } TEST_F(ParserTest, Opus) { diff --git a/testing/test_util.cc b/testing/test_util.cc index 1a1b11e..18d772a 100644 --- a/testing/test_util.cc +++ b/testing/test_util.cc @@ -15,6 +15,10 @@ #include #include "common/libwebm_util.h" +#include "common/webmids.h" + +#include "mkvparser/mkvparser.h" +#include "mkvparser/mkvreader.h" namespace test { @@ -55,4 +59,91 @@ bool CompareFiles(const std::string& file1, const std::string& file2) { return std::feof(f1.get()) && std::feof(f2.get()); } +bool HasCuePoints(const mkvparser::Segment* segment, + std::int64_t* cues_offset) { + if (!segment || !cues_offset) { + return false; + } + using mkvparser::SeekHead; + const SeekHead* const seek_head = segment->GetSeekHead(); + if (!seek_head) { + return false; + } + + std::int64_t offset = 0; + for (int i = 0; i < seek_head->GetCount(); ++i) { + const SeekHead::Entry* const entry = seek_head->GetEntry(i); + // TODO(tomfinegan): Cues ID is really 0x1C53BB6B, aka kMkvCues, but + // mkvparser reads IDs as EBML unsigned ints in some cases, yielding magic + // numbers like the following. Investigate fixing this behavior. + if (entry->id == 0xC53BB6B) { // Cues ID as stored in Entry class. + offset = entry->pos; + } + } + + if (offset == -1) { + // No Cues found. + return false; + } + *cues_offset = offset; + return true; +} + +bool ValidateCues(mkvparser::Segment* segment, mkvparser::IMkvReader* reader) { + if (!segment) { + return false; + } + + std::int64_t cues_offset = 0; + if (!HasCuePoints(segment, &cues_offset)) { + // No cues to validate, everything is OK. + return true; + } + + // Parse Cues. + long long cues_pos = 0; // NOLINT + long cues_len = 0; // NOLINT + if (segment->ParseCues(cues_offset, cues_pos, cues_len)) { + return false; + } + + // Get a pointer to the video track if it exists. Otherwise, we assume + // that Cues are based on the first track (which is true for all our test + // files). + const mkvparser::Tracks* const tracks = segment->GetTracks(); + const mkvparser::Track* cues_track = tracks->GetTrackByIndex(0); + for (int i = 1; i < static_cast(tracks->GetTracksCount()); ++i) { + const mkvparser::Track* const track = tracks->GetTrackByIndex(i); + if (track->GetType() == mkvparser::Track::kVideo) { + cues_track = track; + break; + } + } + + // Iterate through Cues and verify if they are pointing to the correct + // Cluster position. + const mkvparser::Cues* const cues = segment->GetCues(); + const mkvparser::CuePoint* cue_point = NULL; + while (cues->LoadCuePoint()) { + if (!cue_point) { + cue_point = cues->GetFirst(); + } else { + cue_point = cues->GetNext(cue_point); + } + const mkvparser::CuePoint::TrackPosition* const track_position = + cue_point->Find(cues_track); + const long long cluster_pos = track_position->m_pos + // NOLINT + segment->m_start; + + // If a cluster does not begin at |cluster_pos|, then the file is + // incorrect. + long length; // NOLINT + const std::int64_t id = mkvparser::ReadID(reader, cluster_pos, length); + if (id != libwebm::kMkvCluster) { + return false; + } + } + return true; +} + } // namespace test \ No newline at end of file diff --git a/testing/test_util.h b/testing/test_util.h index 8bb007f..22ca274 100644 --- a/testing/test_util.h +++ b/testing/test_util.h @@ -13,6 +13,11 @@ #include #include +namespace mkvparser { +class IMkvReader; +class Segment; +} + namespace test { // constants for muxer and parser tests @@ -52,6 +57,12 @@ std::string GetTestFilePath(const std::string& name); // files match exactly, false otherwise. bool CompareFiles(const std::string& file1, const std::string& file2); +// Validates cue points. Assumes caller has already called Load() on |segment|. +// Returns true when: +// All cue points point at clusters, OR +// Data parsed by |segment| has no cue points. +bool ValidateCues(mkvparser::Segment* segment, mkvparser::IMkvReader* reader); + } // namespace test #endif // LIBWEBM_TESTING_TEST_UTIL_H_ \ No newline at end of file