Tag Parser  6.3.0
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(tags.size() == 0);
57  }
58 }
59 
63 void OverallTests::checkMp4Testfile2()
64 {
65  CPPUNIT_ASSERT(m_fileInfo.containerFormat() == ContainerFormat::Mp4);
66  const auto tracks = m_fileInfo.tracks();
67  CPPUNIT_ASSERT_EQUAL(5_st, tracks.size());
68  for(const auto &track : tracks) {
69  switch(track->id()) {
70  case 1:
71  CPPUNIT_ASSERT(track->mediaType() == MediaType::Video);
72  CPPUNIT_ASSERT(track->format() == GeneralMediaFormat::Avc);
73  CPPUNIT_ASSERT(track->format().sub == SubFormats::AvcHighProfile);
74  CPPUNIT_ASSERT_EQUAL(4.0, track->version());
75  CPPUNIT_ASSERT(track->creationTime().year() == 2013);
76  CPPUNIT_ASSERT(track->pixelSize() == Size(1920, 750));
77  break;
78  case 2:
79  CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
80  CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Aac, track->format().general);
81  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned char>(SubFormats::AacMpeg4LowComplexityProfile), track->format().sub);
82  CPPUNIT_ASSERT(!(track->format().extension & ExtensionFormats::SpectralBandReplication));
83  CPPUNIT_ASSERT(!(track->format().extension & ExtensionFormats::ParametricStereo));
84  CPPUNIT_ASSERT_EQUAL("eng"s, track->language());
85  CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
86  CPPUNIT_ASSERT_EQUAL(48000u, track->samplingFrequency());
87  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned char>(Mpeg4ChannelConfigs::FrontLeftFrontRight), track->channelConfig());
88  break;
89  case 3:
90  CPPUNIT_ASSERT(track->mediaType() == MediaType::Audio);
91  CPPUNIT_ASSERT(track->format() == GeneralMediaFormat::Ac3);
92  CPPUNIT_ASSERT_EQUAL("eng"s, track->language());
93  CPPUNIT_ASSERT(track->creationTime().year() == 2013);
94  break;
95  case 4:
96  CPPUNIT_ASSERT(track->mediaType() == MediaType::Audio);
97  CPPUNIT_ASSERT(track->format() == GeneralMediaFormat::DtsHd);
98  CPPUNIT_ASSERT_EQUAL("eng"s, track->language());
99  CPPUNIT_ASSERT(track->creationTime().year() == 2013);
100  break;
101  case 6:
102  CPPUNIT_ASSERT(track->mediaType() == MediaType::Text);
103  CPPUNIT_ASSERT(track->format() == GeneralMediaFormat::TimedText);
104  CPPUNIT_ASSERT(track->creationTime().year() == 2013);
105  break;
106  default:
107  CPPUNIT_FAIL("unknown track ID");
108  }
109  }
110  const auto tags = m_fileInfo.tags();
111  switch(m_tagStatus) {
112  case TagStatus::Original:
113  CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
114  break;
116  checkMp4TestMetaData();
117  break;
118  case TagStatus::Removed:
119  CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
120  }
121 }
122 
126 void OverallTests::checkMp4Testfile3()
127 {
128  CPPUNIT_ASSERT(m_fileInfo.containerFormat() == ContainerFormat::Mp4);
129  CPPUNIT_ASSERT(m_fileInfo.container() && m_fileInfo.container()->documentType() == "dash");
130  const auto tracks = m_fileInfo.tracks();
131  CPPUNIT_ASSERT(tracks.size() == 1);
132  for(const auto &track : tracks) {
133  switch(track->id()) {
134  case 1:
135  CPPUNIT_ASSERT(track->mediaType() == MediaType::Video);
136  CPPUNIT_ASSERT(track->format() == GeneralMediaFormat::Avc);
137  CPPUNIT_ASSERT(track->format().sub == SubFormats::AvcMainProfile);
138  CPPUNIT_ASSERT(track->version() == 3.1);
139  CPPUNIT_ASSERT(track->creationTime().year() == 2014);
140  CPPUNIT_ASSERT(track->pixelSize() == Size(854, 480));
141  CPPUNIT_ASSERT(!strcmp(track->chromaFormat(), "YUV 4:2:0"));
142  break;
143  default:
144  CPPUNIT_FAIL("unknown track ID");
145  }
146  }
147  const auto tags = m_fileInfo.tags();
148  switch(m_tagStatus) {
149  case TagStatus::Original:
150  CPPUNIT_ASSERT(tags.size() == 0);
151  break;
153  checkMp4TestMetaData();
154  break;
155  case TagStatus::Removed:
156  CPPUNIT_ASSERT(tags.size() == 0);
157  }
158 }
159 
163 void OverallTests::checkMp4Testfile4()
164 {
165  CPPUNIT_ASSERT(m_fileInfo.containerFormat() == ContainerFormat::Mp4);
166  CPPUNIT_ASSERT(m_fileInfo.container() && m_fileInfo.container()->documentType() == "M4A ");
167  const auto tracks = m_fileInfo.tracks();
168  CPPUNIT_ASSERT(tracks.size() == 1);
169  for(const auto &track : tracks) {
170  switch(track->id()) {
171  case 1:
172  CPPUNIT_ASSERT(track->mediaType() == MediaType::Audio);
173  CPPUNIT_ASSERT(track->format() == GeneralMediaFormat::Alac);
174  CPPUNIT_ASSERT(track->creationTime().year() == 2008);
175  CPPUNIT_ASSERT(track->channelCount() == 2);
176  CPPUNIT_ASSERT(track->bitsPerSample() == 16);
177  break;
178  default:
179  CPPUNIT_FAIL("unknown track ID");
180  }
181  }
182  const auto tags = m_fileInfo.tags();
183  switch(m_tagStatus) {
184  case TagStatus::Original:
185  CPPUNIT_ASSERT(tags.size() == 1);
186  CPPUNIT_ASSERT(tags.front()->value(KnownField::Title).toString() == "Sad Song");
187  CPPUNIT_ASSERT(tags.front()->value(KnownField::Artist).toString() == "Oasis");
188  CPPUNIT_ASSERT(tags.front()->value(KnownField::Album).toString() == "Don't Go Away (Apple Lossless)");
189  CPPUNIT_ASSERT(tags.front()->value(KnownField::Genre).toString() == "Alternative & Punk");
190  CPPUNIT_ASSERT(tags.front()->value(KnownField::Encoder).toString() == "iTunes v7.5.0.20");
191  CPPUNIT_ASSERT(tags.front()->value(KnownField::Year).toString() == "1998");
192  CPPUNIT_ASSERT(tags.front()->value(KnownField::Comment).isEmpty());
193  CPPUNIT_ASSERT(tags.front()->value(KnownField::Cover).dataSize() == 0x58f3);
194  CPPUNIT_ASSERT(BE::toUInt64(tags.front()->value(KnownField::Cover).dataPointer()) == 0xFFD8FFE000104A46);
195  CPPUNIT_ASSERT(tags.front()->value(KnownField::TrackPosition).toPositionInSet() == PositionInSet(3, 4));
196  CPPUNIT_ASSERT(tags.front()->value(KnownField::DiskPosition).toPositionInSet() == PositionInSet(1, 1));
197  break;
199  checkMp4TestMetaData();
200  break;
201  case TagStatus::Removed:
202  CPPUNIT_ASSERT(tags.size() == 0);
203  }
204 }
205 
209 void OverallTests::checkMp4Testfile5()
210 {
211  CPPUNIT_ASSERT(m_fileInfo.containerFormat() == ContainerFormat::Mp4);
212  CPPUNIT_ASSERT(m_fileInfo.container() && m_fileInfo.container()->documentType() == "mp42");
213  const auto tracks = m_fileInfo.tracks();
214  CPPUNIT_ASSERT(tracks.size() == 1);
215  for(const auto &track : tracks) {
216  switch(track->id()) {
217  case 1:
218  CPPUNIT_ASSERT(track->mediaType() == MediaType::Audio);
219  CPPUNIT_ASSERT(track->format() == GeneralMediaFormat::Aac);
220  CPPUNIT_ASSERT(track->format().sub == SubFormats::AacMpeg4LowComplexityProfile);
221  CPPUNIT_ASSERT(track->format().extension & ExtensionFormats::SpectralBandReplication);
222  CPPUNIT_ASSERT(track->format().extension & ExtensionFormats::ParametricStereo);
223  CPPUNIT_ASSERT(track->creationTime().year() == 2014);
224  CPPUNIT_ASSERT(track->channelCount() == 2);
225  CPPUNIT_ASSERT(track->channelConfig() == Mpeg4ChannelConfigs::FrontCenter);
226  CPPUNIT_ASSERT(track->extensionChannelConfig() == Mpeg4ChannelConfigs::FrontLeftFrontRight);
227  CPPUNIT_ASSERT(track->samplingFrequency() == 24000);
228  CPPUNIT_ASSERT(track->extensionSamplingFrequency() == 48000);
229  CPPUNIT_ASSERT(track->bitsPerSample() == 16);
230  break;
231  default:
232  CPPUNIT_FAIL("unknown track ID");
233  }
234  }
235  const auto tags = m_fileInfo.tags();
236  switch(m_tagStatus) {
237  case TagStatus::Original:
238  CPPUNIT_ASSERT(tags.size() == 0);
239  break;
241  checkMp4TestMetaData();
242  break;
243  case TagStatus::Removed:
244  CPPUNIT_ASSERT(tags.size() == 0);
245  }
246 }
247 
251 void OverallTests::checkMp4Testfile6()
252 {
253  CPPUNIT_ASSERT(m_fileInfo.containerFormat() == ContainerFormat::Mp4);
254  const auto tracks = m_fileInfo.tracks();
255  if(m_mode & Mp4TestFlags::RemoveTagOrTrack) {
256  CPPUNIT_ASSERT(tracks.size() == 4);
257  } else {
258  CPPUNIT_ASSERT(tracks.size() == 6);
259  }
260  bool track2Present = false, track5Present = false;
261  for(const auto &track : tracks) {
262  switch(track->id()) {
263  case 1:
264  CPPUNIT_ASSERT(track->mediaType() == MediaType::Video);
265  CPPUNIT_ASSERT(track->format() == GeneralMediaFormat::Avc);
266  CPPUNIT_ASSERT(track->format().sub == SubFormats::AvcHighProfile);
267  CPPUNIT_ASSERT(track->version() == 4);
268  CPPUNIT_ASSERT(track->creationTime().year() == 2013);
269  CPPUNIT_ASSERT(track->pixelSize() == Size(1920, 750));
270  break;
271  case 2:
272  CPPUNIT_ASSERT(track2Present = !track2Present);
273  CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
274  CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Aac, track->format().general);
275  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned char>(SubFormats::AacMpeg4LowComplexityProfile), track->format().sub);
276  CPPUNIT_ASSERT(!(track->format().extension & ExtensionFormats::SpectralBandReplication));
277  CPPUNIT_ASSERT(!(track->format().extension & ExtensionFormats::ParametricStereo));
278  CPPUNIT_ASSERT_EQUAL("eng"s, track->language());
279  CPPUNIT_ASSERT_EQUAL(2013, track->creationTime().year());
280  CPPUNIT_ASSERT_EQUAL(48000u, track->samplingFrequency());
281  CPPUNIT_ASSERT_EQUAL(static_cast<unsigned char>(Mpeg4ChannelConfigs::FrontLeftFrontRight), track->channelConfig());
282  break;
283  case 3:
284  CPPUNIT_ASSERT(track->mediaType() == MediaType::Audio);
285  CPPUNIT_ASSERT(track->format() == GeneralMediaFormat::Ac3);
286  CPPUNIT_ASSERT(track->language() == "eng");
287  CPPUNIT_ASSERT(track->creationTime().year() == 2013);
288  break;
289  case 4:
290  CPPUNIT_ASSERT(track->mediaType() == MediaType::Audio);
291  CPPUNIT_ASSERT(track->format() == GeneralMediaFormat::DtsHd);
292  CPPUNIT_ASSERT(track->language() == "eng");
293  CPPUNIT_ASSERT(track->creationTime().year() == 2013);
294  break;
295  case 5:
296  CPPUNIT_ASSERT(track5Present = !track5Present);
297  CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
298  CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Aac, track->format().general);
299  CPPUNIT_ASSERT_EQUAL(2012, track->creationTime().year());
300  CPPUNIT_ASSERT_EQUAL(44100u, track->samplingFrequency());
301  CPPUNIT_ASSERT_EQUAL(static_cast<byte>(Mpeg4ChannelConfigs::FrontLeftFrontRight), track->channelConfig());
302  break;
303  case 6:
304  CPPUNIT_ASSERT(track->mediaType() == MediaType::Text);
305  CPPUNIT_ASSERT(track->format() == GeneralMediaFormat::TimedText);
306  CPPUNIT_ASSERT(track->creationTime().year() == 2013);
307  break;
308  default:
309  CPPUNIT_FAIL("unknown track ID");
310  }
311  }
312  if(m_mode & Mp4TestFlags::RemoveTagOrTrack) {
313  CPPUNIT_ASSERT(!track2Present);
314  CPPUNIT_ASSERT(!track5Present);
315  } else {
316  CPPUNIT_ASSERT(track2Present);
317  CPPUNIT_ASSERT(track5Present);
318  }
319 
320  CPPUNIT_ASSERT(m_fileInfo.tags().size() == 0);
321 }
322 
326 void OverallTests::checkMp4TestMetaData()
327 {
328  // check whether a tag is assigned
329  const auto tags = m_fileInfo.tags();
330  Mp4Tag *tag = m_fileInfo.mp4Tag();
331  CPPUNIT_ASSERT(tags.size() == 1);
332  CPPUNIT_ASSERT(tag != nullptr);
333 
334  // check test meta data
335  CPPUNIT_ASSERT_EQUAL(m_testTitle, tag->value(KnownField::Title));
336  CPPUNIT_ASSERT_EQUAL(m_testComment.toString(), tag->value(KnownField::Comment).toString()); // loss of description is ok
337  CPPUNIT_ASSERT_EQUAL(m_testAlbum, tag->value(KnownField::Album));
338  CPPUNIT_ASSERT_EQUAL(m_preservedMetaData.front(), tag->value(KnownField::Artist));
339  CPPUNIT_ASSERT_EQUAL(m_testPosition, tag->value(KnownField::TrackPosition));
340  CPPUNIT_ASSERT_EQUAL(m_testPosition, tag->value(KnownField::DiskPosition));
341 
342  // TODO: check more fields
343  m_preservedMetaData.pop();
344 }
345 
349 void OverallTests::checkMp4Constraints()
350 {
351  using namespace Mp4TestFlags;
352 
353  CPPUNIT_ASSERT(m_fileInfo.container());
354  if(m_mode & PaddingConstraints) {
355  if(m_mode & ForceRewring) {
356  CPPUNIT_ASSERT_EQUAL(4096_st, m_fileInfo.paddingSize());
357  } else {
358  CPPUNIT_ASSERT(m_fileInfo.paddingSize() >= 1024);
359  CPPUNIT_ASSERT(m_fileInfo.paddingSize() <= (4096 + 1024));
360  }
361  if(!(m_mode & RemoveTagOrTrack) && (m_fileInfo.container()->documentType() != "dash") && ((m_mode & ForceRewring) || (m_mode & ForceTagPos))) {
362  const ElementPosition currentTagPos = m_fileInfo.container()->determineTagPosition();
363  if(currentTagPos == ElementPosition::Keep) {
364  CPPUNIT_ASSERT_EQUAL(m_expectedTagPos, m_fileInfo.container()->determineIndexPosition());
365  }
366  }
367  }
368 }
369 
373 void OverallTests::setMp4TestMetaData()
374 {
375  // ensure a tag exists
376  Tag *tag = m_fileInfo.container()->createTag();
377 
378  // assign test meta data
379  tag->setValue(KnownField::Title, m_testTitle);
380  tag->setValue(KnownField::Comment, m_testComment);
381  tag->setValue(KnownField::Album, m_testAlbum);
382  m_preservedMetaData.push(tag->value(KnownField::Artist));
383  tag->setValue(KnownField::TrackPosition, m_testPosition);
384  tag->setValue(KnownField::DiskPosition, m_testPosition);
385  // TODO: set more fields
386 }
387 
391 void OverallTests::addMp4Track()
392 {
393  m_additionalFileInfo.setPath(TestUtilities::testFilePath("mtx-test-data/mp4/10-DanseMacabreOp.40.m4a"));
394  m_additionalFileInfo.reopen(true);
395  m_additionalFileInfo.parseContainerFormat();
396  m_additionalFileInfo.parseTracks();
397  CPPUNIT_ASSERT_EQUAL(ContainerFormat::Mp4, m_additionalFileInfo.containerFormat());
398  CPPUNIT_ASSERT_EQUAL(ContainerFormat::Mp4, m_fileInfo.containerFormat());
399  const auto &tracks = m_additionalFileInfo.tracks();
400  CPPUNIT_ASSERT_EQUAL(1_st, tracks.size());
401  CPPUNIT_ASSERT_EQUAL(TrackType::Mp4Track, tracks[0]->type());
402  auto *track = static_cast<Mp4Track *>(tracks[0]);
403  CPPUNIT_ASSERT(static_cast<Mp4Container *>(m_additionalFileInfo.container())->removeTrack(track));
404  static_cast<Mp4Container *>(m_fileInfo.container())->addTrack(track);
405 }
406 
411 {
412  cerr << endl << "MP4 parser" << endl;
413  m_fileInfo.setForceFullParse(false);
414  m_tagStatus = TagStatus::Original;
415  parseFile(TestUtilities::testFilePath("mtx-test-data/mp4/10-DanseMacabreOp.40.m4a"), &OverallTests::checkMp4Testfile1);
416  parseFile(TestUtilities::testFilePath("mtx-test-data/mp4/1080p-DTS-HD-7.1.mp4"), &OverallTests::checkMp4Testfile2);
417  parseFile(TestUtilities::testFilePath("mtx-test-data/mp4/dash/dragon-age-inquisition-H1LkM6IVlm4-video.mp4"), &OverallTests::checkMp4Testfile3);
418  parseFile(TestUtilities::testFilePath("mtx-test-data/alac/othertest-itunes.m4a"), &OverallTests::checkMp4Testfile4);
419  parseFile(TestUtilities::testFilePath("mtx-test-data/aac/he-aacv2-ps.m4a"), &OverallTests::checkMp4Testfile5);
420 }
421 
422 #ifdef PLATFORM_UNIX
423 
427 void OverallTests::testMp4Making()
428 {
429  // full parse is required to determine padding
430  m_fileInfo.setForceFullParse(true);
431 
432  // do the test under different conditions
433  for(m_mode = 0; m_mode != 0x20; ++m_mode) {
434  using namespace Mp4TestFlags;
435 
436  // setup test conditions
437 
438  m_fileInfo.setForceRewrite(m_mode & ForceRewring);
439  if(m_mode & KeepTagPos) {
440  m_fileInfo.setTagPosition(ElementPosition::Keep);
441  } else {
442  m_fileInfo.setTagPosition(m_mode & TagsBeforeData ? ElementPosition::BeforeData : ElementPosition::AfterData);
443  }
444  m_fileInfo.setIndexPosition(m_fileInfo.tagPosition());
445  m_fileInfo.setPreferredPadding(m_mode & PaddingConstraints ? 4096 : 0);
446  m_fileInfo.setMinPadding(m_mode & PaddingConstraints ? 1024 : 0);
447  m_fileInfo.setMaxPadding(m_mode & PaddingConstraints ? (4096 + 1024) : static_cast<size_t>(-1));
448  m_fileInfo.setForceTagPosition(m_mode & ForceTagPos);
449  m_fileInfo.setForceIndexPosition(m_mode & ForceTagPos);
450 
451  // print test conditions
452  list<string> testConditions;
453  if(m_mode & ForceRewring) {
454  testConditions.emplace_back("forcing rewrite");
455  }
456  if(m_mode & KeepTagPos) {
457  if(m_mode & RemoveTagOrTrack) {
458  testConditions.emplace_back("removing tag");
459  } else {
460  testConditions.emplace_back("keeping tag position");
461  }
462  } else if(m_mode & TagsBeforeData) {
463  testConditions.emplace_back("tags before data");
464  } else {
465  testConditions.emplace_back("tags after data");
466  }
467  if(m_mode & PaddingConstraints) {
468  testConditions.emplace_back("padding constraints");
469  }
470  if(m_mode & ForceTagPos) {
471  testConditions.emplace_back("forcing tag position");
472  }
473  cerr << endl << "MP4 maker - testmode " << m_mode << ": " << joinStrings(testConditions, ", ") << endl;
474 
475  // do actual tests
476  // -> either remove tags or set test meta data
478  void (OverallTests::*modifyRoutine)(void) = (m_mode & RemoveTagOrTrack) ? &OverallTests::removeAllTags : &OverallTests::setMp4TestMetaData;
479  makeFile(TestUtilities::workingCopyPath("mtx-test-data/mp4/10-DanseMacabreOp.40.m4a"), modifyRoutine, &OverallTests::checkMp4Testfile1);
480  makeFile(TestUtilities::workingCopyPath("mtx-test-data/mp4/1080p-DTS-HD-7.1.mp4"), modifyRoutine, &OverallTests::checkMp4Testfile2);
481  makeFile(TestUtilities::workingCopyPath("mtx-test-data/mp4/dash/dragon-age-inquisition-H1LkM6IVlm4-video.mp4"), modifyRoutine, &OverallTests::checkMp4Testfile3);
482  makeFile(TestUtilities::workingCopyPath("mtx-test-data/alac/othertest-itunes.m4a"), modifyRoutine, &OverallTests::checkMp4Testfile4);
483  makeFile(TestUtilities::workingCopyPath("mtx-test-data/aac/he-aacv2-ps.m4a"), modifyRoutine, &OverallTests::checkMp4Testfile5);
484  // -> add/remove tracks
485  modifyRoutine = (m_mode & RemoveTagOrTrack) ? &OverallTests::removeSecondTrack : &OverallTests::addMp4Track;
486  m_fileInfo.setTagPosition(ElementPosition::Keep);
487  makeFile(TestUtilities::workingCopyPath("mtx-test-data/mp4/1080p-DTS-HD-7.1.mp4"), modifyRoutine, &OverallTests::checkMp4Testfile6);
488  }
489 }
490 #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:119
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:43
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 testMp4Parsing()
Tests the MP4 parser via MediaFileInfo.
Definition: overallmp4.cpp:410
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:316
virtual const TagValue & value(KnownField field) const =0
Returns the value of the specified field.