4 #include "../diagnostics.h"
6 #include <initializer_list>
22 using namespace MatroskaTagIds;
30 case KnownField::RecordDate:
38 case KnownField::PartNumber:
40 case KnownField::TotalParts:
44 case KnownField::EncoderSettings:
64 case KnownField::Length:
66 case KnownField::Language:
73 KnownField MatroskaTag::internallyGetKnownField(
const IdentifierType &
id)
const
75 using namespace MatroskaTagIds;
76 static const map<string, KnownField> fieldMap({
88 {
bps(), KnownField::Bps },
97 {
language(), KnownField::Language },
99 const auto knownField(fieldMap.find(
id));
100 return knownField != fieldMap.cend() ? knownField->second : KnownField::Invalid;
112 static const string context(
"parsing Matroska tag");
113 tagElement.
parse(diag);
114 if (tagElement.
totalSize() > numeric_limits<std::uint32_t>::max()) {
116 diag.emplace_back(DiagLevel::Critical,
"Matroska tag is too big.", context);
119 m_size = static_cast<std::uint32_t>(tagElement.
totalSize());
122 switch (child->id()) {
126 field.
reparse(*child, diag,
true);
127 fields().emplace(field.
id(), move(field));
132 parseTargets(*child, diag);
147 static const string context(
"parsing targets of Matroska tag");
149 bool targetTypeValueFound =
false;
150 bool targetTypeFound =
false;
151 targetsElement.
parse(diag);
155 }
catch (
const Failure &) {
156 diag.emplace_back(DiagLevel::Critical,
"Unable to parse childs of Targets element.", context);
159 switch (child->id()) {
161 if (!targetTypeValueFound) {
162 m_target.setLevel(child->readUInteger());
163 targetTypeValueFound =
true;
166 DiagLevel::Warning,
"Targets element contains multiple TargetTypeValue elements. Surplus elements will be ignored.", context);
170 if (!targetTypeFound) {
171 m_target.setLevelName(child->readString());
172 targetTypeFound =
true;
175 DiagLevel::Warning,
"Targets element contains multiple TargetType elements. Surplus elements will be ignored.", context);
179 m_target.tracks().emplace_back(child->readUInteger());
182 m_target.editions().emplace_back(child->readUInteger());
185 m_target.chapters().emplace_back(child->readUInteger());
188 m_target.attachments().emplace_back(child->readUInteger());
191 diag.emplace_back(DiagLevel::Warning,
"Targets element contains unknown element. It will be ignored.", context);
194 if (!m_target.level()) {
195 m_target.setLevel(50);
210 MatroskaTagMaker::MatroskaTagMaker(MatroskaTag &tag, Diagnostics &diag)
215 if (m_tag.target().level() != 50) {
219 if (!m_tag.target().levelName().empty()) {
223 for (
const auto &v : initializer_list<vector<std::uint64_t>>{
224 m_tag.target().tracks(), m_tag.target().editions(), m_tag.target().chapters(), m_tag.target().attachments() }) {
232 m_maker.reserve(m_tag.fields().size());
233 m_simpleTagsSize = 0;
234 for (
auto &pair : m_tag.fields()) {
236 m_maker.emplace_back(pair.second.prepareMaking(diag));
237 m_simpleTagsSize += m_maker.back().requiredSize();
238 }
catch (
const Failure &) {
241 m_tagSize += m_simpleTagsSize;
257 stream.write(buff, 2);
259 stream.write(buff, len);
262 stream.write(buff, 2);
264 stream.write(buff, len);
266 if (t.
level() != 50) {
269 stream.write(buff, 2);
271 stream.put(static_cast<char>(0x80 | len));
272 stream.write(buff, len);
277 stream.write(buff, 2);
279 stream.write(buff, len);
283 using p = pair<std::uint16_t, vector<std::uint64_t>>;
286 if (!pair.second.empty()) {
287 BE::getBytes(pair.first, buff);
288 for (
auto uid : pair.second) {
290 *(buff + 2) = static_cast<char>(0x80 | len);
291 stream.write(buff, 3 + len);
296 for (
const auto &maker : m_maker) {