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;
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(diag);
61 switch (cuePointElement->id()) {
66 cuePointElementSize = 0;
67 for (
EbmlElement *cuePointChild = cuePointElement->
firstChild(); cuePointChild; cuePointChild = cuePointChild->nextSibling()) {
69 cuePointChild->parse(diag);
70 switch (cuePointChild->id()) {
75 cuePointChild->makeBuffer();
76 cuePointElementSize += cuePointChild->totalSize();
79 cueTrackPositionsElementSize = 0;
80 cueRelativePositionElement = cueClusterPositionElement =
nullptr;
82 cueTrackPositionsChild = cueTrackPositionsChild->nextSibling()) {
84 cueTrackPositionsChild->
parse(diag);
85 switch (cueTrackPositionsChild->id()) {
89 cueTrackPositionsChild->makeBuffer();
90 cueTrackPositionsElementSize += cueTrackPositionsChild->totalSize();
93 relPos = (cueRelativePositionElement = cueTrackPositionsChild)->readUInteger();
96 pos = (cueClusterPositionElement = cueTrackPositionsChild)->readUInteger();
97 cueTrackPositionsElementSize += 2 + EbmlElement::calculateUIntegerLength(pos);
98 m_offsets.emplace(cueTrackPositionsChild, pos);
101 statePos = cueTrackPositionsChild->readUInteger();
102 cueTrackPositionsElementSize += 2 + EbmlElement::calculateUIntegerLength(statePos);
103 m_offsets.emplace(cueTrackPositionsChild, statePos);
106 cueReferenceElementSize = 0;
108 cueReferenceChild = cueReferenceChild->nextSibling()) {
110 cueReferenceChild->parse(diag);
111 switch (cueReferenceChild->id()) {
117 cueReferenceChild->makeBuffer();
118 cueReferenceElementSize += cueReferenceChild->totalSize();
122 statePos = cueReferenceChild->readUInteger();
123 cueReferenceElementSize += 2 + EbmlElement::calculateUIntegerLength(statePos);
124 m_offsets.emplace(cueReferenceChild, statePos);
127 diag.emplace_back(DiagLevel::Warning,
128 "\"CueReference\"-element contains a element which is not known to the parser. It will be ignored.", context);
131 cueTrackPositionsElementSize
132 += 1 + EbmlElement::calculateSizeDenotationLength(cueReferenceElementSize) + cueReferenceElementSize;
133 m_sizes.emplace(cueTrackPositionsChild, cueReferenceElementSize);
136 diag.emplace_back(DiagLevel::Warning,
137 "\"CueTrackPositions\"-element contains a element which is not known to the parser. It will be ignored.", context);
140 if (!cueClusterPositionElement) {
142 DiagLevel::Critical,
"\"CueTrackPositions\"-element does not contain mandatory \"CueClusterPosition\"-element.", context);
143 }
else if (cueRelativePositionElement) {
144 cueTrackPositionsElementSize += 2 + EbmlElement::calculateUIntegerLength(relPos);
145 m_relativeOffsets.emplace(piecewise_construct, forward_as_tuple(cueRelativePositionElement), forward_as_tuple(pos, relPos));
148 += 1 + EbmlElement::calculateSizeDenotationLength(cueTrackPositionsElementSize) + cueTrackPositionsElementSize;
149 m_sizes.emplace(cuePointChild, cueTrackPositionsElementSize);
152 diag.emplace_back(DiagLevel::Warning,
153 "\"CuePoint\"-element contains a element which is not a \"CueTime\"- or a \"CueTrackPositions\"-element. It will be ignored.",
157 cuesElementSize += 1 + EbmlElement::calculateSizeDenotationLength(cuePointElementSize) + cuePointElementSize;
158 m_sizes.emplace(cuePointElement, cuePointElementSize);
162 DiagLevel::Warning,
"\"Cues\"-element contains a element which is not a \"CuePoint\"-element. It will be ignored.", context);
165 m_sizes.emplace(m_cuesElement = cuesElement, cuesElementSize);
172 bool MatroskaCuePositionUpdater::updateOffsets(uint64 originalOffset, uint64 newOffset)
174 bool updated =
false;
175 for (
auto &offset : m_offsets) {
176 if (offset.second.initialValue() == originalOffset && offset.second.currentValue() != newOffset) {
177 updated = updateSize(offset.first->parent(),
178 static_cast<int>(EbmlElement::calculateUIntegerLength(newOffset))
179 - static_cast<int>(EbmlElement::calculateUIntegerLength(offset.second.currentValue())))
181 offset.second.update(newOffset);
191 bool MatroskaCuePositionUpdater::updateRelativeOffsets(uint64 referenceOffset, uint64 originalRelativeOffset, uint64 newRelativeOffset)
193 bool updated =
false;
194 for (
auto &offset : m_relativeOffsets) {
195 if (offset.second.referenceOffset() == referenceOffset && offset.second.initialValue() == originalRelativeOffset
196 && offset.second.currentValue() != newRelativeOffset) {
197 updated = updateSize(offset.first->parent(),
198 static_cast<int>(EbmlElement::calculateUIntegerLength(newRelativeOffset))
199 - static_cast<int>(EbmlElement::calculateUIntegerLength(offset.second.currentValue())))
201 offset.second.update(newRelativeOffset);
211 bool MatroskaCuePositionUpdater::updateSize(
EbmlElement *element,
int shift)
224 uint64 &size = m_sizes.at(element);
226 const uint64 newSize = shift > 0 ? size +
static_cast<uint64
>(shift) : size - static_cast<uint64>(-shift);
228 const bool updated = updateSize(element->
parent(),
229 shift +
static_cast<int>(EbmlElement::calculateSizeDenotationLength(newSize))
230 - static_cast<int>(EbmlElement::calculateSizeDenotationLength(size)));
234 }
catch (
const out_of_range &) {
243 void MatroskaCuePositionUpdater::make(ostream &stream,
Diagnostics &diag)
245 static const string context(
"making \"Cues\"-element");
246 if (!m_cuesElement) {
247 diag.emplace_back(DiagLevel::Warning,
"No cues written; the cues of the source file could not be parsed correctly.", context);
256 stream.write(buff, 4);
257 len = EbmlElement::makeSizeDenotation(m_sizes[m_cuesElement], buff);
258 stream.write(buff, len);
260 for (
EbmlElement *cuePointElement = m_cuesElement->
firstChild(); cuePointElement; cuePointElement = cuePointElement->nextSibling()) {
261 cuePointElement->parse(diag);
262 switch (cuePointElement->id()) {
269 len = EbmlElement::makeSizeDenotation(m_sizes[cuePointElement], buff);
270 stream.write(buff, len);
271 for (
EbmlElement *cuePointChild = cuePointElement->
firstChild(); cuePointChild; cuePointChild = cuePointChild->nextSibling()) {
272 cuePointChild->parse(diag);
273 switch (cuePointChild->id()) {
279 cuePointChild->copyBuffer(stream);
280 cuePointChild->discardBuffer();
286 len = EbmlElement::makeSizeDenotation(m_sizes[cuePointChild], buff);
287 stream.write(buff, len);
289 cueTrackPositionsChild = cueTrackPositionsChild->nextSibling()) {
290 cueTrackPositionsChild->parse(diag);
291 switch (cueTrackPositionsChild->id()) {
296 cueTrackPositionsChild->copyBuffer(stream);
297 cueTrackPositionsChild->discardBuffer();
302 EbmlElement::makeSimpleElement(
303 stream, cueTrackPositionsChild->id(), m_relativeOffsets.at(cueTrackPositionsChild).currentValue());
304 }
catch (
const out_of_range &) {
312 EbmlElement::makeSimpleElement(
313 stream, cueTrackPositionsChild->id(), m_offsets.at(cueTrackPositionsChild).currentValue());
318 len = EbmlElement::makeSizeDenotation(m_sizes[cueTrackPositionsChild], buff);
319 stream.write(buff, len);
321 cueReferenceChild = cueReferenceChild->nextSibling()) {
322 cueReferenceChild->parse(diag);
323 switch (cueReferenceChild->id()) {
330 cueReferenceChild->copyBuffer(stream);
331 cueReferenceChild->discardBuffer();
332 cueReferenceChild->copyEntirely(stream, diag,
nullptr);
337 EbmlElement::makeSimpleElement(
338 stream, cueReferenceChild->id(), m_offsets.at(cueReferenceChild).currentValue());
341 diag.emplace_back(DiagLevel::Warning,
342 "\"CueReference\"-element contains a element which is not known to the parser. It will be ignored.",
348 diag.emplace_back(DiagLevel::Warning,
349 "\"CueTrackPositions\"-element contains a element which is not known to the parser. It will be ignored.",
355 diag.emplace_back(DiagLevel::Warning,
356 "\"CuePoint\"-element contains a element which is not a \"CueTime\"- or a \"CueTrackPositions\"-element. It will be " 364 DiagLevel::Warning,
"\"Cues\"-element contains a element which is not a \"CuePoint\"-element. It will be ignored.", context);
367 }
catch (
const out_of_range &) {
369 DiagLevel::Critical,
"Unable to write the file index because the index of the original file could not be parsed correctly.", context);
ImplementationType * firstChild()
Returns the first child of the element.
void parse(Diagnostics &diag)
Parses the header information of the element which is read from the related stream at the start offse...
ImplementationType * parent()
Returns the parent of the element.