Tag Parser 12.1.0
C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags
Loading...
Searching...
No Matches
overallogg.cpp
Go to the documentation of this file.
1#include "./helper.h"
2#include "./overall.h"
3
4#include "../abstracttrack.h"
5#include "../tag.h"
6#include "../vorbis/vorbiscomment.h"
7
8#include <c++utilities/io/misc.h>
9
10#include <functional>
11
12using namespace CppUtilities;
13
17void OverallTests::checkOggTestfile1()
18{
19 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Ogg, m_fileInfo.containerFormat());
20 const auto tracks = m_fileInfo.tracks();
21 CPPUNIT_ASSERT_EQUAL(2_st, tracks.size());
22 for (const auto &track : tracks) {
23 switch (track->id()) {
24 case 897658443:
25 CPPUNIT_ASSERT_EQUAL(MediaType::Video, track->mediaType());
26 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Theora, track->format().general);
27 break;
28 case 1755441791:
29 CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
30 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Vorbis, track->format().general);
31 CPPUNIT_ASSERT_EQUAL(static_cast<std::uint16_t>(2), track->channelCount());
32 CPPUNIT_ASSERT_EQUAL(44100u, track->samplingFrequency());
33 CPPUNIT_ASSERT_EQUAL(4, track->duration().minutes());
34 break;
35 default:
36 CPPUNIT_FAIL("unknown track ID");
37 }
38 }
39 const auto tags = m_fileInfo.tags();
40 switch (m_tagStatus) {
42 CPPUNIT_ASSERT(m_fileInfo.hasAnyTag());
43 CPPUNIT_ASSERT_EQUAL(1_st, tags.size());
44 CPPUNIT_ASSERT_EQUAL("ffmpeg2theora 0.13"s, tags.front()->value(KnownField::Encoder).toString());
45 CPPUNIT_ASSERT_EQUAL(std::vector<std::uint64_t>{ 0x68a1ea7f }, tags.front()->target().tracks());
46 // Theora tags are currently not supported and hence only the Vorbis comment is
47 // taken into account here
48 break;
50 checkOggTestMetaData();
51 break;
53 CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
54 }
55
56 CPPUNIT_ASSERT(m_diag.level() <= DiagLevel::Information);
57}
58
62void OverallTests::checkOggTestfile2()
63{
64 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Ogg, m_fileInfo.containerFormat());
65 const auto tracks = m_fileInfo.tracks();
66 CPPUNIT_ASSERT_EQUAL(1_st, tracks.size());
67 for (const auto &track : tracks) {
68 switch (track->id()) {
69 case 1375632254:
70 CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
71 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Opus, track->format().general);
72 CPPUNIT_ASSERT_EQUAL(static_cast<std::uint16_t>(2), track->channelCount());
73 CPPUNIT_ASSERT_EQUAL(48000u, track->samplingFrequency());
74 CPPUNIT_ASSERT_EQUAL(1, track->duration().minutes());
75 break;
76 default:
77 CPPUNIT_FAIL("unknown track ID");
78 }
79 }
80 const auto tags = m_fileInfo.tags();
81 switch (m_tagStatus) {
83 CPPUNIT_ASSERT(m_fileInfo.hasAnyTag());
84 CPPUNIT_ASSERT_EQUAL(1_st, tags.size());
85 CPPUNIT_ASSERT_EQUAL("opusenc from opus-tools 0.1.6"s, tags.front()->value(KnownField::Encoder).toString());
86 break;
88 checkOggTestMetaData();
89 break;
91 CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
92 }
93
94 CPPUNIT_ASSERT(m_diag.level() <= DiagLevel::Information);
95}
96
100void OverallTests::checkOggTestfile3()
101{
102 CPPUNIT_ASSERT_EQUAL(ContainerFormat::Ogg, m_fileInfo.containerFormat());
103 const auto tracks = m_fileInfo.tracks();
104 CPPUNIT_ASSERT_EQUAL(1_st, tracks.size());
105 for (const auto &track : tracks) {
106 switch (track->id()) {
107 case 1843569915:
108 CPPUNIT_ASSERT_EQUAL(MediaType::Audio, track->mediaType());
109 CPPUNIT_ASSERT_EQUAL(GeneralMediaFormat::Opus, track->format().general);
110 CPPUNIT_ASSERT_EQUAL(static_cast<std::uint16_t>(2), track->channelCount());
111 CPPUNIT_ASSERT_EQUAL(48000u, track->samplingFrequency());
112 CPPUNIT_ASSERT_EQUAL(TimeSpan::fromSeconds(19.461), track->duration());
113 break;
114 default:
115 CPPUNIT_FAIL("unknown track ID");
116 }
117 }
118 const auto tags = m_fileInfo.tags();
119 switch (m_tagStatus) {
121 CPPUNIT_ASSERT(m_fileInfo.hasAnyTag());
122 CPPUNIT_ASSERT_EQUAL(1_st, tags.size());
123 CPPUNIT_ASSERT_EQUAL("Lavf58.76.100"s, tags.front()->value(KnownField::Encoder).toString());
124 CPPUNIT_ASSERT_EQUAL("eng"s, tags.front()->value(KnownField::Language).toString());
125 [[fallthrough]];
127 checkOggTestMetaDataCover();
128 break;
130 CPPUNIT_ASSERT_EQUAL(0_st, tags.size());
131 }
132
133 if (m_tagStatus != TagStatus::Original) {
134 CPPUNIT_ASSERT_MESSAGE("no warnings for non-broken file", m_diag.level() <= DiagLevel::Information);
135 return;
136 }
137 CPPUNIT_ASSERT_EQUAL_MESSAGE("warning present", DiagLevel::Warning, m_diag.level());
138 for (const auto &msg : m_diag) {
139 if (msg.level() == DiagLevel::Warning) {
140 CPPUNIT_ASSERT_EQUAL_MESSAGE("warning due to broken segment termination", "3 bytes left in last segment."s, msg.message());
141 CPPUNIT_ASSERT_EQUAL_MESSAGE("warning relates to Vorbis comment", "parsing Vorbis comment"s, msg.context());
142 break;
143 }
144 }
145}
146
150void OverallTests::checkOggTestMetaData()
151{
152 // check whether a tag is assigned
153 const auto tags = m_fileInfo.tags();
154 const auto *const tag = m_fileInfo.vorbisComment();
155 CPPUNIT_ASSERT_EQUAL(1_st, tags.size());
156 CPPUNIT_ASSERT(tag != nullptr);
157
158 // check test meta data
159 CPPUNIT_ASSERT_EQUAL(m_testTitle, tag->value(KnownField::Title));
160 CPPUNIT_ASSERT_EQUAL(m_testComment.toString(), tag->value(KnownField::Comment).toString()); // loss of description is ok
161 CPPUNIT_ASSERT_EQUAL(m_testAlbum, tag->value(KnownField::Album));
162 CPPUNIT_ASSERT_EQUAL(m_preservedMetaData.front(), tag->value(KnownField::Artist));
163 CPPUNIT_ASSERT_EQUAL(m_testPosition, tag->value(KnownField::TrackPosition));
164 CPPUNIT_ASSERT_EQUAL(m_testPosition, tag->value(KnownField::DiskPosition));
165 // TODO: check more fields
166 m_preservedMetaData.pop();
167}
168
169void OverallTests::checkOggTestMetaDataCover()
170{
171 // check whether a tag is assigned
172 const auto tags = m_fileInfo.tags();
173 const auto *const tag = m_fileInfo.vorbisComment();
174 CPPUNIT_ASSERT_EQUAL(1_st, tags.size());
175 CPPUNIT_ASSERT(tag != nullptr);
176
177 const auto expectedCoverData = readFile(testFilePath("ogg/example-cover.png"));
178 CPPUNIT_ASSERT_EQUAL_MESSAGE("expected cover assigned", std::string_view(expectedCoverData), tag->value(KnownField::Cover).data());
179}
180
181void OverallTests::setOggTestMetaData()
182{
183 // ensure a tag exists
184 auto *const tag = m_fileInfo.createVorbisComment();
185
186 // assign test meta data
187 tag->setValue(KnownField::Title, m_testTitle);
188 tag->setValue(KnownField::Comment, m_testComment);
189 tag->setValue(KnownField::Album, m_testAlbum);
190 m_preservedMetaData.push(tag->value(KnownField::Artist));
191 tag->setValue(KnownField::TrackPosition, m_testPosition);
192 tag->setValue(KnownField::DiskPosition, m_testPosition);
193 // TODO: set more fields
194}
195
196void OverallTests::setOggTestMetaDataCover()
197{
198 auto *const tag = m_fileInfo.createVorbisComment();
199 const auto cover = readFile(testFilePath("ogg/example-cover.png"));
200 tag->setValue(KnownField::Cover, TagValue(cover.data(), cover.size(), TagDataType::Picture));
201}
202
208{
209 cerr << endl << "OGG parser" << endl;
210 m_fileInfo.setForceFullParse(false);
211 m_tagStatus = TagStatus::Original;
212 parseFile(testFilePath("mtx-test-data/ogg/qt4dance_medium.ogg"), &OverallTests::checkOggTestfile1);
213 parseFile(testFilePath("mtx-test-data/opus/v-opus.ogg"), &OverallTests::checkOggTestfile2);
214 parseFile(testFilePath("ogg/noise-broken-segment-termination.opus"), &OverallTests::checkOggTestfile3);
215}
216
224{
225 // full parse is required to determine padding
226 m_fileInfo.setForceFullParse(true);
227
228 // do the test under different conditions
229 for (m_mode = 0; m_mode != 0x2; ++m_mode) {
230 using namespace SimpleTestFlags;
231
232 // no need to setup test conditions because the Ogg maker
233 // doesn't take those settings into account (currently)
234
235 // print test conditions
236 list<string> testConditions;
237 if (m_mode & RemoveTag) {
238 testConditions.emplace_back("removing tag");
239 } else {
240 testConditions.emplace_back("modifying tag");
241 }
242 cerr << endl << "OGG maker - testmode " << m_mode << ": " << joinStrings(testConditions, ", ") << endl;
243
244 // do actual tests
245 m_tagStatus = (m_mode & RemoveTag) ? TagStatus::Removed : TagStatus::TestMetaDataPresent;
246 const auto modifyRoutine = (m_mode & RemoveTag) ? &OverallTests::removeAllTags : &OverallTests::setOggTestMetaData;
247 const auto modifyRoutineCover = (m_mode & RemoveTag) ? &OverallTests::removeAllTags : &OverallTests::setOggTestMetaDataCover;
248 makeFile(workingCopyPath("mtx-test-data/ogg/qt4dance_medium.ogg"), modifyRoutine, &OverallTests::checkOggTestfile1);
249 makeFile(workingCopyPath("mtx-test-data/opus/v-opus.ogg"), modifyRoutine, &OverallTests::checkOggTestfile2);
250 makeFile(workingCopyPath("ogg/noise-without-cover.opus"), modifyRoutineCover, &OverallTests::checkOggTestfile3);
251 }
252}
void testOggParsing()
Tests the Ogg parser via MediaFileInfo.
void testOggMaking()
Tests the Ogg maker via MediaFileInfo.
DiagLevel level() const
Returns the worst diag level present in the container.
std::vector< AbstractTrack * > tracks() const
Returns the tracks for the current file.
VorbisComment * createVorbisComment()
Creates a Vorbis comment for the current file.
VorbisComment * vorbisComment() const
Returns a pointer to the first assigned Vorbis comment or nullptr if none is assigned.
void setForceFullParse(bool forceFullParse)
Sets whether forcing a full parse is enabled.
void tags(std::vector< Tag * > &tags) const
Stores all tags assigned to the current file in the specified vector.
ContainerFormat containerFormat() const
Returns the container format of the current file.
bool hasAnyTag() const
Returns an indication whether a tag of any format is assigned.
The TagValue class wraps values of different types.
Definition tagvalue.h:147
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:450
bool setValue(KnownField field, const TagValue &value) override
Assigns the given value to the specified field.
constexpr TAG_PARSER_EXPORT std::string_view cover()
@ TestMetaDataPresent