Tag Parser  7.0.3
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/mp4container.h"
6 #include "../mp4/mp4ids.h"
7 #include "../mp4/mp4tag.h"
8 
9 namespace Mp4TestFlags {
10 enum TestFlag {
11  ForceRewring = 0x1,
12  KeepTagPos = 0x2,
16  ForceTagPos = 0x8,
17 };
18 }
19 
23 void OverallTests::checkMp4Testfile1()
24 {
25  CPPUNIT_ASSERT_EQUAL(ContainerFormat::Mp4, m_fileInfo.containerFormat());
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()) {
30  case 1:
31  CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
32  CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Aac, track->format().general);
33  CPPUNIT_ASSERT_EQUAL(2012, track->creationTime().year());
34  CPPUNIT_ASSERT_EQUAL(44100u, track->samplingFrequency());
35  CPPUNIT_ASSERT_EQUAL(static_cast<byte>(Mpeg4ChannelConfigs::FrontLeftFrontRight), track->channelConfig());
36  break;
37  default:
38  CPPUNIT_FAIL("unknown track ID");
39  }
40  }
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());
48  CPPUNIT_ASSERT_EQUAL(
49  "qaac 1.32, CoreAudioToolbox 7.9.7.3, AAC-LC Encoder, TVBR q63, Quality 96"s, tags.front()->value(KnownField::Encoder).toString());
50  CPPUNIT_ASSERT_EQUAL(10, tags.front()->value(KnownField::TrackPosition).toPositionInSet().position());
51  break;
53  checkMp4TestMetaData();
54  break;
55  case TagStatus::Removed:
56  CPPUNIT_ASSERT_EQUAL(0_st, tracks.size());
57  }
58  CPPUNIT_ASSERT(m_diag.level() <= DiagLevel::Information);
59 }
60 
64 void OverallTests::checkMp4Testfile2()
65 {
66  CPPUNIT_ASSERT_EQUAL(ContainerFormat::Mp4, m_fileInfo.containerFormat());
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_diag.level() <= DiagLevel::Information);
123 }
124 
128 void OverallTests::checkMp4Testfile3()
129 {
130  CPPUNIT_ASSERT_EQUAL(ContainerFormat::Mp4, m_fileInfo.containerFormat());
131  CPPUNIT_ASSERT(m_fileInfo.container() != nullptr);
132  CPPUNIT_ASSERT_EQUAL("dash"s, m_fileInfo.container()->documentType());
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()) {
137  case 1:
138  CPPUNIT_ASSERT_EQUAL(MediaType::Video, track->mediaType());
139  CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Avc, track->format().general);
140  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned char>(SubFormats::AvcMainProfile), track->format().sub);
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()));
145  break;
146  default:
147  CPPUNIT_FAIL("unknown track ID");
148  }
149  }
150  const auto tags = m_fileInfo.tags();
151  switch (m_tagStatus) {
152  case TagStatus::Original:
153  CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
154  break;
156  checkMp4TestMetaData();
157  break;
158  case TagStatus::Removed:
159  CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
160  }
161 
162  for (const auto &msg : m_diag) {
163  if (msg.level() != DiagLevel::Warning) {
164  continue;
165  }
166  if (m_mode & Mp4TestFlags::TagsBeforeData) {
167  CPPUNIT_FAIL("No warnings expected when putting tags before data.");
168  } else {
169  CPPUNIT_ASSERT_EQUAL("Sorry, but putting index/tags at the end is not possible when dealing with DASH files."s, msg.message());
170  }
171  }
172  CPPUNIT_ASSERT(m_diag.level() <= DiagLevel::Warning);
173 }
174 
178 void OverallTests::checkMp4Testfile4()
179 {
180  CPPUNIT_ASSERT_EQUAL(ContainerFormat::Mp4, m_fileInfo.containerFormat());
181  CPPUNIT_ASSERT(m_fileInfo.container() != nullptr);
182  CPPUNIT_ASSERT_EQUAL("M4A "s, m_fileInfo.container()->documentType());
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()) {
187  case 1:
188  CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
189  CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Alac, track->format().general);
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());
193  break;
194  default:
195  CPPUNIT_FAIL("unknown track ID");
196  }
197  }
198  const auto tags = m_fileInfo.tags();
199  switch (m_tagStatus) {
200  case TagStatus::Original:
201  CPPUNIT_ASSERT_EQUAL(1_st, tags.size());
202  CPPUNIT_ASSERT_EQUAL("Sad Song"s, tags.front()->value(KnownField::Title).toString());
203  CPPUNIT_ASSERT_EQUAL("Oasis"s, tags.front()->value(KnownField::Artist).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());
208  CPPUNIT_ASSERT(tags.front()->value(KnownField::Comment).isEmpty());
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()));
211  CPPUNIT_ASSERT_EQUAL(PositionInSet(3, 4), tags.front()->value(KnownField::TrackPosition).toPositionInSet());
212  CPPUNIT_ASSERT_EQUAL(PositionInSet(1, 1), tags.front()->value(KnownField::DiskPosition).toPositionInSet());
213  break;
215  checkMp4TestMetaData();
216  break;
217  case TagStatus::Removed:
218  CPPUNIT_ASSERT_EQUAL(0_st, tracks.size());
219  }
220  CPPUNIT_ASSERT(m_diag.level() <= DiagLevel::Information);
221 }
222 
226 void OverallTests::checkMp4Testfile5()
227 {
228  CPPUNIT_ASSERT_EQUAL(ContainerFormat::Mp4, m_fileInfo.containerFormat());
229  CPPUNIT_ASSERT(m_fileInfo.container() != nullptr);
230  CPPUNIT_ASSERT_EQUAL("mp42"s, m_fileInfo.container()->documentType());
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()) {
235  case 1:
236  CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
237  CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Aac, track->format().general);
238  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned char>(SubFormats::AacMpeg4LowComplexityProfile), track->format().sub);
239  CPPUNIT_ASSERT(track->format().extension & ExtensionFormats::SpectralBandReplication);
240  CPPUNIT_ASSERT(track->format().extension & ExtensionFormats::ParametricStereo);
241  CPPUNIT_ASSERT_EQUAL(2014, track->creationTime().year());
242  CPPUNIT_ASSERT_EQUAL(static_cast<uint16>(2), track->channelCount());
243  CPPUNIT_ASSERT_EQUAL(static_cast<byte>(Mpeg4ChannelConfigs::FrontCenter), track->channelConfig());
244  CPPUNIT_ASSERT_EQUAL(static_cast<byte>(Mpeg4ChannelConfigs::FrontLeftFrontRight), track->extensionChannelConfig());
245  CPPUNIT_ASSERT_EQUAL(24000u, track->samplingFrequency());
246  CPPUNIT_ASSERT_EQUAL(48000u, track->extensionSamplingFrequency());
247  CPPUNIT_ASSERT_EQUAL(static_cast<uint16>(16), track->bitsPerSample());
248  break;
249  default:
250  CPPUNIT_FAIL("unknown track ID");
251  }
252  }
253  const auto tags = m_fileInfo.tags();
254  switch (m_tagStatus) {
255  case TagStatus::Original:
256  CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
257  break;
259  checkMp4TestMetaData();
260  break;
261  case TagStatus::Removed:
262  CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
263  }
264  CPPUNIT_ASSERT(m_diag.level() <= DiagLevel::Information);
265 }
266 
270 void OverallTests::checkMp4Testfile6()
271 {
272  CPPUNIT_ASSERT_EQUAL(ContainerFormat::Mp4, m_fileInfo.containerFormat());
273  const auto tracks = m_fileInfo.tracks();
274  if (m_mode & Mp4TestFlags::RemoveTagOrTrack) {
275  CPPUNIT_ASSERT_EQUAL(4_st, tracks.size());
276  } else {
277  CPPUNIT_ASSERT_EQUAL(6_st, tracks.size());
278  }
279  bool track2Present = false, track5Present = false;
280  for (const auto &track : tracks) {
281  switch (track->id()) {
282  case 1:
283  CPPUNIT_ASSERT_EQUAL(MediaType::Video, track->mediaType());
284  CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Avc, track->format().general);
285  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned char>(SubFormats::AvcHighProfile), track->format().sub);
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());
289  break;
290  case 2:
291  CPPUNIT_ASSERT(track2Present = !track2Present);
292  CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
293  CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Aac, track->format().general);
294  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned char>(SubFormats::AacMpeg4LowComplexityProfile), track->format().sub);
295  CPPUNIT_ASSERT(!(track->format().extension & ExtensionFormats::SpectralBandReplication));
296  CPPUNIT_ASSERT(!(track->format().extension & ExtensionFormats::ParametricStereo));
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());
301  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned char>(Mpeg4ChannelConfigs::FrontLeftFrontRight), track->channelConfig());
302  break;
303  case 3:
304  CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
305  CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Ac3, track->format().general);
306  CPPUNIT_ASSERT_EQUAL("eng"s, track->language());
307  CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
308  break;
309  case 4:
310  CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
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());
314  break;
315  case 5:
316  CPPUNIT_ASSERT(track5Present = !track5Present);
317  CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
318  CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Aac, track->format().general);
319  CPPUNIT_ASSERT_EQUAL(2012, track->creationTime().year());
320  CPPUNIT_ASSERT_EQUAL(44100u, track->samplingFrequency());
321  CPPUNIT_ASSERT_EQUAL(static_cast<byte>(Mpeg4ChannelConfigs::FrontLeftFrontRight), track->channelConfig());
322  CPPUNIT_ASSERT_EQUAL("new track"s, track->name());
323  break;
324  case 6:
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());
328  break;
329  default:
330  CPPUNIT_FAIL("unknown track ID");
331  }
332  }
333  if (m_mode & Mp4TestFlags::RemoveTagOrTrack) {
334  CPPUNIT_ASSERT(!track2Present);
335  CPPUNIT_ASSERT(!track5Present);
336  } else {
337  CPPUNIT_ASSERT(track2Present);
338  CPPUNIT_ASSERT(track5Present);
339  }
340 
341  CPPUNIT_ASSERT_EQUAL(0_st, m_fileInfo.tags().size());
342  CPPUNIT_ASSERT(m_diag.level() <= DiagLevel::Information);
343 }
344 
348 void OverallTests::checkMp4TestMetaData()
349 {
350  // check whether a tag is assigned
351  const auto tags = m_fileInfo.tags();
352  Mp4Tag *tag = m_fileInfo.mp4Tag();
353  CPPUNIT_ASSERT_EQUAL(1_st, tags.size());
354  CPPUNIT_ASSERT(tag != nullptr);
355 
356  // check test meta data
357  CPPUNIT_ASSERT_EQUAL(m_testTitle, tag->value(KnownField::Title));
358  CPPUNIT_ASSERT_EQUAL(m_testComment.toString(), tag->value(KnownField::Comment).toString()); // loss of description is ok
359  CPPUNIT_ASSERT_EQUAL(m_testAlbum, tag->value(KnownField::Album));
360  CPPUNIT_ASSERT_EQUAL(m_preservedMetaData.front(), tag->value(KnownField::Artist));
361  CPPUNIT_ASSERT_EQUAL(m_testPosition, tag->value(KnownField::TrackPosition));
362  CPPUNIT_ASSERT_EQUAL(m_testPosition, tag->value(KnownField::DiskPosition));
363 
364  // TODO: check more fields
365  m_preservedMetaData.pop();
366 }
367 
371 void OverallTests::checkMp4Constraints()
372 {
373  using namespace Mp4TestFlags;
374 
375  CPPUNIT_ASSERT(m_fileInfo.container());
376  if (m_mode & PaddingConstraints) {
377  if (m_mode & ForceRewring) {
378  CPPUNIT_ASSERT_EQUAL(4096_st, m_fileInfo.paddingSize());
379  } else {
380  CPPUNIT_ASSERT(m_fileInfo.paddingSize() >= 1024);
381  CPPUNIT_ASSERT(m_fileInfo.paddingSize() <= (4096 + 1024));
382  }
383  if (!(m_mode & RemoveTagOrTrack) && (m_fileInfo.container()->documentType() != "dash")
384  && ((m_mode & ForceRewring) || (m_mode & ForceTagPos))) {
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));
388  }
389  }
390  }
391 }
392 
396 void OverallTests::setMp4TestMetaData()
397 {
398  // ensure a tag exists
399  Tag *tag = m_fileInfo.container()->createTag();
400 
401  // assign test meta data
402  tag->setValue(KnownField::Title, m_testTitle);
403  tag->setValue(KnownField::Comment, m_testComment);
404  tag->setValue(KnownField::Album, m_testAlbum);
405  m_preservedMetaData.push(tag->value(KnownField::Artist));
406  tag->setValue(KnownField::TrackPosition, m_testPosition);
407  tag->setValue(KnownField::DiskPosition, m_testPosition);
408  // TODO: set more fields
409 }
410 
418 void OverallTests::alterMp4Tracks()
419 {
420  m_additionalFileInfo.setPath(TestUtilities::testFilePath("mtx-test-data/mp4/10-DanseMacabreOp.40.m4a"));
421  m_additionalFileInfo.reopen(true);
422  m_additionalFileInfo.parseContainerFormat(m_diag);
423  m_additionalFileInfo.parseTracks(m_diag);
424  CPPUNIT_ASSERT_EQUAL(ContainerFormat::Mp4, m_additionalFileInfo.containerFormat());
425  CPPUNIT_ASSERT_EQUAL(ContainerFormat::Mp4, m_fileInfo.containerFormat());
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());
432  track->setName("new track");
433  auto *container = static_cast<Mp4Container *>(m_fileInfo.container());
434  CPPUNIT_ASSERT_EQUAL(5_st, container->trackCount());
435  container->addTrack(track);
436  CPPUNIT_ASSERT_EQUAL(6_st, container->trackCount());
437  auto &secondTrack = container->tracks()[1];
438  secondTrack->setLanguage("ger");
439  secondTrack->setName("test");
440 }
441 
446 {
447  cerr << endl << "MP4 parser" << endl;
448  m_fileInfo.setForceFullParse(false);
449  m_tagStatus = TagStatus::Original;
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);
455 }
456 
457 #ifdef PLATFORM_UNIX
458 
462 void OverallTests::testMp4Making()
463 {
464  // full parse is required to determine padding
465  m_fileInfo.setForceFullParse(true);
466 
467  // do the test under different conditions
468  for (m_mode = 0; m_mode != 0x20; ++m_mode) {
469  using namespace Mp4TestFlags;
470 
471  // setup test conditions
472 
473  m_fileInfo.setForceRewrite(m_mode & ForceRewring);
474  if (m_mode & KeepTagPos) {
475  m_fileInfo.setTagPosition(ElementPosition::Keep);
476  } else {
477  m_fileInfo.setTagPosition(m_mode & TagsBeforeData ? ElementPosition::BeforeData : ElementPosition::AfterData);
478  }
479  m_fileInfo.setIndexPosition(m_fileInfo.tagPosition());
480  m_fileInfo.setPreferredPadding(m_mode & PaddingConstraints ? 4096 : 0);
481  m_fileInfo.setMinPadding(m_mode & PaddingConstraints ? 1024 : 0);
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);
485 
486  // print test conditions
487  list<string> testConditions;
488  if (m_mode & ForceRewring) {
489  testConditions.emplace_back("forcing rewrite");
490  }
491  if (m_mode & KeepTagPos) {
492  if (m_mode & RemoveTagOrTrack) {
493  testConditions.emplace_back("removing tag");
494  } else {
495  testConditions.emplace_back("keeping tag position");
496  }
497  } else if (m_mode & TagsBeforeData) {
498  testConditions.emplace_back("tags before data");
499  } else {
500  testConditions.emplace_back("tags after data");
501  }
502  if (m_mode & PaddingConstraints) {
503  testConditions.emplace_back("padding constraints");
504  }
505  if (m_mode & ForceTagPos) {
506  testConditions.emplace_back("forcing tag position");
507  }
508  cerr << endl << "MP4 maker - testmode " << m_mode << ": " << joinStrings(testConditions, ", ") << endl;
509 
510  // do actual tests
511  // -> either remove tags or set test meta data
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);
520  // -> add/remove tracks
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);
524  }
525 }
526 #endif
void setPath(const std::string &path)
Sets the current file.
const std::string & documentType() const
Returns a string that describes the document type if available; otherwise returns an empty string...
std::size_t trackCount() const
Returns the number of tracks that could be parsed.
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.
ContainerFormat containerFormat() const
Returns the container format of the current file.
The Size class defines the size of a two-dimensional object using integer point precision.
Definition: size.h:16
DiagLevel level() const
Definition: diagnostics.cpp:32
The OverallTests class tests reading and writing tags and parsing technical information for all suppo...
Definition: overall.h:42
void tags(std::vector< Tag *> &tags) const
Stores all tags assigned to the current file in the specified vector.
void reopen(bool readonly=false)
Opens a std::fstream for the current file.
void setName(const std::string &name)
Sets the name.
void setForceFullParse(bool forceFullParse)
Sets whether forcing a full parse is enabled.
void parseTracks(Diagnostics &diag)
Parses the tracks of the current file.
AbstractContainer * container() const
Returns the container for the current file.
void parseContainerFormat(Diagnostics &diag)
Parses the container format of the current file.
Mp4Tag * mp4Tag() const
Returns a pointer to the assigned MP4 tag or nullptr if none is assigned.
void testMp4Parsing()
Tests the MP4 parser via MediaFileInfo.
Definition: overallmp4.cpp:445
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:343
std::vector< AbstractTrack * > tracks() const
Returns the tracks for the current file.
ElementPosition
Definition: settings.h:10
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.
Definition: mp4tag.cpp:58