10#include <c++utilities/application/commandlineutils.h>
14#include "resources/config.h"
32void OverallTests::checkMp4Testfile1()
34 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Mp4, m_fileInfo.
containerFormat());
35 const auto tracks = m_fileInfo.
tracks();
36 CPPUNIT_ASSERT_EQUAL(1_st, tracks.size());
37 for (
const auto &track : tracks) {
38 switch (track->id()) {
40 CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
41 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Aac, track->format().general);
42 CPPUNIT_ASSERT_EQUAL(2012, track->creationTime().year());
43 CPPUNIT_ASSERT_EQUAL(44100u, track->samplingFrequency());
47 CPPUNIT_FAIL(
"unknown track ID");
50 const auto tags = m_fileInfo.
tags();
51 switch (m_tagStatus) {
53 CPPUNIT_ASSERT_EQUAL(1_st, tags.size());
54 CPPUNIT_ASSERT_EQUAL(
"Danse Macabre, Op.40"s, tags.front()->value(KnownField::Title).toString());
55 CPPUNIT_ASSERT_EQUAL(
"Saint-Saƫns"s, tags.front()->value(KnownField::Artist).toString());
56 CPPUNIT_ASSERT_EQUAL(
"Classical"s, tags.front()->value(KnownField::Genre).toString());
58 "qaac 1.32, CoreAudioToolbox 7.9.7.3, AAC-LC Encoder, TVBR q63, Quality 96"s, tags.front()->value(KnownField::Encoder).toString());
59 CPPUNIT_ASSERT_EQUAL(10, tags.front()->value(KnownField::TrackPosition).toPositionInSet().position());
62 checkMp4TestMetaData();
65 CPPUNIT_ASSERT_EQUAL(0_st, tracks.size());
67 CPPUNIT_ASSERT(m_diag.
level() <= DiagLevel::Information);
73void OverallTests::checkMp4Testfile2()
75 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Mp4, m_fileInfo.
containerFormat());
76 const auto tracks = m_fileInfo.
tracks();
77 CPPUNIT_ASSERT_EQUAL(5_st, tracks.size());
78 for (
const auto &track : tracks) {
79 switch (track->id()) {
81 CPPUNIT_ASSERT_EQUAL(MediaType::Video, track->mediaType());
82 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Avc, track->format().general);
84 CPPUNIT_ASSERT_EQUAL(4.0, track->version());
85 CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
86 CPPUNIT_ASSERT(track->pixelSize() ==
Size(1920, 750));
89 CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
90 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Aac, track->format().general);
94 CPPUNIT_ASSERT_EQUAL(
Locale(
"eng"sv, LocaleFormat::ISO_639_2_T), track->locale());
95 CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
96 CPPUNIT_ASSERT_EQUAL(48000u, track->samplingFrequency());
100 CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
101 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Ac3, track->format().general);
102 CPPUNIT_ASSERT_EQUAL(
Locale(
"eng"sv, LocaleFormat::ISO_639_2_T), track->locale());
103 CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
106 CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
107 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::DtsHd, track->format().general);
108 CPPUNIT_ASSERT_EQUAL(
Locale(
"eng"sv, LocaleFormat::ISO_639_2_T), track->locale());
109 CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
112 CPPUNIT_ASSERT_EQUAL(MediaType::Text, track->mediaType());
113 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::TimedText, track->format().general);
114 CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
117 CPPUNIT_FAIL(
"unknown track ID");
120 const auto tags = m_fileInfo.
tags();
121 switch (m_tagStatus) {
123 CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
126 checkMp4TestMetaData();
129 CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
131 CPPUNIT_ASSERT(m_diag.
level() <= DiagLevel::Information);
137void OverallTests::checkMp4Testfile3()
139 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Mp4, m_fileInfo.
containerFormat());
140 CPPUNIT_ASSERT(m_fileInfo.
container() !=
nullptr);
142 const auto tracks = m_fileInfo.
tracks();
143 CPPUNIT_ASSERT_EQUAL(1_st, tracks.size());
144 for (
const auto &track : tracks) {
145 switch (track->id()) {
147 CPPUNIT_ASSERT_EQUAL(MediaType::Video, track->mediaType());
148 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Avc, track->format().general);
150 CPPUNIT_ASSERT_EQUAL(3.1, track->version());
151 CPPUNIT_ASSERT_EQUAL(2014, track->creationTime().year());
152 CPPUNIT_ASSERT_EQUAL(
Size(854, 480), track->pixelSize());
153 CPPUNIT_ASSERT_EQUAL(
"YUV 4:2:0"s,
string(track->chromaFormat()));
156 CPPUNIT_FAIL(
"unknown track ID");
159 const auto tags = m_fileInfo.
tags();
160 switch (m_tagStatus) {
162 CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
165 checkMp4TestMetaData();
168 CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
171 for (
const auto &msg : m_diag) {
172 if (msg.level() != DiagLevel::Warning) {
176 CPPUNIT_FAIL(
"No warnings expected when putting tags before data.");
178 CPPUNIT_ASSERT_EQUAL(
"Sorry, but putting index/tags at the end is not possible when dealing with DASH files."s, msg.message());
181 CPPUNIT_ASSERT(m_diag.level() <= DiagLevel::Warning);
187void OverallTests::checkMp4Testfile4()
189 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Mp4, m_fileInfo.
containerFormat());
190 CPPUNIT_ASSERT(m_fileInfo.
container() !=
nullptr);
192 const auto tracks = m_fileInfo.
tracks();
193 CPPUNIT_ASSERT_EQUAL(1_st, tracks.size());
194 for (
const auto &track : tracks) {
195 switch (track->id()) {
197 CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
198 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Alac, track->format().general);
199 CPPUNIT_ASSERT_EQUAL(2008, track->creationTime().year());
200 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint16_t
>(2), track->channelCount());
201 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint16_t
>(16), track->bitsPerSample());
204 CPPUNIT_FAIL(
"unknown track ID");
207 const auto tags = m_fileInfo.
tags();
208 switch (m_tagStatus) {
210 CPPUNIT_ASSERT_EQUAL(1_st, tags.size());
211 CPPUNIT_ASSERT_EQUAL(
"Sad Song"s, tags.front()->value(KnownField::Title).toString());
212 CPPUNIT_ASSERT_EQUAL(
"Oasis"s, tags.front()->value(KnownField::Artist).toString());
213 CPPUNIT_ASSERT_EQUAL(
"Don't Go Away (Apple Lossless)"s, tags.front()->value(KnownField::Album).toString());
214 CPPUNIT_ASSERT_EQUAL(
"Alternative & Punk"s, tags.front()->value(KnownField::Genre).toString());
215 CPPUNIT_ASSERT_EQUAL(
"iTunes v7.5.0.20"s, tags.front()->value(KnownField::Encoder).toString());
216 CPPUNIT_ASSERT_EQUAL(
"1998"s, tags.front()->value(KnownField::RecordDate).toString());
217 CPPUNIT_ASSERT(tags.front()->value(KnownField::Comment).isEmpty());
218 CPPUNIT_ASSERT_EQUAL(0x58f3_st, tags.front()->value(KnownField::Cover).dataSize());
219 CPPUNIT_ASSERT_EQUAL(0xFFD8FFE000104A46ul, BE::toInt<std::uint64_t>(tags.front()->value(KnownField::Cover).dataPointer()));
220 CPPUNIT_ASSERT_EQUAL(
PositionInSet(3, 4), tags.front()->value(KnownField::TrackPosition).toPositionInSet());
221 CPPUNIT_ASSERT_EQUAL(
PositionInSet(1, 1), tags.front()->value(KnownField::DiskPosition).toPositionInSet());
224 checkMp4TestMetaData();
227 CPPUNIT_ASSERT_EQUAL(0_st, tracks.size());
229 CPPUNIT_ASSERT(m_diag.level() <= DiagLevel::Information);
235void OverallTests::checkMp4Testfile5()
237 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Mp4, m_fileInfo.
containerFormat());
238 CPPUNIT_ASSERT(m_fileInfo.
container() !=
nullptr);
240 const auto tracks = m_fileInfo.
tracks();
241 CPPUNIT_ASSERT_EQUAL(1_st, tracks.size());
242 for (
const auto &track : tracks) {
243 switch (track->id()) {
245 CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
246 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Aac, track->format().general);
250 CPPUNIT_ASSERT_EQUAL(2014, track->creationTime().year());
251 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint16_t
>(2), track->channelCount());
254 CPPUNIT_ASSERT_EQUAL(24000u, track->samplingFrequency());
255 CPPUNIT_ASSERT_EQUAL(48000u, track->extensionSamplingFrequency());
256 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint16_t
>(16), track->bitsPerSample());
259 CPPUNIT_FAIL(
"unknown track ID");
262 const auto tags = m_fileInfo.
tags();
263 switch (m_tagStatus) {
265 CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
268 checkMp4TestMetaData();
271 CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
273 CPPUNIT_ASSERT(m_diag.level() <= DiagLevel::Information);
279void OverallTests::checkMp4Testfile6()
281 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Mp4, m_fileInfo.
containerFormat());
282 const auto tracks = m_fileInfo.
tracks();
284 CPPUNIT_ASSERT_EQUAL(4_st, tracks.size());
286 CPPUNIT_ASSERT_EQUAL(6_st, tracks.size());
288 bool track2Present =
false, track5Present =
false;
289 for (
const auto &track : tracks) {
290 switch (track->id()) {
292 CPPUNIT_ASSERT_EQUAL(MediaType::Video, track->mediaType());
293 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Avc, track->format().general);
295 CPPUNIT_ASSERT_EQUAL(4.0, track->version());
296 CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
297 CPPUNIT_ASSERT_EQUAL(
Size(1920, 750), track->pixelSize());
300 CPPUNIT_ASSERT(track2Present = !track2Present);
301 CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
302 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Aac, track->format().general);
306 CPPUNIT_ASSERT_EQUAL(
Locale(
"ger"sv, LocaleFormat::ISO_639_2_T), track->locale());
307 CPPUNIT_ASSERT_EQUAL(
"test"s, track->name());
308 CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
309 CPPUNIT_ASSERT_EQUAL(48000u, track->samplingFrequency());
313 CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
314 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Ac3, track->format().general);
315 CPPUNIT_ASSERT_EQUAL(
Locale(
"eng"sv, LocaleFormat::ISO_639_2_T), track->locale());
316 CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
319 CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
320 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::DtsHd, track->format().general);
321 CPPUNIT_ASSERT_EQUAL(
Locale(
"eng"sv, LocaleFormat::ISO_639_2_T), track->locale());
322 CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
325 CPPUNIT_ASSERT(track5Present = !track5Present);
326 CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
327 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Aac, track->format().general);
328 CPPUNIT_ASSERT_EQUAL(2012, track->creationTime().year());
329 CPPUNIT_ASSERT_EQUAL(44100u, track->samplingFrequency());
331 CPPUNIT_ASSERT_EQUAL(
"new track"s, track->name());
334 CPPUNIT_ASSERT_EQUAL(MediaType::Text, track->mediaType());
335 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::TimedText, track->format().general);
336 CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
339 CPPUNIT_FAIL(
"unknown track ID");
343 CPPUNIT_ASSERT(!track2Present);
344 CPPUNIT_ASSERT(!track5Present);
346 CPPUNIT_ASSERT(track2Present);
347 CPPUNIT_ASSERT(track5Present);
350 CPPUNIT_ASSERT_EQUAL(0_st, m_fileInfo.
tags().size());
351 CPPUNIT_ASSERT(m_diag.level() <= DiagLevel::Information);
357void OverallTests::checkMp4Testfile7()
359 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Mp4, m_fileInfo.
containerFormat());
360 CPPUNIT_ASSERT(m_fileInfo.
container() !=
nullptr);
362 const auto tracks = m_fileInfo.
tracks();
363 CPPUNIT_ASSERT_EQUAL(3_st, tracks.size());
364 for (
const auto &track : tracks) {
365 switch (track->id()) {
367 CPPUNIT_ASSERT_EQUAL(
"VideoHandle"s, track->name());
368 CPPUNIT_ASSERT_EQUAL(MediaType::Video, track->mediaType());
369 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Avc, track->format().general);
371 CPPUNIT_ASSERT_EQUAL(
static_cast<unsigned char>(0), track->format().extension);
372 CPPUNIT_ASSERT_EQUAL(4.0, track->version());
373 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint16_t
>(0), track->channelCount());
374 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint8_t
>(0), track->channelConfig());
375 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint8_t
>(0), track->extensionChannelConfig());
376 CPPUNIT_ASSERT_EQUAL(0u, track->samplingFrequency());
377 CPPUNIT_ASSERT_EQUAL(0u, track->extensionSamplingFrequency());
378 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint16_t
>(24), track->depth());
379 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint64_t
>(51), track->sampleCount());
380 CPPUNIT_ASSERT_EQUAL(1920u, track->pixelSize().width());
381 CPPUNIT_ASSERT_EQUAL(1080u, track->pixelSize().height());
382 CPPUNIT_ASSERT_EQUAL(72u, track->resolution().width());
383 CPPUNIT_ASSERT_EQUAL(72u, track->resolution().height());
384 CPPUNIT_ASSERT_EQUAL(DateTime::fromDateAndTime(2018, 7, 8, 20, 3, 52), track->creationTime());
385 CPPUNIT_ASSERT_EQUAL(DateTime::fromDateAndTime(2018, 7, 8, 20, 3, 52), track->modificationTime());
386 CPPUNIT_ASSERT_EQUAL(
"YUV 4:2:0"s,
string(track->chromaFormat()));
387 CPPUNIT_ASSERT_EQUAL(1, track->duration().seconds());
390 CPPUNIT_ASSERT_EQUAL(
"SoundHandle"s, track->name());
391 CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
392 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Aac, track->format().general);
394 CPPUNIT_ASSERT_EQUAL(
static_cast<unsigned char>(0), track->format().extension);
395 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint16_t
>(2), track->channelCount());
397 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint8_t
>(0), track->extensionChannelConfig());
398 CPPUNIT_ASSERT_EQUAL(48000u, track->samplingFrequency());
399 CPPUNIT_ASSERT_EQUAL(0u, track->extensionSamplingFrequency());
400 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint16_t
>(16), track->bitsPerSample());
401 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint64_t
>(76), track->sampleCount());
402 CPPUNIT_ASSERT_EQUAL(DateTime::fromDateAndTime(2018, 7, 8, 20, 3, 52), track->creationTime());
403 CPPUNIT_ASSERT_EQUAL(DateTime::fromDateAndTime(2018, 7, 8, 20, 3, 52), track->modificationTime());
404 CPPUNIT_ASSERT_EQUAL(1, track->duration().seconds());
405 CPPUNIT_ASSERT_EQUAL(256.0, track->bitrate());
408 CPPUNIT_ASSERT_EQUAL(
"MetaHandler"s, track->name());
409 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Unknown, track->format().general);
410 CPPUNIT_ASSERT_EQUAL(
"urim"s, track->formatId());
413 CPPUNIT_FAIL(
"unknown track ID");
416 const auto tags = m_fileInfo.
tags();
417 switch (m_tagStatus) {
419 CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
422 checkMp4TestMetaData();
425 CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
427 CPPUNIT_ASSERT(m_diag.level() <= DiagLevel::Information);
433void OverallTests::checkMp4TestMetaData()
436 const auto tags = m_fileInfo.
tags();
438 CPPUNIT_ASSERT_EQUAL(1_st, tags.size());
439 CPPUNIT_ASSERT(tag !=
nullptr);
442 CPPUNIT_ASSERT_EQUAL(m_testTitle, tag->
value(KnownField::Title));
444 CPPUNIT_ASSERT_EQUAL(m_testAlbum, tag->
value(KnownField::Album));
445 CPPUNIT_ASSERT_EQUAL(m_preservedMetaData.front(), tag->
value(KnownField::Artist));
446 CPPUNIT_ASSERT_EQUAL(m_testPosition, tag->
value(KnownField::TrackPosition));
447 CPPUNIT_ASSERT_EQUAL(m_testPosition, tag->
value(KnownField::DiskPosition));
450 m_preservedMetaData.pop();
456void OverallTests::checkMp4Constraints()
461 if (m_mode & PaddingConstraints) {
462 if (m_mode & ForceRewring) {
463 CPPUNIT_ASSERT_EQUAL(
static_cast<std::uint64_t
>(4096), m_fileInfo.
paddingSize());
466 CPPUNIT_ASSERT(m_fileInfo.
paddingSize() <= (4096 + 1024));
469 && ((m_mode & ForceRewring) || (m_mode & ForceTagPos))) {
471 if (currentTagPos == ElementPosition::Keep) {
481void OverallTests::setMp4TestMetaData()
487 tag->
setValue(KnownField::Title, m_testTitle);
488 tag->
setValue(KnownField::Comment, m_testComment);
489 tag->
setValue(KnownField::Album, m_testAlbum);
490 m_preservedMetaData.push(tag->
value(KnownField::Artist));
491 tag->
setValue(KnownField::TrackPosition, m_testPosition);
492 tag->
setValue(KnownField::DiskPosition, m_testPosition);
503void OverallTests::alterMp4Tracks()
505 m_additionalFileInfo.
setPath(testFilePath(
"mtx-test-data/mp4/10-DanseMacabreOp.40.m4a"));
506 m_additionalFileInfo.
reopen(
true);
508 m_additionalFileInfo.
parseTracks(m_diag, m_progress);
509 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Mp4, m_additionalFileInfo.
containerFormat());
510 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Mp4, m_fileInfo.
containerFormat());
511 const auto &tracks = m_additionalFileInfo.
tracks();
512 CPPUNIT_ASSERT_EQUAL(1_st, tracks.size());
513 CPPUNIT_ASSERT_EQUAL(TrackType::Mp4Track, tracks[0]->type());
514 auto *track =
static_cast<Mp4Track *
>(tracks[0]);
516 CPPUNIT_ASSERT_EQUAL(0_st, m_additionalFileInfo.
trackCount());
517 track->setName(
"new track");
519 CPPUNIT_ASSERT_EQUAL(5_st, container->trackCount());
520 container->addTrack(track);
521 CPPUNIT_ASSERT_EQUAL(6_st, container->trackCount());
522 auto &secondTrack = container->tracks()[1];
523 secondTrack->setLocale(
Locale(
"ger"sv, LocaleFormat::ISO_639_2_T));
524 secondTrack->setName(
"test");
532 cerr << endl <<
"MP4 parser" << endl;
535 parseFile(testFilePath(
"mtx-test-data/mp4/10-DanseMacabreOp.40.m4a"), &OverallTests::checkMp4Testfile1);
536 parseFile(testFilePath(
"mtx-test-data/mp4/1080p-DTS-HD-7.1.mp4"), &OverallTests::checkMp4Testfile2);
537 parseFile(testFilePath(
"mtx-test-data/mp4/dash/dragon-age-inquisition-H1LkM6IVlm4-video.mp4"), &OverallTests::checkMp4Testfile3);
538 parseFile(testFilePath(
"mtx-test-data/alac/othertest-itunes.m4a"), &OverallTests::checkMp4Testfile4);
539 parseFile(testFilePath(
"mtx-test-data/aac/he-aacv2-ps.m4a"), &OverallTests::checkMp4Testfile5);
540 parseFile(testFilePath(
"mp4/android-8.1-camera-recoding.mp4"), &OverallTests::checkMp4Testfile7);
553 for (m_mode = 0; m_mode != 0x20; ++m_mode) {
559 if (m_mode & KeepTagPos) {
562 m_fileInfo.
setTagPosition(m_mode & TagsBeforeData ? ElementPosition::BeforeData : ElementPosition::AfterData);
566 m_fileInfo.
setMinPadding(m_mode & PaddingConstraints ? 1024 : 0);
567 m_fileInfo.
setMaxPadding(m_mode & PaddingConstraints ? (4096 + 1024) : numeric_limits<size_t>::max());
572 list<string> testConditions;
573 if (m_mode & ForceRewring) {
574 testConditions.emplace_back(
"forcing rewrite");
576 if (m_mode & KeepTagPos) {
577 if (m_mode & RemoveTagOrTrack) {
578 testConditions.emplace_back(
"removing tag");
580 testConditions.emplace_back(
"keeping tag position");
582 }
else if (m_mode & TagsBeforeData) {
583 testConditions.emplace_back(
"tags before data");
585 testConditions.emplace_back(
"tags after data");
587 if (m_mode & PaddingConstraints) {
588 testConditions.emplace_back(
"padding constraints");
590 if (m_mode & ForceTagPos) {
591 testConditions.emplace_back(
"forcing tag position");
593 cerr << endl <<
"MP4 maker - testmode " << m_mode <<
": " << joinStrings(testConditions,
", ") << endl;
598 void (
OverallTests::*modifyRoutine)(void) = (m_mode & RemoveTagOrTrack) ? &OverallTests::removeAllTags : &OverallTests::setMp4TestMetaData;
599 makeFile(workingCopyPath(
"mtx-test-data/mp4/10-DanseMacabreOp.40.m4a"), modifyRoutine, &OverallTests::checkMp4Testfile1);
600 makeFile(workingCopyPath(
"mtx-test-data/mp4/1080p-DTS-HD-7.1.mp4"), modifyRoutine, &OverallTests::checkMp4Testfile2);
602 workingCopyPath(
"mtx-test-data/mp4/dash/dragon-age-inquisition-H1LkM6IVlm4-video.mp4"), modifyRoutine, &OverallTests::checkMp4Testfile3);
603 makeFile(workingCopyPath(
"mtx-test-data/alac/othertest-itunes.m4a"), modifyRoutine, &OverallTests::checkMp4Testfile4);
604 makeFile(workingCopyPath(
"mtx-test-data/aac/he-aacv2-ps.m4a"), modifyRoutine, &OverallTests::checkMp4Testfile5);
605 makeFile(workingCopyPath(
"mp4/android-8.1-camera-recoding.mp4"), modifyRoutine, &OverallTests::checkMp4Testfile7);
607 modifyRoutine = (m_mode & RemoveTagOrTrack) ? &OverallTests::removeSecondTrack : &OverallTests::alterMp4Tracks;
609 makeFile(workingCopyPath(
"mtx-test-data/mp4/1080p-DTS-HD-7.1.mp4"), modifyRoutine, &OverallTests::checkMp4Testfile6);
619 static constexpr auto hugePadding =
static_cast<std::size_t
>(std::numeric_limits<std::uint32_t>::max()) + 1;
620 static constexpr auto expectedChunkCount = std::uint32_t{ 435 };
622 std::cerr <<
"\nMaking MP4 file with 64-bit offsets\n";
623 if (std::numeric_limits<std::size_t>::max() <= std::numeric_limits<std::uint32_t>::max()) {
624 std::cerr <<
" - skipping test with 64-bit offsets, std::size_t is not big enough\n";
627 if (!CppUtilities::isEnvVariableSet(PROJECT_VARNAME_UPPER
"_TEST_WITH_BIG_FILES").value_or(
false)) {
628 std::cerr <<
" - skipping test with 64-bit offsets, set " PROJECT_VARNAME_UPPER
"_TEST_WITH_BIG_FILES=1 to enable\n";
634 m_fileInfo.
setPath(workingCopyPath(
"mtx-test-data/mp4/10-DanseMacabreOp.40.m4a"));
635 std::cerr <<
" - testing with file " << m_fileInfo.
path() <<
"\n";
641 CPPUNIT_ASSERT(container);
642 auto *firstElement = container->firstElement();
643 CPPUNIT_ASSERT(firstElement);
644 auto *sampleTable = firstElement->subelementByPath(
646 CPPUNIT_ASSERT(sampleTable);
649 CPPUNIT_ASSERT_MESSAGE(
"file has initially a 32-bit chunk offset table", chunkOffsetTable);
650 CPPUNIT_ASSERT_MESSAGE(
"file has initially no 64-bit chunk offset table", !chunkOffsetTable64);
651 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"initially no padding present", 3724_st, m_fileInfo.
paddingSize());
652 auto *track = container->track(0);
653 CPPUNIT_ASSERT(track);
654 CPPUNIT_ASSERT_EQUAL(expectedChunkCount, track->chunkCount());
655 CPPUNIT_ASSERT_EQUAL(4u, track->chunkOffsetSize());
666 CPPUNIT_ASSERT(container);
667 firstElement = container->firstElement();
668 CPPUNIT_ASSERT(firstElement);
669 sampleTable = firstElement->subelementByPath(
671 CPPUNIT_ASSERT(sampleTable);
674 CPPUNIT_ASSERT_MESSAGE(
"the 32-bit chunk offset table is no longer present", !chunkOffsetTable);
675 CPPUNIT_ASSERT_MESSAGE(
"the chunk offset table has been converted to 64-bit", chunkOffsetTable64);
676 CPPUNIT_ASSERT_EQUAL_MESSAGE(
"padding present", hugePadding, m_fileInfo.
paddingSize());
677 track = container->track(0);
678 CPPUNIT_ASSERT(track);
679 CPPUNIT_ASSERT_EQUAL(expectedChunkCount, track->chunkCount());
680 CPPUNIT_ASSERT_EQUAL(8u, track->chunkOffsetSize());
681 CPPUNIT_ASSERT(m_diag.level() <= DiagLevel::Information);
The OverallTests class tests reading and writing tags and parsing technical information for all suppo...
void testMp4MakingWith64BitOffsets()
Tests the MP4 maker via MediaFileInfo with a big padding to require 64-bit chunk offsets.
void testMp4Making()
Tests the MP4 maker via MediaFileInfo.
void testMp4Parsing()
Tests the MP4 parser via MediaFileInfo.
virtual ElementPosition determineTagPosition(Diagnostics &diag) const
Determines the position of the tags inside the file.
virtual ElementPosition determineIndexPosition(Diagnostics &diag) const
Determines the position of the index.
const std::string & documentType() const
Returns a string that describes the document type if available; otherwise returns an empty string.
virtual Tag * createTag(const TagTarget &target=TagTarget())
Creates and returns a tag for the specified target.
const std::string & path() const
Returns the path of the current file.
void reopen(bool readOnly=false)
Opens a std::fstream for the current file.
void open(bool readOnly=false)
Opens a std::fstream for the current file.
void setPath(std::string_view path)
Sets the current file.
DiagLevel level() const
Returns the worst diag level present in the container.
bool removeTrack(AbstractTrack *track) override
Removes the specified track to the container.
Implementation of GenericContainer<MediaFileInfo, Mp4Tag, Mp4Track, Mp4Atom>.
Implementation of TagParser::Tag for the MP4 container.
const TagValue & value(KnownField value) const override
Returns the value of the specified field.
Implementation of TagParser::AbstractTrack for the MP4 container.
The Size class defines the size of a two-dimensional object using integer point precision.
std::string toString(TagTextEncoding encoding=TagTextEncoding::Unspecified) const
Converts the value of the current TagValue object to its equivalent std::string representation.
The Tag class is used to store, read and write tag information.
virtual bool setValue(KnownField field, const TagValue &value)=0
Assigns the given value to the specified field.
virtual const TagValue & value(KnownField field) const =0
Returns the value of the specified field.
The Locale struct specifies a language and/or a country using one or more LocaleDetail objects.