4 #include <c++utilities/conversion/binaryconversion.h> 38 uint64 MatroskaCuePositionUpdater::totalSize()
const 41 uint64 size = m_sizes.at(m_cuesElement);
42 return 4 + EbmlElement::calculateSizeDenotationLength(size) + size;
52 void MatroskaCuePositionUpdater::parse(
EbmlElement *cuesElement)
54 static const string context(
"parsing \"Cues\"-element");
56 uint64 cuesElementSize = 0, cuePointElementSize, cueTrackPositionsElementSize, cueReferenceElementSize, pos, relPos, statePos;
57 EbmlElement *cueRelativePositionElement, *cueClusterPositionElement;
58 for(
EbmlElement *cuePointElement = cuesElement->
firstChild(); cuePointElement; cuePointElement = cuePointElement->nextSibling()) {
60 cuePointElement->
parse();
61 switch(cuePointElement->id()) {
66 cuePointElementSize = 0;
67 for(
EbmlElement *cuePointChild = cuePointElement->
firstChild(); cuePointChild; cuePointChild = cuePointChild->nextSibling()) {
69 cuePointChild->parse();
70 switch(cuePointChild->id()) {
75 cuePointChild->makeBuffer();
76 cuePointElementSize += cuePointChild->totalSize();
79 cueTrackPositionsElementSize = 0;
80 cueRelativePositionElement = cueClusterPositionElement =
nullptr;
81 for(
EbmlElement *cueTrackPositionsChild = cuePointChild->
firstChild(); cueTrackPositionsChild; cueTrackPositionsChild = cueTrackPositionsChild->nextSibling()) {
83 cueTrackPositionsChild->
parse();
84 switch(cueTrackPositionsChild->id()) {
88 cueTrackPositionsChild->makeBuffer();
89 cueTrackPositionsElementSize += cueTrackPositionsChild->totalSize();
92 relPos = (cueRelativePositionElement = cueTrackPositionsChild)->readUInteger();
95 pos = (cueClusterPositionElement = cueTrackPositionsChild)->readUInteger();
96 cueTrackPositionsElementSize += 2 + EbmlElement::calculateUIntegerLength(pos);
97 m_offsets.emplace(cueTrackPositionsChild, pos);
100 statePos = cueTrackPositionsChild->readUInteger();
101 cueTrackPositionsElementSize += 2 + EbmlElement::calculateUIntegerLength(statePos);
102 m_offsets.emplace(cueTrackPositionsChild, statePos);
105 cueReferenceElementSize = 0;
106 for(
EbmlElement *cueReferenceChild = cueTrackPositionsChild->
firstChild(); cueReferenceChild; cueReferenceChild = cueReferenceChild->nextSibling()) {
108 cueReferenceChild->parse();
109 switch(cueReferenceChild->id()) {
115 cueReferenceChild->makeBuffer();
116 cueReferenceElementSize += cueReferenceChild->totalSize();
120 statePos = cueReferenceChild->readUInteger();
121 cueReferenceElementSize += 2 + EbmlElement::calculateUIntegerLength(statePos);
122 m_offsets.emplace(cueReferenceChild, statePos);
125 addNotification(NotificationType::Warning,
"\"CueReference\"-element contains a element which is not known to the parser. It will be ignored.", context);
128 cueTrackPositionsElementSize += 1 + EbmlElement::calculateSizeDenotationLength(cueReferenceElementSize) + cueReferenceElementSize;
129 m_sizes.emplace(cueTrackPositionsChild, cueReferenceElementSize);
132 addNotification(NotificationType::Warning,
"\"CueTrackPositions\"-element contains a element which is not known to the parser. It will be ignored.", context);
135 if(!cueClusterPositionElement) {
136 addNotification(NotificationType::Critical,
"\"CueTrackPositions\"-element does not contain mandatory \"CueClusterPosition\"-element.", context);
137 }
else if(cueRelativePositionElement) {
138 cueTrackPositionsElementSize += 2 + EbmlElement::calculateUIntegerLength(relPos);
139 m_relativeOffsets.emplace(piecewise_construct, forward_as_tuple(cueRelativePositionElement), forward_as_tuple(pos, relPos));
141 cuePointElementSize += 1 + EbmlElement::calculateSizeDenotationLength(cueTrackPositionsElementSize) + cueTrackPositionsElementSize;
142 m_sizes.emplace(cuePointChild, cueTrackPositionsElementSize);
145 addNotification(NotificationType::Warning,
"\"CuePoint\"-element contains a element which is not a \"CueTime\"- or a \"CueTrackPositions\"-element. It will be ignored.", context);
148 cuesElementSize += 1 + EbmlElement::calculateSizeDenotationLength(cuePointElementSize) + cuePointElementSize;
149 m_sizes.emplace(cuePointElement, cuePointElementSize);
152 addNotification(NotificationType::Warning,
"\"Cues\"-element contains a element which is not a \"CuePoint\"-element. It will be ignored.", context);
155 m_sizes.emplace(m_cuesElement = cuesElement, cuesElementSize);
162 bool MatroskaCuePositionUpdater::updateOffsets(uint64 originalOffset, uint64 newOffset)
164 bool updated =
false;
165 for(
auto &offset : m_offsets) {
166 if(offset.second.initialValue() == originalOffset && offset.second.currentValue() != newOffset) {
167 updated = updateSize(offset.first->parent(),
static_cast<int>(EbmlElement::calculateUIntegerLength(newOffset)) - static_cast<int>(EbmlElement::calculateUIntegerLength(offset.second.currentValue()))) || updated;
168 offset.second.update(newOffset);
178 bool MatroskaCuePositionUpdater::updateRelativeOffsets(uint64 referenceOffset, uint64 originalRelativeOffset, uint64 newRelativeOffset)
180 bool updated =
false;
181 for(
auto &offset : m_relativeOffsets) {
182 if(offset.second.referenceOffset() == referenceOffset && offset.second.initialValue() == originalRelativeOffset && offset.second.currentValue() != newRelativeOffset) {
183 updated = updateSize(offset.first->parent(),
static_cast<int>(EbmlElement::calculateUIntegerLength(newRelativeOffset)) - static_cast<int>(EbmlElement::calculateUIntegerLength(offset.second.currentValue()))) || updated;
184 offset.second.update(newRelativeOffset);
194 bool MatroskaCuePositionUpdater::updateSize(
EbmlElement *element,
int shift)
207 uint64 &size = m_sizes.at(element);
209 uint64 newSize = shift > 0 ? size +
static_cast<uint64
>(shift) : size - static_cast<uint64>(-shift);
211 bool updated = updateSize(element->
parent(), shift +
static_cast<int>(EbmlElement::calculateSizeDenotationLength(newSize)) - static_cast<int>(EbmlElement::calculateSizeDenotationLength(size)));
215 }
catch(
const out_of_range &) {
224 void MatroskaCuePositionUpdater::make(ostream &stream)
226 static const string context(
"making \"Cues\"-element");
228 addNotification(NotificationType::Warning,
"No cues written; the cues of the source file could not be parsed correctly.", context);
237 stream.write(buff, 4);
238 len = EbmlElement::makeSizeDenotation(m_sizes[m_cuesElement], buff);
239 stream.write(buff, len);
241 for(
EbmlElement *cuePointElement = m_cuesElement->
firstChild(); cuePointElement; cuePointElement = cuePointElement->nextSibling()) {
242 cuePointElement->parse();
243 switch(cuePointElement->id()) {
250 len = EbmlElement::makeSizeDenotation(m_sizes[cuePointElement], buff);
251 stream.write(buff, len);
252 for(
EbmlElement *cuePointChild = cuePointElement->
firstChild(); cuePointChild; cuePointChild = cuePointChild->nextSibling()) {
253 cuePointChild->parse();
254 switch(cuePointChild->id()) {
260 cuePointChild->copyBuffer(stream);
261 cuePointChild->discardBuffer();
267 len = EbmlElement::makeSizeDenotation(m_sizes[cuePointChild], buff);
268 stream.write(buff, len);
269 for(
EbmlElement *cueTrackPositionsChild = cuePointChild->
firstChild(); cueTrackPositionsChild; cueTrackPositionsChild = cueTrackPositionsChild->nextSibling()) {
270 cueTrackPositionsChild->parse();
271 switch(cueTrackPositionsChild->id()) {
276 cueTrackPositionsChild->copyBuffer(stream);
277 cueTrackPositionsChild->discardBuffer();
282 EbmlElement::makeSimpleElement(stream, cueTrackPositionsChild->id(), m_relativeOffsets.at(cueTrackPositionsChild).currentValue());
283 }
catch(
const out_of_range &) {
291 EbmlElement::makeSimpleElement(stream, cueTrackPositionsChild->id(), m_offsets.at(cueTrackPositionsChild).currentValue());
296 len = EbmlElement::makeSizeDenotation(m_sizes[cueTrackPositionsChild], buff);
297 stream.write(buff, len);
298 for(
EbmlElement *cueReferenceChild = cueTrackPositionsChild->
firstChild(); cueReferenceChild; cueReferenceChild = cueReferenceChild->nextSibling()) {
299 cueReferenceChild->parse();
300 switch(cueReferenceChild->id()) {
307 cueReferenceChild->copyBuffer(stream);
308 cueReferenceChild->discardBuffer();
309 cueReferenceChild->copyEntirely(stream);
314 EbmlElement::makeSimpleElement(stream, cueReferenceChild->id(), m_offsets.at(cueReferenceChild).currentValue());
317 addNotification(NotificationType::Warning,
"\"CueReference\"-element contains a element which is not known to the parser. It will be ignored.", context);
322 addNotification(NotificationType::Warning,
"\"CueTrackPositions\"-element contains a element which is not known to the parser. It will be ignored.", context);
327 addNotification(NotificationType::Warning,
"\"CuePoint\"-element contains a element which is not a \"CueTime\"- or a \"CueTrackPositions\"-element. It will be ignored.", context);
332 addNotification(NotificationType::Warning,
"\"Cues\"-element contains a element which is not a \"CuePoint\"-element. It will be ignored.", context);
335 }
catch(
const out_of_range &) {
336 addNotification(NotificationType::Critical,
"Unable to write the file index because the index of the original file could not be parsed correctly.", context);