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 default:
return string();
47 KnownField MatroskaTag::knownField(
const std::string &
id)
const 49 using namespace MatroskaTagIds;
50 static const map<string, KnownField> map({
62 {
bps(), KnownField::Bps},
74 }
catch(
const out_of_range &) {
75 return KnownField::Invalid;
89 static const string context(
"parsing Matroska tag");
100 fields().insert(make_pair(field.
id(), field));
103 addNotifications(context, field);
106 parseTargets(*child);
134 void MatroskaTag::make(ostream &stream)
136 prepareMaking().make(stream);
146 void MatroskaTag::parseTargets(
EbmlElement &targetsElement)
148 static const string context(
"parsing targets of Matroska tag");
150 bool targetTypeValueFound =
false;
151 bool targetTypeFound =
false;
152 targetsElement.
parse();
157 addNotification(NotificationType::Critical,
"Unable to parse childs of Targets element.", context);
160 switch(child->id()) {
162 if(!targetTypeValueFound) {
163 m_target.setLevel(child->readUInteger());
164 targetTypeValueFound =
true;
166 addNotification(NotificationType::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;
174 addNotification(NotificationType::Warning,
"Targets element contains multiple TargetType elements. Surplus elements will be ignored.", context);
178 m_target.tracks().emplace_back(child->readUInteger());
181 m_target.editions().emplace_back(child->readUInteger());
184 m_target.chapters().emplace_back(child->readUInteger());
187 m_target.attachments().emplace_back(child->readUInteger());
190 addNotification(NotificationType::Warning,
"Targets element contains unknown element. It will be ignored.", context);
193 if(!m_target.level()) {
194 m_target.setLevel(50);
209 MatroskaTagMaker::MatroskaTagMaker(
MatroskaTag &tag) :
214 if(m_tag.target().level() != 50) {
216 m_targetsSize += 2 + 1 + EbmlElement::calculateUIntegerLength(m_tag.target().level());
218 if(!m_tag.target().levelName().empty()) {
220 m_targetsSize += 2 + EbmlElement::calculateSizeDenotationLength(m_tag.target().levelName().size()) + m_tag.target().levelName().size();
222 for(
const auto &v : initializer_list<vector<uint64> >{m_tag.target().tracks(), m_tag.target().editions(), m_tag.target().chapters(), m_tag.target().attachments()}) {
225 m_targetsSize += 2 + 1 + EbmlElement::calculateUIntegerLength(uid);
228 m_tagSize = 2 + EbmlElement::calculateSizeDenotationLength(m_targetsSize) + m_targetsSize;
230 m_maker.reserve(m_tag.fields().size());
231 m_simpleTagsSize = 0;
232 for(
auto &pair : m_tag.fields()) {
234 m_maker.emplace_back(pair.second.prepareMaking());
235 m_simpleTagsSize += m_maker.back().requiredSize();
239 m_tag.addNotifications(pair.second);
241 m_tagSize += m_simpleTagsSize;
242 m_totalSize = 2 + EbmlElement::calculateSizeDenotationLength(m_tagSize) + m_tagSize;
252 void MatroskaTagMaker::make(ostream &stream)
const 257 stream.write(buff, 2);
258 byte len = EbmlElement::makeSizeDenotation(m_tagSize, buff);
259 stream.write(buff, len);
262 stream.write(buff, 2);
263 len = EbmlElement::makeSizeDenotation(m_targetsSize, buff);
264 stream.write(buff, len);
266 if(t.
level() != 50) {
269 stream.write(buff, 2);
270 len = EbmlElement::makeUInteger(t.
level(), buff);
271 stream.put(0x80 | len);
272 stream.write(buff, len);
277 stream.write(buff, 2);
278 len = EbmlElement::makeSizeDenotation(t.
levelName().size(), buff);
279 stream.write(buff, len);
283 typedef pair<uint16, vector<uint64> > p;
285 if(!pair.second.empty()) {
286 BE::getBytes(pair.first, buff);
287 for(
auto uid : pair.second) {
288 len = EbmlElement::makeUInteger(uid, buff + 3);
289 *(buff + 2) = 0x80 | len;
290 stream.write(buff, 3 + len);
296 for(
const auto &maker : m_maker) {