Test parsing and rewriting nested Mkv tags

This commit is contained in:
Martchus 2017-05-19 00:05:57 +02:00
parent 23e84886d4
commit ee15e08dd9
4 changed files with 195 additions and 4 deletions

29
matroska/matroskatags.dtd Normal file
View File

@ -0,0 +1,29 @@
<!ELEMENT Tags (Tag*)>
<!ELEMENT Tag (
Targets,
Simple*)>
<!ELEMENT Targets (
TrackUID*,
ChapterUID*,
AttachmentUID*,
EditionUID*,
TargetType?,
TargetTypeValue?)>
<!ELEMENT TrackUID (#PCDATA)>
<!ELEMENT ChapterUID (#PCDATA)>
<!ELEMENT AttachmentUID (#PCDATA)>
<!ELEMENT EditionUID (#PCDATA)>
<!ELEMENT TargetType (#PCDATA)>
<!ELEMENT TargetTypeValue (#PCDATA)>
<!ELEMENT Simple (
Name,
String?,
Binary?,
TagLanguage?,
DefaultLanguage?,
Simple*)>
<!ELEMENT TagLanguage (#PCDATA)>
<!ELEMENT DefaultLanguage (#PCDATA)>

View File

@ -0,0 +1,46 @@
<?xml version="1.0"?>
<!-- <!DOCTYPE Tags SYSTEM "matroskatags.dtd"> -->
<Tags>
<Tag>
<Simple>
<Name>TITLE</Name>
<String>Vanilla Sky</String>
<TagLanguage>und</TagLanguage>
</Simple>
<Simple>
<Name>ARTIST</Name>
<String>Test artist</String>
<TagLanguage>und</TagLanguage>
<Simple>
<Name>ADDRESS</Name>
<String>Test address</String>
<TagLanguage>und</TagLanguage>
</Simple>
</Simple>
<Targets>
<TargetTypeValue>50</TargetTypeValue>
</Targets>
</Tag>
<Tag>
<Simple>
<Name>TITLE</Name>
<String>Main video track</String>
<TagLanguage>und</TagLanguage>
</Simple>
<Targets>
<TrackUID>3164620769</TrackUID>
<TargetTypeValue>50</TargetTypeValue>
</Targets>
</Tag>
<Tag>
<Simple>
<Name>TITLE</Name>
<String>English audio track</String>
<TagLanguage>und</TagLanguage>
</Simple>
<Targets>
<TrackUID>3571773145</TrackUID>
<TargetTypeValue>50</TargetTypeValue>
</Targets>
</Tag>
</Tags>

View File

@ -25,6 +25,7 @@
using namespace std;
using namespace ConversionUtilities;
using namespace TestUtilities;
using namespace Media;
using namespace CPPUNIT_NS;
@ -53,7 +54,8 @@ class OverallTests : public TestFixture
CPPUNIT_TEST(testMp3Making);
CPPUNIT_TEST(testOggMaking);
CPPUNIT_TEST(testFlacMaking);
CPPUNIT_TEST(testMkvMaking);
CPPUNIT_TEST(testMkvMakingWithDifferentSettings);
CPPUNIT_TEST(testMkvMakingNestedTags);
#endif
CPPUNIT_TEST_SUITE_END();
@ -61,6 +63,7 @@ public:
void setUp();
void tearDown();
private:
void parseFile(const string &path, void (OverallTests::* checkRoutine)(void));
void makeFile(const string &path, void (OverallTests::* modifyRoutine)(void), void (OverallTests::* checkRoutine)(void));
@ -73,6 +76,7 @@ public:
void checkMkvTestfile7();
void checkMkvTestfile8();
void checkMkvTestfileHandbrakeChapters();
void checkMkvTestfileNestedTags();
void checkMkvTestMetaData();
void checkMkvPaddingConstraints();
@ -100,14 +104,18 @@ public:
void setMp3TestMetaData();
void setOggTestMetaData();
void removeAllTags();
void noop();
void createMkvWithNestedTags();
public:
void testMkvParsing();
void testMp4Parsing();
void testMp3Parsing();
void testOggParsing();
void testFlacParsing();
#ifdef PLATFORM_UNIX
void testMkvMaking();
void testMkvMakingWithDifferentSettings();
void testMkvMakingNestedTags();
void testMp4Making();
void testMp3Making();
void testOggMaking();
@ -123,6 +131,7 @@ private:
TagValue m_testTotalParts;
TagValue m_testPosition;
queue<TagValue> m_preservedMetaData;
string m_nestedTagsMkvPath;
TagStatus m_tagStatus;
uint16 m_mode;
};
@ -143,7 +152,11 @@ void OverallTests::setUp()
}
void OverallTests::tearDown()
{}
{
if(!m_nestedTagsMkvPath.empty()) {
remove(m_nestedTagsMkvPath.data());
}
}
/*!
* \brief Parses the specified file and tests the results using the specified check routine.
@ -595,6 +608,42 @@ void OverallTests::checkMkvTestfileHandbrakeChapters()
}
}
/*!
* \brief Checks "mtx-test-data/mkv/nested-tags.mkv" ("mtx-test-data/mkv/tags.mkv" where "mkv/nested-tags.xml" has been applied).
*/
void OverallTests::checkMkvTestfileNestedTags()
{
CPPUNIT_ASSERT(m_fileInfo.containerFormat() == ContainerFormat::Matroska);
const auto tags = m_fileInfo.tags();
bool generalTagFound = false;
switch(m_tagStatus) {
case TagStatus::Original:
case TagStatus::TestMetaDataPresent:
CPPUNIT_ASSERT_EQUAL(5ul, tags.size());
for(const Tag *tag : tags) {
CPPUNIT_ASSERT(tag->type() == TagType::MatroskaTag);
const auto *mkvTag = static_cast<const MatroskaTag *>(tag);
const auto &target = mkvTag->target();
if(target.level() == 50 && target.tracks().empty()) {
generalTagFound = true;
CPPUNIT_ASSERT_EQUAL("Vanilla Sky"s, tag->value(KnownField::Title).toString());
const auto &fields = mkvTag->fields();
const auto &artistField = fields.find(mkvTag->fieldId(KnownField::Artist));
CPPUNIT_ASSERT(artistField != fields.end());
CPPUNIT_ASSERT_EQUAL("Test artist"s, artistField->second.value().toString());
const auto &nestedFields = artistField->second.nestedFields();
CPPUNIT_ASSERT_EQUAL(1ul, nestedFields.size());
CPPUNIT_ASSERT_EQUAL("ADDRESS"s, nestedFields[0].idToString());
CPPUNIT_ASSERT_EQUAL("Test address"s, nestedFields[0].value().toString());
}
}
CPPUNIT_ASSERT(generalTagFound);
break;
case TagStatus::Removed:
CPPUNIT_ASSERT(tags.size() == 0);
}
}
/*!
* \brief Checks whether test meta data for Matroska files has been applied correctly.
*/
@ -1298,6 +1347,47 @@ void OverallTests::removeAllTags()
m_fileInfo.removeAllTags();
}
/*!
* \brief Does nothing.
* \remarks Used to just resave the file.
*/
void OverallTests::noop()
{
}
/*!
* \brief Creates a Matroska test file with nested tags from "mtx-test-data/mkv/nested-tags.mkv" using "mkv/nested-tags.xml".
* \remarks Requires mkvmerge.
* \todo Make mkvmerge path variable.
*/
void OverallTests::createMkvWithNestedTags()
{
#ifdef PLATFORM_UNIX
m_nestedTagsMkvPath = workingCopyPathMode("mtx-test-data/mkv/nested-tags.mkv", WorkingCopyMode::NoCopy);
remove(m_nestedTagsMkvPath.data());
cerr << "\n\ncreating testfile \"" << m_nestedTagsMkvPath << "\" with mkvmerge" << endl;
const string tagsMkvPath(testFilePath("mtx-test-data/mkv/tags.mkv"));
const string tagsXmlPath(testFilePath("mkv/nested-tags.xml"));
const char *const mkvmergeArgs[] = {
"--ui-language en_US",
"--output", m_nestedTagsMkvPath.data(),
"--no-global-tags", "--language", "0:und", "--default-track", "0:yes", "--language", "1:und", "--default-track", "1:yes",
"(", tagsMkvPath.data(), ")",
"--global-tags", tagsXmlPath.data(), "--track-order", "0:0,0:1", nullptr
};
string mkvmergeOutput, mkvmergeErrors;
int res = execHelperApp("/bin/mkvmerge", mkvmergeArgs, mkvmergeOutput, mkvmergeErrors);
cout << mkvmergeOutput << endl;
cerr << mkvmergeErrors << endl;
if(res) {
cerr << "Failure (exit code " << res << "); unable to test nested tags" << endl;
remove(m_nestedTagsMkvPath.data());
m_nestedTagsMkvPath.clear();
}
#endif
}
/*!
* \brief Tests the Matroska parser via MediaFileInfo.
*/
@ -1315,14 +1405,21 @@ void OverallTests::testMkvParsing()
parseFile(TestUtilities::testFilePath("matroska_wave1/test7.mkv"), &OverallTests::checkMkvTestfile7);
parseFile(TestUtilities::testFilePath("matroska_wave1/test8.mkv"), &OverallTests::checkMkvTestfile8);
parseFile(TestUtilities::testFilePath("mtx-test-data/mkv/handbrake-chapters-2.mkv"), &OverallTests::checkMkvTestfileHandbrakeChapters);
createMkvWithNestedTags();
if(!m_nestedTagsMkvPath.empty()) {
parseFile(m_nestedTagsMkvPath, &OverallTests::checkMkvTestfileNestedTags);
}
}
#ifdef PLATFORM_UNIX
/*!
* \brief Tests the Matroska maker via MediaFileInfo.
*
* This method tests various combinations of the possible settings.
*
* \remarks Relies on the parser to check results.
*/
void OverallTests::testMkvMaking()
void OverallTests::testMkvMakingWithDifferentSettings()
{
// full parse is required to determine padding
m_fileInfo.setForceFullParse(true);
@ -1399,6 +1496,23 @@ void OverallTests::testMkvMaking()
makeFile(TestUtilities::workingCopyPath("mtx-test-data/mkv/handbrake-chapters-2.mkv"), modifyRoutine, &OverallTests::checkMkvTestfileHandbrakeChapters);
}
}
/*!
* \brief Tests making a Matroska file with nested tags via MediaFileInfo.
* \remarks Relies on the parser to check results.
*/
void OverallTests::testMkvMakingNestedTags()
{
createMkvWithNestedTags();
if(!m_nestedTagsMkvPath.empty()) {
cerr << endl << "Matroska maker - rewrite file with nested tags" << endl;
m_fileInfo.setMinPadding(0);
m_fileInfo.setMaxPadding(0);
m_fileInfo.setTagPosition(ElementPosition::BeforeData);
m_fileInfo.setIndexPosition(ElementPosition::BeforeData);
makeFile(m_nestedTagsMkvPath, &OverallTests::noop, &OverallTests::checkMkvTestfileNestedTags);
}
}
#endif
/*!

View File

@ -70,6 +70,8 @@ struct TestFile
{"matroska_wave1/test7.mkv", {"95b21c92ad5a4fe00914ff5009e2a64f12fd4c5fb9cb1c3c888ab50bf0ffe483"}},
{"matroska_wave1/test8.mkv", {"9dddcd1550b814dae44d62e2b9f27c0eca31d5e190df2220cbf7492e3d6c63da"}},
{"mtx-test-data/mkv/handbrake-chapters-2.mkv", {"eccc55f3b59a77086b3ffb914525d312c7886eae34e3933352dea2f6f6a1974c"}},
{"mtx-test-data/mkv/tags.mkv", {"4330019afc3d846600c1ded38158fcac081297f4e56c749251c236f4871e0287"}},
{"mkv/nested-tags.xml", {"85cfcc94920f114e52fd1aa3df24706cd2710626e065a2c8c55dd209ec8dc8ce"}},
{"mp4/test1.m4a", {"4f16e0a22525bd13ba859431406d7f5991e0b4f155c51e10e5f32b0c97034b36"}},
{"mtx-test-data/aac/he-aacv2-ps.m4a", {"be54be0ae45b0184583ced8a84a881a1652a449feb7f6a917e11f60efabb68ac"}},
{"mtx-test-data/alac/othertest-itunes.m4a", {"5e9c64cde00902211533fbe38aaa67ef5f79a945e1d717951b78b4bbf9ff84e8"}},