4 #include <c++utilities/conversion/binaryconversion.h>
38 std::uint64_t MatroskaCuePositionUpdater::totalSize()
const
41 std::uint64_t size = m_sizes.at(m_cuesElement);
42 return 4 + EbmlElement::calculateSizeDenotationLength(size) + size;
54 static const string context(
"parsing \"Cues\"-element");
56 std::uint64_t 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(std::uint64_t originalOffset, std::uint64_t 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(
192 std::uint64_t referenceOffset, std::uint64_t originalRelativeOffset, std::uint64_t newRelativeOffset)
194 bool updated =
false;
195 for (
auto &offset : m_relativeOffsets) {
196 if (offset.second.referenceOffset() == referenceOffset && offset.second.initialValue() == originalRelativeOffset
197 && offset.second.currentValue() != newRelativeOffset) {
198 updated = updateSize(offset.first->parent(),
199 static_cast<int>(EbmlElement::calculateUIntegerLength(newRelativeOffset))
200 -
static_cast<int>(EbmlElement::calculateUIntegerLength(offset.second.currentValue())))
202 offset.second.update(newRelativeOffset);
212 bool MatroskaCuePositionUpdater::updateSize(
EbmlElement *element,
int shift)
225 std::uint64_t &size = m_sizes.at(element);
227 const std::uint64_t newSize = shift > 0 ? size +
static_cast<std::uint64_t
>(shift) : size -
static_cast<std::uint64_t
>(-shift);
229 const bool updated = updateSize(element->
parent(),
230 shift +
static_cast<int>(EbmlElement::calculateSizeDenotationLength(newSize))
231 -
static_cast<int>(EbmlElement::calculateSizeDenotationLength(size)));
235 }
catch (
const out_of_range &) {
244 void MatroskaCuePositionUpdater::make(ostream &stream,
Diagnostics &diag)
246 static const string context(
"making \"Cues\"-element");
247 if (!m_cuesElement) {
248 diag.emplace_back(DiagLevel::Warning,
"No cues written; the cues of the source file could not be parsed correctly.", context);
257 stream.write(buff, 4);
258 len = EbmlElement::makeSizeDenotation(m_sizes[m_cuesElement], buff);
259 stream.write(buff, len);
261 for (
EbmlElement *cuePointElement = m_cuesElement->
firstChild(); cuePointElement; cuePointElement = cuePointElement->nextSibling()) {
262 cuePointElement->parse(diag);
263 switch (cuePointElement->id()) {
270 len = EbmlElement::makeSizeDenotation(m_sizes[cuePointElement], buff);
271 stream.write(buff, len);
272 for (
EbmlElement *cuePointChild = cuePointElement->
firstChild(); cuePointChild; cuePointChild = cuePointChild->nextSibling()) {
273 cuePointChild->parse(diag);
274 switch (cuePointChild->id()) {
280 cuePointChild->copyBuffer(stream);
281 cuePointChild->discardBuffer();
287 len = EbmlElement::makeSizeDenotation(m_sizes[cuePointChild], buff);
288 stream.write(buff, len);
290 cueTrackPositionsChild = cueTrackPositionsChild->nextSibling()) {
291 cueTrackPositionsChild->parse(diag);
292 switch (cueTrackPositionsChild->id()) {
297 cueTrackPositionsChild->copyBuffer(stream);
298 cueTrackPositionsChild->discardBuffer();
303 EbmlElement::makeSimpleElement(
304 stream, cueTrackPositionsChild->id(), m_relativeOffsets.at(cueTrackPositionsChild).currentValue());
305 }
catch (
const out_of_range &) {
313 EbmlElement::makeSimpleElement(
314 stream, cueTrackPositionsChild->id(), m_offsets.at(cueTrackPositionsChild).currentValue());
319 len = EbmlElement::makeSizeDenotation(m_sizes[cueTrackPositionsChild], buff);
320 stream.write(buff, len);
322 cueReferenceChild = cueReferenceChild->nextSibling()) {
323 cueReferenceChild->parse(diag);
324 switch (cueReferenceChild->id()) {
331 cueReferenceChild->copyBuffer(stream);
332 cueReferenceChild->discardBuffer();
333 cueReferenceChild->copyEntirely(stream, diag,
nullptr);
338 EbmlElement::makeSimpleElement(
339 stream, cueReferenceChild->id(), m_offsets.at(cueReferenceChild).currentValue());
342 diag.emplace_back(DiagLevel::Warning,
343 "\"CueReference\"-element contains a element which is not known to the parser. It will be ignored.",
349 diag.emplace_back(DiagLevel::Warning,
350 "\"CueTrackPositions\"-element contains a element which is not known to the parser. It will be ignored.",
356 diag.emplace_back(DiagLevel::Warning,
357 "\"CuePoint\"-element contains a element which is not a \"CueTime\"- or a \"CueTrackPositions\"-element. It will be "
365 DiagLevel::Warning,
"\"Cues\"-element contains a element which is not a \"CuePoint\"-element. It will be ignored.", context);
368 }
catch (
const out_of_range &) {
370 DiagLevel::Critical,
"Unable to write the file index because the index of the original file could not be parsed correctly.", context);