Tag Parser  6.4.1
C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags
overallmp4.cpp
Go to the documentation of this file.
1 #include "./helper.h"
2 #include "./overall.h"
3 
4 #include "../abstracttrack.h"
5 #include "../mp4/mp4ids.h"
6 #include "../mp4/mp4tag.h"
7 #include "../mp4/mp4container.h"
8 
9 namespace Mp4TestFlags {
11 {
12  ForceRewring = 0x1,
13  KeepTagPos = 0x2,
17  ForceTagPos = 0x8,
18 };
19 }
20 
24 void OverallTests::checkMp4Testfile1()
25 {
26  CPPUNIT_ASSERT(m_fileInfo.containerFormat() == ContainerFormat::Mp4);
27  const auto tracks = m_fileInfo.tracks();
28  CPPUNIT_ASSERT(tracks.size() == 1);
29  for(const auto &track : tracks) {
30  switch(track->id()) {
31  case 1:
32  CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
33  CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Aac, track->format().general);
34  CPPUNIT_ASSERT_EQUAL(2012, track->creationTime().year());
35  CPPUNIT_ASSERT_EQUAL(44100u, track->samplingFrequency());
36  CPPUNIT_ASSERT_EQUAL(static_cast<byte>(Mpeg4ChannelConfigs::FrontLeftFrontRight), track->channelConfig());
37  break;
38  default:
39  CPPUNIT_FAIL("unknown track ID");
40  }
41  }
42  const auto tags = m_fileInfo.tags();
43  switch(m_tagStatus) {
45  CPPUNIT_ASSERT(tags.size() == 1);
46  CPPUNIT_ASSERT(tags.front()->value(KnownField::Title).toString() == "Danse Macabre, Op.40");
47  CPPUNIT_ASSERT(tags.front()->value(KnownField::Artist).toString() == "Saint-SaĆ«ns");
48  CPPUNIT_ASSERT(tags.front()->value(KnownField::Genre).toString() == "Classical");
49  CPPUNIT_ASSERT(tags.front()->value(KnownField::Encoder).toString() == "qaac 1.32, CoreAudioToolbox 7.9.7.3, AAC-LC Encoder, TVBR q63, Quality 96");
50  CPPUNIT_ASSERT(tags.front()->value(KnownField::TrackPosition).toPositionInSet().position() == 10);
51  break;
53  checkMp4TestMetaData();
54  break;
55  case TagStatus::Removed:
56  CPPUNIT_ASSERT_EQUAL(0_st, tracks.size());
57  }
58  CPPUNIT_ASSERT(m_fileInfo.worstNotificationTypeIncludingRelatedObjects() <= NotificationType::Information);
59 }
60 
64 void OverallTests::checkMp4Testfile2()
65 {
66  CPPUNIT_ASSERT(m_fileInfo.containerFormat() == ContainerFormat::Mp4);
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()) {
71  case 1:
72  CPPUNIT_ASSERT_EQUAL(MediaType::Video, track->mediaType());
73  CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Avc, track->format().general);
74  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned char>(SubFormats::AvcHighProfile), track->format().sub);
75  CPPUNIT_ASSERT_EQUAL(4.0, track->version());
76  CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
77  CPPUNIT_ASSERT(track->pixelSize() == Size(1920, 750));
78  break;
79  case 2:
80  CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
81  CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Aac, track->format().general);
82  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned char>(SubFormats::AacMpeg4LowComplexityProfile), track->format().sub);
83  CPPUNIT_ASSERT(!(track->format().extension & ExtensionFormats::SpectralBandReplication));
84  CPPUNIT_ASSERT(!(track->format().extension & ExtensionFormats::ParametricStereo));
85  CPPUNIT_ASSERT_EQUAL("eng"s, track->language());
86  CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
87  CPPUNIT_ASSERT_EQUAL(48000u, track->samplingFrequency());
88  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned char>(Mpeg4ChannelConfigs::FrontLeftFrontRight), track->channelConfig());
89  break;
90  case 3:
91  CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
92  CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Ac3, track->format().general);
93  CPPUNIT_ASSERT_EQUAL("eng"s, track->language());
94  CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
95  break;
96  case 4:
97  CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
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());
101  break;
102  case 6:
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());
106  break;
107  default:
108  CPPUNIT_FAIL("unknown track ID");
109  }
110  }
111  const auto tags = m_fileInfo.tags();
112  switch(m_tagStatus) {
113  case TagStatus::Original:
114  CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
115  break;
117  checkMp4TestMetaData();
118  break;
119  case TagStatus::Removed:
120  CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
121  }
122  CPPUNIT_ASSERT(m_fileInfo.worstNotificationTypeIncludingRelatedObjects() <= NotificationType::Information);
123 }
124 
128 void OverallTests::checkMp4Testfile3()
129 {
130  CPPUNIT_ASSERT(m_fileInfo.containerFormat() == ContainerFormat::Mp4);
131  CPPUNIT_ASSERT(m_fileInfo.container() && m_fileInfo.container()->documentType() == "dash");
132  const auto tracks = m_fileInfo.tracks();
133  CPPUNIT_ASSERT(tracks.size() == 1);
134  for(const auto &track : tracks) {
135  switch(track->id()) {
136  case 1:
137  CPPUNIT_ASSERT(track->mediaType() == MediaType::Video);
138  CPPUNIT_ASSERT(track->format() == GeneralMediaFormat::Avc);
139  CPPUNIT_ASSERT(track->format().sub == SubFormats::AvcMainProfile);
140  CPPUNIT_ASSERT(track->version() == 3.1);
141  CPPUNIT_ASSERT(track->creationTime().year() == 2014);
142  CPPUNIT_ASSERT(track->pixelSize() == Size(854, 480));
143  CPPUNIT_ASSERT(!strcmp(track->chromaFormat(), "YUV 4:2:0"));
144  break;
145  default:
146  CPPUNIT_FAIL("unknown track ID");
147  }
148  }
149  const auto tags = m_fileInfo.tags();
150  switch(m_tagStatus) {
151  case TagStatus::Original:
152  CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
153  break;
155  checkMp4TestMetaData();
156  break;
157  case TagStatus::Removed:
158  CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
159  }
160 
161  for(const Notification &notification : m_fileInfo.gatherRelatedNotifications()) {
162  if(notification.type() != NotificationType::Warning) {
163  continue;
164  }
165  if(m_mode & Mp4TestFlags::TagsBeforeData) {
166  CPPUNIT_FAIL("No warnings expected when putting tags before data.");
167  } else {
168  CPPUNIT_ASSERT_EQUAL("Sorry, but putting index/tags at the end is not possible when dealing with DASH files."s, notification.message());
169  }
170  }
171  CPPUNIT_ASSERT(m_fileInfo.worstNotificationTypeIncludingRelatedObjects() <= NotificationType::Warning);
172 }
173 
177 void OverallTests::checkMp4Testfile4()
178 {
179  CPPUNIT_ASSERT(m_fileInfo.containerFormat() == ContainerFormat::Mp4);
180  CPPUNIT_ASSERT(m_fileInfo.container() && m_fileInfo.container()->documentType() == "M4A ");
181  const auto tracks = m_fileInfo.tracks();
182  CPPUNIT_ASSERT(tracks.size() == 1);
183  for(const auto &track : tracks) {
184  switch(track->id()) {
185  case 1:
186  CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
187  CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Alac, track->format().general);
188  CPPUNIT_ASSERT(track->creationTime().year() == 2008);
189  CPPUNIT_ASSERT(track->channelCount() == 2);
190  CPPUNIT_ASSERT(track->bitsPerSample() == 16);
191  break;
192  default:
193  CPPUNIT_FAIL("unknown track ID");
194  }
195  }
196  const auto tags = m_fileInfo.tags();
197  switch(m_tagStatus) {
198  case TagStatus::Original:
199  CPPUNIT_ASSERT(tags.size() == 1);
200  CPPUNIT_ASSERT(tags.front()->value(KnownField::Title).toString() == "Sad Song");
201  CPPUNIT_ASSERT(tags.front()->value(KnownField::Artist).toString() == "Oasis");
202  CPPUNIT_ASSERT(tags.front()->value(KnownField::Album).toString() == "Don't Go Away (Apple Lossless)");
203  CPPUNIT_ASSERT(tags.front()->value(KnownField::Genre).toString() == "Alternative & Punk");
204  CPPUNIT_ASSERT(tags.front()->value(KnownField::Encoder).toString() == "iTunes v7.5.0.20");
205  CPPUNIT_ASSERT(tags.front()->value(KnownField::Year).toString() == "1998");
206  CPPUNIT_ASSERT(tags.front()->value(KnownField::Comment).isEmpty());
207  CPPUNIT_ASSERT(tags.front()->value(KnownField::Cover).dataSize() == 0x58f3);
208  CPPUNIT_ASSERT(BE::toUInt64(tags.front()->value(KnownField::Cover).dataPointer()) == 0xFFD8FFE000104A46);
209  CPPUNIT_ASSERT(tags.front()->value(KnownField::TrackPosition).toPositionInSet() == PositionInSet(3, 4));
210  CPPUNIT_ASSERT(tags.front()->value(KnownField::DiskPosition).toPositionInSet() == PositionInSet(1, 1));
211  break;
213  checkMp4TestMetaData();
214  break;
215  case TagStatus::Removed:
216  CPPUNIT_ASSERT_EQUAL(0_st, tracks.size());
217  }
218  CPPUNIT_ASSERT(m_fileInfo.worstNotificationTypeIncludingRelatedObjects() <= NotificationType::Information);
219 }
220 
224 void OverallTests::checkMp4Testfile5()
225 {
226  CPPUNIT_ASSERT(m_fileInfo.containerFormat() == ContainerFormat::Mp4);
227  CPPUNIT_ASSERT(m_fileInfo.container() && m_fileInfo.container()->documentType() == "mp42");
228  const auto tracks = m_fileInfo.tracks();
229  CPPUNIT_ASSERT(tracks.size() == 1);
230  for(const auto &track : tracks) {
231  switch(track->id()) {
232  case 1:
233  CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
234  CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Aac, track->format().general);
235  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned char>(SubFormats::AacMpeg4LowComplexityProfile), track->format().sub);
236  CPPUNIT_ASSERT(track->format().extension & ExtensionFormats::SpectralBandReplication);
237  CPPUNIT_ASSERT(track->format().extension & ExtensionFormats::ParametricStereo);
238  CPPUNIT_ASSERT(track->creationTime().year() == 2014);
239  CPPUNIT_ASSERT(track->channelCount() == 2);
240  CPPUNIT_ASSERT(track->channelConfig() == Mpeg4ChannelConfigs::FrontCenter);
241  CPPUNIT_ASSERT(track->extensionChannelConfig() == Mpeg4ChannelConfigs::FrontLeftFrontRight);
242  CPPUNIT_ASSERT(track->samplingFrequency() == 24000);
243  CPPUNIT_ASSERT(track->extensionSamplingFrequency() == 48000);
244  CPPUNIT_ASSERT(track->bitsPerSample() == 16);
245  break;
246  default:
247  CPPUNIT_FAIL("unknown track ID");
248  }
249  }
250  const auto tags = m_fileInfo.tags();
251  switch(m_tagStatus) {
252  case TagStatus::Original:
253  CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
254  break;
256  checkMp4TestMetaData();
257  break;
258  case TagStatus::Removed:
259  CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
260  }
261  CPPUNIT_ASSERT(m_fileInfo.worstNotificationTypeIncludingRelatedObjects() <= NotificationType::Information);
262 }
263 
267 void OverallTests::checkMp4Testfile6()
268 {
269  CPPUNIT_ASSERT(m_fileInfo.containerFormat() == ContainerFormat::Mp4);
270  const auto tracks = m_fileInfo.tracks();
271  if(m_mode & Mp4TestFlags::RemoveTagOrTrack) {
272  CPPUNIT_ASSERT_EQUAL(4_st, tracks.size());
273  } else {
274  CPPUNIT_ASSERT_EQUAL(6_st, tracks.size());
275  }
276  bool track2Present = false, track5Present = false;
277  for(const auto &track : tracks) {
278  switch(track->id()) {
279  case 1:
280  CPPUNIT_ASSERT_EQUAL(MediaType::Video, track->mediaType());
281  CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Avc, track->format().general);
282  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned char>(SubFormats::AvcHighProfile), track->format().sub);
283  CPPUNIT_ASSERT_EQUAL(4.0, track->version());
284  CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
285  CPPUNIT_ASSERT(track->pixelSize() == Size(1920, 750));
286  break;
287  case 2:
288  CPPUNIT_ASSERT(track2Present = !track2Present);
289  CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
290  CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Aac, track->format().general);
291  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned char>(SubFormats::AacMpeg4LowComplexityProfile), track->format().sub);
292  CPPUNIT_ASSERT(!(track->format().extension & ExtensionFormats::SpectralBandReplication));
293  CPPUNIT_ASSERT(!(track->format().extension & ExtensionFormats::ParametricStereo));
294  CPPUNIT_ASSERT_EQUAL("ger"s, track->language());
295  CPPUNIT_ASSERT_EQUAL("test"s, track->name());
296  CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
297  CPPUNIT_ASSERT_EQUAL(48000u, track->samplingFrequency());
298  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned char>(Mpeg4ChannelConfigs::FrontLeftFrontRight), track->channelConfig());
299  break;
300  case 3:
301  CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
302  CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Ac3, track->format().general);
303  CPPUNIT_ASSERT_EQUAL("eng"s, track->language());
304  CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
305  break;
306  case 4:
307  CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
308  CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::DtsHd, track->format().general);
309  CPPUNIT_ASSERT_EQUAL("eng"s, track->language());
310  CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
311  break;
312  case 5:
313  CPPUNIT_ASSERT(track5Present = !track5Present);
314  CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
315  CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Aac, track->format().general);
316  CPPUNIT_ASSERT_EQUAL(2012, track->creationTime().year());
317  CPPUNIT_ASSERT_EQUAL(44100u, track->samplingFrequency());
318  CPPUNIT_ASSERT_EQUAL(static_cast<byte>(Mpeg4ChannelConfigs::FrontLeftFrontRight), track->channelConfig());
319  CPPUNIT_ASSERT_EQUAL("new track"s, track->name());
320  break;
321  case 6:
322  CPPUNIT_ASSERT_EQUAL(MediaType::Text, track->mediaType());
323  CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::TimedText, track->format().general);
324  CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
325  break;
326  default:
327  CPPUNIT_FAIL("unknown track ID");
328  }
329  }
330  if(m_mode & Mp4TestFlags::RemoveTagOrTrack) {
331  CPPUNIT_ASSERT(!track2Present);
332  CPPUNIT_ASSERT(!track5Present);
333  } else {
334  CPPUNIT_ASSERT(track2Present);
335  CPPUNIT_ASSERT(track5Present);
336  }
337 
338  CPPUNIT_ASSERT_EQUAL(0_st, m_fileInfo.tags().size());
339 
340  CPPUNIT_ASSERT(m_fileInfo.worstNotificationTypeIncludingRelatedObjects() <= NotificationType::Information);
341 }
342 
346 void OverallTests::checkMp4TestMetaData()
347 {
348  // check whether a tag is assigned
349  const auto tags = m_fileInfo.tags();
350  Mp4Tag *tag = m_fileInfo.mp4Tag();
351  CPPUNIT_ASSERT(tags.size() == 1);
352  CPPUNIT_ASSERT(tag != nullptr);
353 
354  // check test meta data
355  CPPUNIT_ASSERT_EQUAL(m_testTitle, tag->value(KnownField::Title));
356  CPPUNIT_ASSERT_EQUAL(m_testComment.toString(), tag->value(KnownField::Comment).toString()); // loss of description is ok
357  CPPUNIT_ASSERT_EQUAL(m_testAlbum, tag->value(KnownField::Album));
358  CPPUNIT_ASSERT_EQUAL(m_preservedMetaData.front(), tag->value(KnownField::Artist));
359  CPPUNIT_ASSERT_EQUAL(m_testPosition, tag->value(KnownField::TrackPosition));
360  CPPUNIT_ASSERT_EQUAL(m_testPosition, tag->value(KnownField::DiskPosition));
361 
362  // TODO: check more fields
363  m_preservedMetaData.pop();
364 }
365 
369 void OverallTests::checkMp4Constraints()
370 {
371  using namespace Mp4TestFlags;
372 
373  CPPUNIT_ASSERT(m_fileInfo.container());
374  if(m_mode & PaddingConstraints) {
375  if(m_mode & ForceRewring) {
376  CPPUNIT_ASSERT_EQUAL(4096_st, m_fileInfo.paddingSize());
377  } else {
378  CPPUNIT_ASSERT(m_fileInfo.paddingSize() >= 1024);
379  CPPUNIT_ASSERT(m_fileInfo.paddingSize() <= (4096 + 1024));
380  }
381  if(!(m_mode & RemoveTagOrTrack) && (m_fileInfo.container()->documentType() != "dash") && ((m_mode & ForceRewring) || (m_mode & ForceTagPos))) {
382  const ElementPosition currentTagPos = m_fileInfo.container()->determineTagPosition();
383  if(currentTagPos == ElementPosition::Keep) {
384  CPPUNIT_ASSERT_EQUAL(m_expectedTagPos, m_fileInfo.container()->determineIndexPosition());
385  }
386  }
387  }
388 }
389 
393 void OverallTests::setMp4TestMetaData()
394 {
395  // ensure a tag exists
396  Tag *tag = m_fileInfo.container()->createTag();
397 
398  // assign test meta data
399  tag->setValue(KnownField::Title, m_testTitle);
400  tag->setValue(KnownField::Comment, m_testComment);
401  tag->setValue(KnownField::Album, m_testAlbum);
402  m_preservedMetaData.push(tag->value(KnownField::Artist));
403  tag->setValue(KnownField::TrackPosition, m_testPosition);
404  tag->setValue(KnownField::DiskPosition, m_testPosition);
405  // TODO: set more fields
406 }
407 
415 void OverallTests::alterMp4Tracks()
416 {
417  m_additionalFileInfo.setPath(TestUtilities::testFilePath("mtx-test-data/mp4/10-DanseMacabreOp.40.m4a"));
418  m_additionalFileInfo.reopen(true);
419  m_additionalFileInfo.parseContainerFormat();
420  m_additionalFileInfo.parseTracks();
421  CPPUNIT_ASSERT_EQUAL(ContainerFormat::Mp4, m_additionalFileInfo.containerFormat());
422  CPPUNIT_ASSERT_EQUAL(ContainerFormat::Mp4, m_fileInfo.containerFormat());
423  const auto &tracks = m_additionalFileInfo.tracks();
424  CPPUNIT_ASSERT_EQUAL(1_st, tracks.size());
425  CPPUNIT_ASSERT_EQUAL(TrackType::Mp4Track, tracks[0]->type());
426  auto *track = static_cast<Mp4Track *>(tracks[0]);
427  CPPUNIT_ASSERT(static_cast<Mp4Container *>(m_additionalFileInfo.container())->removeTrack(track));
428  CPPUNIT_ASSERT_EQUAL(0_st, m_additionalFileInfo.trackCount());
429  track->setName("new track");
430  auto *container = static_cast<Mp4Container *>(m_fileInfo.container());
431  CPPUNIT_ASSERT_EQUAL(5_st, container->trackCount());
432  container->addTrack(track);
433  CPPUNIT_ASSERT_EQUAL(6_st, container->trackCount());
434  auto &secondTrack = container->tracks()[1];
435  secondTrack->setLanguage("ger");
436  secondTrack->setName("test");
437 }
438 
443 {
444  cerr << endl << "MP4 parser" << endl;
445  m_fileInfo.setForceFullParse(false);
446  m_tagStatus = TagStatus::Original;
447  parseFile(TestUtilities::testFilePath("mtx-test-data/mp4/10-DanseMacabreOp.40.m4a"), &OverallTests::checkMp4Testfile1);
448  parseFile(TestUtilities::testFilePath("mtx-test-data/mp4/1080p-DTS-HD-7.1.mp4"), &OverallTests::checkMp4Testfile2);
449  parseFile(TestUtilities::testFilePath("mtx-test-data/mp4/dash/dragon-age-inquisition-H1LkM6IVlm4-video.mp4"), &OverallTests::checkMp4Testfile3);
450  parseFile(TestUtilities::testFilePath("mtx-test-data/alac/othertest-itunes.m4a"), &OverallTests::checkMp4Testfile4);
451  parseFile(TestUtilities::testFilePath("mtx-test-data/aac/he-aacv2-ps.m4a"), &OverallTests::checkMp4Testfile5);
452 }
453 
454 #ifdef PLATFORM_UNIX
455 
459 void OverallTests::testMp4Making()
460 {
461  // full parse is required to determine padding
462  m_fileInfo.setForceFullParse(true);
463 
464  // do the test under different conditions
465  for(m_mode = 0; m_mode != 0x20; ++m_mode) {
466  using namespace Mp4TestFlags;
467 
468  // setup test conditions
469 
470  m_fileInfo.setForceRewrite(m_mode & ForceRewring);
471  if(m_mode & KeepTagPos) {
472  m_fileInfo.setTagPosition(ElementPosition::Keep);
473  } else {
474  m_fileInfo.setTagPosition(m_mode & TagsBeforeData ? ElementPosition::BeforeData : ElementPosition::AfterData);
475  }
476  m_fileInfo.setIndexPosition(m_fileInfo.tagPosition());
477  m_fileInfo.setPreferredPadding(m_mode & PaddingConstraints ? 4096 : 0);
478  m_fileInfo.setMinPadding(m_mode & PaddingConstraints ? 1024 : 0);
479  m_fileInfo.setMaxPadding(m_mode & PaddingConstraints ? (4096 + 1024) : static_cast<size_t>(-1));
480  m_fileInfo.setForceTagPosition(m_mode & ForceTagPos);
481  m_fileInfo.setForceIndexPosition(m_mode & ForceTagPos);
482 
483  // print test conditions
484  list<string> testConditions;
485  if(m_mode & ForceRewring) {
486  testConditions.emplace_back("forcing rewrite");
487  }
488  if(m_mode & KeepTagPos) {
489  if(m_mode & RemoveTagOrTrack) {
490  testConditions.emplace_back("removing tag");
491  } else {
492  testConditions.emplace_back("keeping tag position");
493  }
494  } else if(m_mode & TagsBeforeData) {
495  testConditions.emplace_back("tags before data");
496  } else {
497  testConditions.emplace_back("tags after data");
498  }
499  if(m_mode & PaddingConstraints) {
500  testConditions.emplace_back("padding constraints");
501  }
502  if(m_mode & ForceTagPos) {
503  testConditions.emplace_back("forcing tag position");
504  }
505  cerr << endl << "MP4 maker - testmode " << m_mode << ": " << joinStrings(testConditions, ", ") << endl;
506 
507  // do actual tests
508  // -> either remove tags or set test meta data
510  void (OverallTests::*modifyRoutine)(void) = (m_mode & RemoveTagOrTrack) ? &OverallTests::removeAllTags : &OverallTests::setMp4TestMetaData;
511  makeFile(TestUtilities::workingCopyPath("mtx-test-data/mp4/10-DanseMacabreOp.40.m4a"), modifyRoutine, &OverallTests::checkMp4Testfile1);
512  makeFile(TestUtilities::workingCopyPath("mtx-test-data/mp4/1080p-DTS-HD-7.1.mp4"), modifyRoutine, &OverallTests::checkMp4Testfile2);
513  makeFile(TestUtilities::workingCopyPath("mtx-test-data/mp4/dash/dragon-age-inquisition-H1LkM6IVlm4-video.mp4"), modifyRoutine, &OverallTests::checkMp4Testfile3);
514  makeFile(TestUtilities::workingCopyPath("mtx-test-data/alac/othertest-itunes.m4a"), modifyRoutine, &OverallTests::checkMp4Testfile4);
515  makeFile(TestUtilities::workingCopyPath("mtx-test-data/aac/he-aacv2-ps.m4a"), modifyRoutine, &OverallTests::checkMp4Testfile5);
516  // -> add/remove tracks
517  modifyRoutine = (m_mode & RemoveTagOrTrack) ? &OverallTests::removeSecondTrack : &OverallTests::alterMp4Tracks;
518  m_fileInfo.setTagPosition(ElementPosition::Keep);
519  makeFile(TestUtilities::workingCopyPath("mtx-test-data/mp4/1080p-DTS-HD-7.1.mp4"), modifyRoutine, &OverallTests::checkMp4Testfile6);
520  }
521 }
522 #endif
The Size class defines the size of a two-dimensional object using integer point precision.
Definition: size.h:16
Implementation of Media::AbstractTrack for the MP4 container.
Definition: mp4track.h:120
bool addTrack(TrackType *track)
Adds the specified track to the container.
Implementation of GenericContainer<MediaFileInfo, Mp4Tag, Mp4Track, Mp4Atom>.
Definition: mp4container.h:19
The PositionInSet class describes the position of an element in a set which consists of a certain num...
Definition: positioninset.h:20
Implementation of Media::Tag for the MP4 container.
Definition: mp4tag.h:90
The OverallTests class tests reading and writing tags and parsing technical information for all suppo...
Definition: overall.h:44
The Tag class is used to store, read and write tag information.
Definition: tag.h:98
const TagValue & value(KnownField value) const
Returns the value of the specified field.
Definition: mp4tag.cpp:58
void setName(const std::string &name)
Sets the name.
The Notification class holds a notification message of a certain notification type.
Definition: notification.h:43
void testMp4Parsing()
Tests the MP4 parser via MediaFileInfo.
Definition: overallmp4.cpp:442
virtual bool setValue(KnownField field, const TagValue &value)=0
Assigns the given value to the specified field.
std::string toString(TagTextEncoding encoding=TagTextEncoding::Unspecified) const
Converts the value of the current TagValue object to its equivalent std::string representation.
Definition: tagvalue.h:320
virtual const TagValue & value(KnownField field) const =0
Returns the value of the specified field.