parser_tests: Move cue validation to test_util.
And tidy it up a bit. Change-Id: I68e7f16ad2aa922fdb064802e8986a6955364c32
This commit is contained in:
parent
4b0690faa2
commit
ff8c2b6af7
@ -111,72 +111,6 @@ class ParserTest : public testing::Test {
|
|||||||
EXPECT_EQ(static_cast<long long>(pos), track_position->m_pos);
|
EXPECT_EQ(static_cast<long long>(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<int>(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:
|
protected:
|
||||||
MkvReader reader_;
|
MkvReader reader_;
|
||||||
bool is_reader_open_;
|
bool is_reader_open_;
|
||||||
@ -383,7 +317,7 @@ TEST_F(ParserTest, Cues) {
|
|||||||
EXPECT_TRUE(cue_point == last_cue_point);
|
EXPECT_TRUE(cue_point == last_cue_point);
|
||||||
CompareCuePointContents(track, cue_point, 4000000, kVideoTrackNumber, 269);
|
CompareCuePointContents(track, cue_point, 4000000, kVideoTrackNumber, 269);
|
||||||
|
|
||||||
EXPECT_TRUE(ValidateCues());
|
EXPECT_TRUE(ValidateCues(segment_, &reader_));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserTest, CuesBeforeClusters) {
|
TEST_F(ParserTest, CuesBeforeClusters) {
|
||||||
@ -409,7 +343,7 @@ TEST_F(ParserTest, CuesBeforeClusters) {
|
|||||||
EXPECT_TRUE(cue_point == last_cue_point);
|
EXPECT_TRUE(cue_point == last_cue_point);
|
||||||
CompareCuePointContents(track, cue_point, 6000000, kVideoTrackNumber, 301);
|
CompareCuePointContents(track, cue_point, 6000000, kVideoTrackNumber, 301);
|
||||||
|
|
||||||
EXPECT_TRUE(ValidateCues());
|
EXPECT_TRUE(ValidateCues(segment_, &reader_));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserTest, CuesTrackNumber) {
|
TEST_F(ParserTest, CuesTrackNumber) {
|
||||||
@ -435,7 +369,7 @@ TEST_F(ParserTest, CuesTrackNumber) {
|
|||||||
EXPECT_TRUE(cue_point == last_cue_point);
|
EXPECT_TRUE(cue_point == last_cue_point);
|
||||||
CompareCuePointContents(track, cue_point, 6000000, 10, 269);
|
CompareCuePointContents(track, cue_point, 6000000, 10, 269);
|
||||||
|
|
||||||
EXPECT_TRUE(ValidateCues());
|
EXPECT_TRUE(ValidateCues(segment_, &reader_));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserTest, Opus) {
|
TEST_F(ParserTest, Opus) {
|
||||||
|
@ -15,6 +15,10 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "common/libwebm_util.h"
|
#include "common/libwebm_util.h"
|
||||||
|
#include "common/webmids.h"
|
||||||
|
|
||||||
|
#include "mkvparser/mkvparser.h"
|
||||||
|
#include "mkvparser/mkvreader.h"
|
||||||
|
|
||||||
namespace test {
|
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());
|
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<int>(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
|
} // namespace test
|
@ -13,6 +13,11 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
namespace mkvparser {
|
||||||
|
class IMkvReader;
|
||||||
|
class Segment;
|
||||||
|
}
|
||||||
|
|
||||||
namespace test {
|
namespace test {
|
||||||
|
|
||||||
// constants for muxer and parser tests
|
// constants for muxer and parser tests
|
||||||
@ -52,6 +57,12 @@ std::string GetTestFilePath(const std::string& name);
|
|||||||
// files match exactly, false otherwise.
|
// files match exactly, false otherwise.
|
||||||
bool CompareFiles(const std::string& file1, const std::string& file2);
|
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
|
} // namespace test
|
||||||
|
|
||||||
#endif // LIBWEBM_TESTING_TEST_UTIL_H_
|
#endif // LIBWEBM_TESTING_TEST_UTIL_H_
|
Loading…
Reference in New Issue
Block a user