5 #include <initializer_list> 20 using namespace MatroskaTagIds;
29 case KnownField::PartNumber:
return partNumber();
30 case KnownField::TotalParts:
return totalParts();
34 case KnownField::Bps:
return bps();
42 case KnownField::Length:
return duration();
43 case KnownField::Language:
return language();
44 default:
return string();
48 KnownField MatroskaTag::knownField(
const std::string &
id)
const 50 using namespace MatroskaTagIds;
51 static const map<string, KnownField> map({
63 {
bps(), KnownField::Bps},
76 }
catch(
const out_of_range &) {
77 return KnownField::Invalid;
91 static const string context(
"parsing Matroska tag");
102 fields().insert(make_pair(field.
id(), field));
105 addNotifications(context, field);
108 parseTargets(*child);
136 void MatroskaTag::make(ostream &stream)
138 prepareMaking().make(stream);
148 void MatroskaTag::parseTargets(
EbmlElement &targetsElement)
150 static const string context(
"parsing targets of Matroska tag");
152 bool targetTypeValueFound =
false;
153 bool targetTypeFound =
false;
154 targetsElement.
parse();
159 addNotification(NotificationType::Critical,
"Unable to parse childs of Targets element.", context);
162 switch(child->id()) {
164 if(!targetTypeValueFound) {
165 m_target.setLevel(child->readUInteger());
166 targetTypeValueFound =
true;
168 addNotification(NotificationType::Warning,
"Targets element contains multiple TargetTypeValue elements. Surplus elements will be ignored.", context);
172 if(!targetTypeFound) {
173 m_target.setLevelName(child->readString());
174 targetTypeFound =
true;
176 addNotification(NotificationType::Warning,
"Targets element contains multiple TargetType elements. Surplus elements will be ignored.", context);
180 m_target.tracks().emplace_back(child->readUInteger());
183 m_target.editions().emplace_back(child->readUInteger());
186 m_target.chapters().emplace_back(child->readUInteger());
189 m_target.attachments().emplace_back(child->readUInteger());
192 addNotification(NotificationType::Warning,
"Targets element contains unknown element. It will be ignored.", context);
195 if(!m_target.level()) {
196 m_target.setLevel(50);
211 MatroskaTagMaker::MatroskaTagMaker(
MatroskaTag &tag) :
216 if(m_tag.target().level() != 50) {
218 m_targetsSize += 2 + 1 + EbmlElement::calculateUIntegerLength(m_tag.target().level());
220 if(!m_tag.target().levelName().empty()) {
222 m_targetsSize += 2 + EbmlElement::calculateSizeDenotationLength(m_tag.target().levelName().size()) + m_tag.target().levelName().size();
224 for(
const auto &v : initializer_list<vector<uint64> >{m_tag.target().tracks(), m_tag.target().editions(), m_tag.target().chapters(), m_tag.target().attachments()}) {
227 m_targetsSize += 2 + 1 + EbmlElement::calculateUIntegerLength(uid);
230 m_tagSize = 2 + EbmlElement::calculateSizeDenotationLength(m_targetsSize) + m_targetsSize;
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());
237 m_simpleTagsSize += m_maker.back().requiredSize();
241 m_tag.addNotifications(pair.second);
243 m_tagSize += m_simpleTagsSize;
244 m_totalSize = 2 + EbmlElement::calculateSizeDenotationLength(m_tagSize) + m_tagSize;
254 void MatroskaTagMaker::make(ostream &stream)
const 259 stream.write(buff, 2);
260 byte len = EbmlElement::makeSizeDenotation(m_tagSize, buff);
261 stream.write(buff, len);
264 stream.write(buff, 2);
265 len = EbmlElement::makeSizeDenotation(m_targetsSize, buff);
266 stream.write(buff, len);
268 if(t.
level() != 50) {
271 stream.write(buff, 2);
272 len = EbmlElement::makeUInteger(t.
level(), buff);
273 stream.put(0x80 | len);
274 stream.write(buff, len);
279 stream.write(buff, 2);
280 len = EbmlElement::makeSizeDenotation(t.
levelName().size(), buff);
281 stream.write(buff, len);
285 typedef pair<uint16, vector<uint64> > p;
287 if(!pair.second.empty()) {
288 BE::getBytes(pair.first, buff);
289 for(
auto uid : pair.second) {
290 len = EbmlElement::makeUInteger(uid, buff + 3);
291 *(buff + 2) = 0x80 | len;
292 stream.write(buff, 3 + len);
298 for(
const auto &maker : m_maker) {