4 #include "../abstracttrack.h" 5 #include "../mp4/mp4container.h" 6 #include "../mp4/mp4ids.h" 7 #include "../mp4/mp4tag.h" 23 void OverallTests::checkMp4Testfile1()
26 const auto tracks = m_fileInfo.
tracks();
27 CPPUNIT_ASSERT_EQUAL(1_st, tracks.size());
28 for (
const auto &track : tracks) {
29 switch (track->id()) {
33 CPPUNIT_ASSERT_EQUAL(2012, track->creationTime().year());
34 CPPUNIT_ASSERT_EQUAL(44100u, track->samplingFrequency());
38 CPPUNIT_FAIL(
"unknown track ID");
41 const auto tags = m_fileInfo.
tags();
42 switch (m_tagStatus) {
44 CPPUNIT_ASSERT_EQUAL(1_st, tags.size());
45 CPPUNIT_ASSERT_EQUAL(
"Danse Macabre, Op.40"s, tags.front()->value(
KnownField::Title).toString());
46 CPPUNIT_ASSERT_EQUAL(
"Saint-Saƫns"s, tags.front()->value(
KnownField::Artist).toString());
47 CPPUNIT_ASSERT_EQUAL(
"Classical"s, tags.front()->value(
KnownField::Genre).toString());
49 "qaac 1.32, CoreAudioToolbox 7.9.7.3, AAC-LC Encoder, TVBR q63, Quality 96"s, tags.front()->value(
KnownField::Encoder).toString());
53 checkMp4TestMetaData();
56 CPPUNIT_ASSERT_EQUAL(0_st, tracks.size());
58 CPPUNIT_ASSERT(m_diag.
level() <= DiagLevel::Information);
64 void OverallTests::checkMp4Testfile2()
67 const auto tracks = m_fileInfo.
tracks();
68 CPPUNIT_ASSERT_EQUAL(5_st, tracks.size());
69 for (
const auto &track : tracks) {
70 switch (track->id()) {
75 CPPUNIT_ASSERT_EQUAL(4.0, track->version());
76 CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
77 CPPUNIT_ASSERT(track->pixelSize() ==
Size(1920, 750));
85 CPPUNIT_ASSERT_EQUAL(
"eng"s, track->language());
86 CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
87 CPPUNIT_ASSERT_EQUAL(48000u, track->samplingFrequency());
93 CPPUNIT_ASSERT_EQUAL(
"eng"s, track->language());
94 CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
98 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::DtsHd, track->format().general);
99 CPPUNIT_ASSERT_EQUAL(
"eng"s, track->language());
100 CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
103 CPPUNIT_ASSERT_EQUAL(MediaType::Text, track->mediaType());
104 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::TimedText, track->format().general);
105 CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
108 CPPUNIT_FAIL(
"unknown track ID");
111 const auto tags = m_fileInfo.
tags();
112 switch (m_tagStatus) {
114 CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
117 checkMp4TestMetaData();
120 CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
122 CPPUNIT_ASSERT(m_diag.
level() <= DiagLevel::Information);
128 void OverallTests::checkMp4Testfile3()
131 CPPUNIT_ASSERT(m_fileInfo.
container() !=
nullptr);
133 const auto tracks = m_fileInfo.
tracks();
134 CPPUNIT_ASSERT_EQUAL(1_st, tracks.size());
135 for (
const auto &track : tracks) {
136 switch (track->id()) {
141 CPPUNIT_ASSERT_EQUAL(3.1, track->version());
142 CPPUNIT_ASSERT_EQUAL(2014, track->creationTime().year());
143 CPPUNIT_ASSERT_EQUAL(
Size(854, 480), track->pixelSize());
144 CPPUNIT_ASSERT_EQUAL(
"YUV 4:2:0"s,
string(track->chromaFormat()));
147 CPPUNIT_FAIL(
"unknown track ID");
150 const auto tags = m_fileInfo.
tags();
151 switch (m_tagStatus) {
153 CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
156 checkMp4TestMetaData();
159 CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
162 for (
const auto &msg : m_diag) {
163 if (msg.level() != DiagLevel::Warning) {
167 CPPUNIT_FAIL(
"No warnings expected when putting tags before data.");
169 CPPUNIT_ASSERT_EQUAL(
"Sorry, but putting index/tags at the end is not possible when dealing with DASH files."s, msg.message());
172 CPPUNIT_ASSERT(m_diag.level() <= DiagLevel::Warning);
178 void OverallTests::checkMp4Testfile4()
181 CPPUNIT_ASSERT(m_fileInfo.
container() !=
nullptr);
183 const auto tracks = m_fileInfo.
tracks();
184 CPPUNIT_ASSERT_EQUAL(1_st, tracks.size());
185 for (
const auto &track : tracks) {
186 switch (track->id()) {
190 CPPUNIT_ASSERT_EQUAL(2008, track->creationTime().year());
191 CPPUNIT_ASSERT_EQUAL(static_cast<uint16>(2), track->channelCount());
192 CPPUNIT_ASSERT_EQUAL(static_cast<uint16>(16), track->bitsPerSample());
195 CPPUNIT_FAIL(
"unknown track ID");
198 const auto tags = m_fileInfo.
tags();
199 switch (m_tagStatus) {
201 CPPUNIT_ASSERT_EQUAL(1_st, tags.size());
202 CPPUNIT_ASSERT_EQUAL(
"Sad Song"s, tags.front()->value(
KnownField::Title).toString());
204 CPPUNIT_ASSERT_EQUAL(
"Don't Go Away (Apple Lossless)"s, tags.front()->value(
KnownField::Album).toString());
205 CPPUNIT_ASSERT_EQUAL(
"Alternative & Punk"s, tags.front()->value(
KnownField::Genre).toString());
206 CPPUNIT_ASSERT_EQUAL(
"iTunes v7.5.0.20"s, tags.front()->value(
KnownField::Encoder).toString());
207 CPPUNIT_ASSERT_EQUAL(
"1998"s, tags.front()->value(
KnownField::Year).toString());
209 CPPUNIT_ASSERT_EQUAL(0x58f3_st, tags.front()->value(
KnownField::Cover).dataSize());
210 CPPUNIT_ASSERT_EQUAL(0xFFD8FFE000104A46ul, BE::toUInt64(tags.front()->value(
KnownField::Cover).dataPointer()));
215 checkMp4TestMetaData();
218 CPPUNIT_ASSERT_EQUAL(0_st, tracks.size());
220 CPPUNIT_ASSERT(m_diag.level() <= DiagLevel::Information);
226 void OverallTests::checkMp4Testfile5()
229 CPPUNIT_ASSERT(m_fileInfo.
container() !=
nullptr);
231 const auto tracks = m_fileInfo.
tracks();
232 CPPUNIT_ASSERT_EQUAL(1_st, tracks.size());
233 for (
const auto &track : tracks) {
234 switch (track->id()) {
241 CPPUNIT_ASSERT_EQUAL(2014, track->creationTime().year());
242 CPPUNIT_ASSERT_EQUAL(static_cast<uint16>(2), track->channelCount());
245 CPPUNIT_ASSERT_EQUAL(24000u, track->samplingFrequency());
246 CPPUNIT_ASSERT_EQUAL(48000u, track->extensionSamplingFrequency());
247 CPPUNIT_ASSERT_EQUAL(static_cast<uint16>(16), track->bitsPerSample());
250 CPPUNIT_FAIL(
"unknown track ID");
253 const auto tags = m_fileInfo.
tags();
254 switch (m_tagStatus) {
256 CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
259 checkMp4TestMetaData();
262 CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
264 CPPUNIT_ASSERT(m_diag.level() <= DiagLevel::Information);
270 void OverallTests::checkMp4Testfile6()
273 const auto tracks = m_fileInfo.
tracks();
275 CPPUNIT_ASSERT_EQUAL(4_st, tracks.size());
277 CPPUNIT_ASSERT_EQUAL(6_st, tracks.size());
279 bool track2Present =
false, track5Present =
false;
280 for (
const auto &track : tracks) {
281 switch (track->id()) {
286 CPPUNIT_ASSERT_EQUAL(4.0, track->version());
287 CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
288 CPPUNIT_ASSERT_EQUAL(
Size(1920, 750), track->pixelSize());
291 CPPUNIT_ASSERT(track2Present = !track2Present);
297 CPPUNIT_ASSERT_EQUAL(
"ger"s, track->language());
298 CPPUNIT_ASSERT_EQUAL(
"test"s, track->name());
299 CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
300 CPPUNIT_ASSERT_EQUAL(48000u, track->samplingFrequency());
306 CPPUNIT_ASSERT_EQUAL(
"eng"s, track->language());
307 CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
311 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::DtsHd, track->format().general);
312 CPPUNIT_ASSERT_EQUAL(
"eng"s, track->language());
313 CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
316 CPPUNIT_ASSERT(track5Present = !track5Present);
319 CPPUNIT_ASSERT_EQUAL(2012, track->creationTime().year());
320 CPPUNIT_ASSERT_EQUAL(44100u, track->samplingFrequency());
322 CPPUNIT_ASSERT_EQUAL(
"new track"s, track->name());
325 CPPUNIT_ASSERT_EQUAL(MediaType::Text, track->mediaType());
326 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::TimedText, track->format().general);
327 CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
330 CPPUNIT_FAIL(
"unknown track ID");
334 CPPUNIT_ASSERT(!track2Present);
335 CPPUNIT_ASSERT(!track5Present);
337 CPPUNIT_ASSERT(track2Present);
338 CPPUNIT_ASSERT(track5Present);
341 CPPUNIT_ASSERT_EQUAL(0_st, m_fileInfo.
tags().size());
342 CPPUNIT_ASSERT(m_diag.level() <= DiagLevel::Information);
348 void OverallTests::checkMp4TestMetaData()
351 const auto tags = m_fileInfo.
tags();
353 CPPUNIT_ASSERT_EQUAL(1_st, tags.size());
354 CPPUNIT_ASSERT(tag !=
nullptr);
365 m_preservedMetaData.pop();
371 void OverallTests::checkMp4Constraints()
375 CPPUNIT_ASSERT(m_fileInfo.container());
378 CPPUNIT_ASSERT_EQUAL(4096_st, m_fileInfo.paddingSize());
380 CPPUNIT_ASSERT(m_fileInfo.paddingSize() >= 1024);
381 CPPUNIT_ASSERT(m_fileInfo.paddingSize() <= (4096 + 1024));
383 if (!(m_mode &
RemoveTagOrTrack) && (m_fileInfo.container()->documentType() !=
"dash")
385 const ElementPosition currentTagPos = m_fileInfo.container()->determineTagPosition(m_diag);
386 if (currentTagPos == ElementPosition::Keep) {
387 CPPUNIT_ASSERT_EQUAL(m_expectedTagPos, m_fileInfo.container()->determineIndexPosition(m_diag));
396 void OverallTests::setMp4TestMetaData()
418 void OverallTests::alterMp4Tracks()
420 m_additionalFileInfo.
setPath(TestUtilities::testFilePath(
"mtx-test-data/mp4/10-DanseMacabreOp.40.m4a"));
421 m_additionalFileInfo.
reopen(
true);
426 const auto &tracks = m_additionalFileInfo.
tracks();
427 CPPUNIT_ASSERT_EQUAL(1_st, tracks.size());
428 CPPUNIT_ASSERT_EQUAL(TrackType::Mp4Track, tracks[0]->type());
429 auto *track =
static_cast<Mp4Track *
>(tracks[0]);
430 CPPUNIT_ASSERT(static_cast<Mp4Container *>(m_additionalFileInfo.
container())->removeTrack(track));
431 CPPUNIT_ASSERT_EQUAL(0_st, m_additionalFileInfo.
trackCount());
434 CPPUNIT_ASSERT_EQUAL(5_st, container->trackCount());
436 CPPUNIT_ASSERT_EQUAL(6_st, container->trackCount());
437 auto &secondTrack = container->tracks()[1];
438 secondTrack->setLanguage(
"ger");
439 secondTrack->setName(
"test");
447 cerr << endl <<
"MP4 parser" << endl;
450 parseFile(TestUtilities::testFilePath(
"mtx-test-data/mp4/10-DanseMacabreOp.40.m4a"), &OverallTests::checkMp4Testfile1);
451 parseFile(TestUtilities::testFilePath(
"mtx-test-data/mp4/1080p-DTS-HD-7.1.mp4"), &OverallTests::checkMp4Testfile2);
452 parseFile(TestUtilities::testFilePath(
"mtx-test-data/mp4/dash/dragon-age-inquisition-H1LkM6IVlm4-video.mp4"), &OverallTests::checkMp4Testfile3);
453 parseFile(TestUtilities::testFilePath(
"mtx-test-data/alac/othertest-itunes.m4a"), &OverallTests::checkMp4Testfile4);
454 parseFile(TestUtilities::testFilePath(
"mtx-test-data/aac/he-aacv2-ps.m4a"), &OverallTests::checkMp4Testfile5);
462 void OverallTests::testMp4Making()
468 for (m_mode = 0; m_mode != 0x20; ++m_mode) {
475 m_fileInfo.setTagPosition(ElementPosition::Keep);
477 m_fileInfo.setTagPosition(m_mode &
TagsBeforeData ? ElementPosition::BeforeData : ElementPosition::AfterData);
479 m_fileInfo.setIndexPosition(m_fileInfo.tagPosition());
482 m_fileInfo.setMaxPadding(m_mode &
PaddingConstraints ? (4096 + 1024) : numeric_limits<size_t>::max());
483 m_fileInfo.setForceTagPosition(m_mode &
ForceTagPos);
484 m_fileInfo.setForceIndexPosition(m_mode &
ForceTagPos);
487 list<string> testConditions;
489 testConditions.emplace_back(
"forcing rewrite");
493 testConditions.emplace_back(
"removing tag");
495 testConditions.emplace_back(
"keeping tag position");
498 testConditions.emplace_back(
"tags before data");
500 testConditions.emplace_back(
"tags after data");
503 testConditions.emplace_back(
"padding constraints");
506 testConditions.emplace_back(
"forcing tag position");
508 cerr << endl <<
"MP4 maker - testmode " << m_mode <<
": " << joinStrings(testConditions,
", ") << endl;
513 void (
OverallTests::*modifyRoutine)(void) = (m_mode &
RemoveTagOrTrack) ? &OverallTests::removeAllTags : &OverallTests::setMp4TestMetaData;
514 makeFile(TestUtilities::workingCopyPath(
"mtx-test-data/mp4/10-DanseMacabreOp.40.m4a"), modifyRoutine, &OverallTests::checkMp4Testfile1);
515 makeFile(TestUtilities::workingCopyPath(
"mtx-test-data/mp4/1080p-DTS-HD-7.1.mp4"), modifyRoutine, &OverallTests::checkMp4Testfile2);
516 makeFile(TestUtilities::workingCopyPath(
"mtx-test-data/mp4/dash/dragon-age-inquisition-H1LkM6IVlm4-video.mp4"), modifyRoutine,
517 &OverallTests::checkMp4Testfile3);
518 makeFile(TestUtilities::workingCopyPath(
"mtx-test-data/alac/othertest-itunes.m4a"), modifyRoutine, &OverallTests::checkMp4Testfile4);
519 makeFile(TestUtilities::workingCopyPath(
"mtx-test-data/aac/he-aacv2-ps.m4a"), modifyRoutine, &OverallTests::checkMp4Testfile5);
521 modifyRoutine = (m_mode &
RemoveTagOrTrack) ? &OverallTests::removeSecondTrack : &OverallTests::alterMp4Tracks;
522 m_fileInfo.setTagPosition(ElementPosition::Keep);
523 makeFile(TestUtilities::workingCopyPath(
"mtx-test-data/mp4/1080p-DTS-HD-7.1.mp4"), modifyRoutine, &OverallTests::checkMp4Testfile6);
void setPath(const std::string &path)
Sets the current file.
Implementation of TagParser::Tag for the MP4 container.
The Tag class is used to store, read and write tag information.
const std::string & documentType() const
Returns a string that describes the document type if available; otherwise returns an empty string...
The PositionInSet class describes the position of an element in a set which consists of a certain num...
Implementation of GenericContainer<MediaFileInfo, Mp4Tag, Mp4Track, Mp4Atom>.
bool addTrack(TrackType *track)
Adds the specified track to the container.
virtual bool setValue(KnownField field, const TagValue &value)=0
Assigns the given value to the specified field.
virtual Tag * createTag(const TagTarget &target=TagTarget())
Creates and returns a tag for the specified target.
Implementation of TagParser::AbstractTrack for the MP4 container.
The Size class defines the size of a two-dimensional object using integer point precision.
DiagLevel level() const
Returns the worst diag level present in the container.
The OverallTests class tests reading and writing tags and parsing technical information for all suppo...
void reopen(bool readonly=false)
Opens a std::fstream for the current file.
void setName(const std::string &name)
Sets the name.
void testMp4Parsing()
Tests the MP4 parser via MediaFileInfo.
std::string toString(TagTextEncoding encoding=TagTextEncoding::Unspecified) const
Converts the value of the current TagValue object to its equivalent std::string representation.
virtual const TagValue & value(KnownField field) const =0
Returns the value of the specified field.
const TagValue & value(KnownField value) const override
Returns the value of the specified field.