4#include <c++utilities/conversion/binaryconversion.h>
41 std::uint64_t size = m_sizes.at(m_cuesElement);
54 static const string context(
"parsing \"Cues\"-element");
56 std::uint64_t cuesElementSize = 0, cuePointElementSize, cueTrackPositionsElementSize, cueReferenceElementSize, pos, relPos, statePos;
57 EbmlElement *cueRelativePositionElement, *cueClusterPositionElement;
60 cuePointElement->
parse(diag);
61 switch (cuePointElement->id()) {
66 cuePointElementSize = 0;
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();
98 m_offsets.emplace(cueTrackPositionsChild, pos);
99 m_cueElementByOriginalOffset.emplace(pos, cueTrackPositionsChild);
102 statePos = cueTrackPositionsChild->readUInteger();
104 m_offsets.emplace(cueTrackPositionsChild, statePos);
105 m_cueElementByOriginalOffset.emplace(statePos, cueTrackPositionsChild);
108 cueReferenceElementSize = 0;
110 cueReferenceChild = cueReferenceChild->
nextSibling()) {
112 cueReferenceChild->parse(diag);
113 switch (cueReferenceChild->id()) {
119 cueReferenceChild->makeBuffer();
120 cueReferenceElementSize += cueReferenceChild->totalSize();
124 statePos = cueReferenceChild->readUInteger();
126 m_offsets.emplace(cueReferenceChild, statePos);
127 m_cueElementByOriginalOffset.emplace(statePos, cueReferenceChild);
131 "\"CueReference\"-element contains a element which is not known to the parser. It will be ignored.", context);
134 cueTrackPositionsElementSize
136 m_sizes.emplace(cueTrackPositionsChild, cueReferenceElementSize);
140 "\"CueTrackPositions\"-element contains a element which is not known to the parser. It will be ignored.", context);
143 if (!cueClusterPositionElement) {
145 DiagLevel::Critical,
"\"CueTrackPositions\"-element does not contain mandatory \"CueClusterPosition\"-element.", context);
146 }
else if (cueRelativePositionElement) {
148 m_relativeOffsets.emplace(piecewise_construct, forward_as_tuple(cueRelativePositionElement), forward_as_tuple(pos, relPos));
149 m_cueRelativePositionElementByOriginalOffsets.emplace(
150 piecewise_construct, forward_as_tuple(pos, relPos), forward_as_tuple(cueRelativePositionElement));
154 m_sizes.emplace(cuePointChild, cueTrackPositionsElementSize);
158 "\"CuePoint\"-element contains a element which is not a \"CueTime\"- or a \"CueTrackPositions\"-element. It will be ignored.",
163 m_sizes.emplace(cuePointElement, cuePointElementSize);
167 DiagLevel::Warning,
"\"Cues\"-element contains a element which is not a \"CuePoint\"-element. It will be ignored.", context);
170 m_sizes.emplace(m_cuesElement =
cuesElement, cuesElementSize);
179 auto updated =
false;
181 for (
auto cueElementRange = m_cueElementByOriginalOffset.equal_range(originalOffset); cueElementRange.first != cueElementRange.second;
182 ++cueElementRange.first) {
183 auto *
const cueElement = cueElementRange.first->second;
184 const auto offsetIterator = m_offsets.find(cueElement);
185 if (offsetIterator == m_offsets.end()) {
188 auto &offset = offsetIterator->second;
189 if (offset.currentValue() != newOffset) {
193 offset.update(newOffset);
204 std::uint64_t referenceOffset, std::uint64_t originalRelativeOffset, std::uint64_t newRelativeOffset)
206 auto updated =
false;
208 for (
auto cueElementRange = m_cueRelativePositionElementByOriginalOffsets.equal_range(std::make_pair(referenceOffset, originalRelativeOffset));
209 cueElementRange.first != cueElementRange.second; ++cueElementRange.first) {
210 auto *
const cueRelativePositionElement = cueElementRange.first->second;
211 const auto offsetIterator = m_relativeOffsets.find(cueRelativePositionElement);
212 if (offsetIterator == m_relativeOffsets.end()) {
215 auto &offset = offsetIterator->second;
216 if (offset.currentValue() != newRelativeOffset) {
217 updated = updateSize(cueRelativePositionElement->parent(),
220 offset.update(newRelativeOffset);
230bool MatroskaCuePositionUpdater::updateSize(
EbmlElement *element,
int shift)
241 const auto sizeIterator = m_sizes.find(element);
242 if (sizeIterator == m_sizes.end()) {
245 std::uint64_t &size = sizeIterator->second;
247 const std::uint64_t newSize = shift > 0 ? size +
static_cast<std::uint64_t
>(shift) : size -
static_cast<std::uint64_t
>(-shift);
249 const bool updated = updateSize(element->
parent(),
262 static const string context(
"making \"Cues\"-element");
263 if (!m_cuesElement) {
264 diag.emplace_back(
DiagLevel::Warning,
"No cues written; the cues of the source file could not be parsed correctly.", context);
273 stream.write(buff, 4);
275 stream.write(buff, len);
278 cuePointElement->parse(diag);
279 switch (cuePointElement->id()) {
287 stream.write(buff, len);
289 cuePointChild->parse(diag);
290 switch (cuePointChild->id()) {
296 cuePointChild->copyBuffer(stream);
297 cuePointChild->discardBuffer();
303 stream.write(buff, len);
305 cueTrackPositionsChild = cueTrackPositionsChild->
nextSibling()) {
306 cueTrackPositionsChild->parse(diag);
307 switch (cueTrackPositionsChild->id()) {
312 cueTrackPositionsChild->copyBuffer(stream);
313 cueTrackPositionsChild->discardBuffer();
316 if (
const auto relativeOffset = m_relativeOffsets.find(cueTrackPositionsChild);
317 relativeOffset != m_relativeOffsets.end()) {
327 stream, cueTrackPositionsChild->id(), m_offsets.at(cueTrackPositionsChild).currentValue());
333 stream.write(buff, len);
335 cueReferenceChild = cueReferenceChild->
nextSibling()) {
336 cueReferenceChild->parse(diag);
337 switch (cueReferenceChild->id()) {
344 cueReferenceChild->copyBuffer(stream);
345 cueReferenceChild->discardBuffer();
346 cueReferenceChild->copyEntirely(stream, diag,
nullptr);
352 stream, cueReferenceChild->id(), m_offsets.at(cueReferenceChild).currentValue());
356 "\"CueReference\"-element contains a element which is not known to the parser. It will be ignored.",
363 "\"CueTrackPositions\"-element contains a element which is not known to the parser. It will be ignored.",
370 "\"CuePoint\"-element contains a element which is not a \"CueTime\"- or a \"CueTrackPositions\"-element. It will be "
378 DiagLevel::Warning,
"\"Cues\"-element contains a element which is not a \"CuePoint\"-element. It will be ignored.", context);
381 }
catch (
const out_of_range &) {
383 DiagLevel::Critical,
"Unable to write the file index because the index of the original file could not be parsed correctly.", context);
The Diagnostics class is a container for DiagMessage.
The EbmlElement class helps to parse EBML files such as Matroska files.
static void makeSimpleElement(std::ostream &stream, IdentifierType id, std::uint64_t content)
Makes a simple EBML element.
static std::uint8_t calculateSizeDenotationLength(std::uint64_t size)
Returns the length of the size denotation for the specified size in byte.
static std::uint8_t makeSizeDenotation(std::uint64_t size, char *buff)
Makes the size denotation for the specified size and stores it to buff.
static std::uint8_t calculateUIntegerLength(std::uint64_t integer)
Returns the length of the specified unsigned integer in byte.
ImplementationType * nextSibling()
Returns the next sibling of the element.
ImplementationType * parent()
Returns the parent of the element.
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...
The exception that is thrown when the data to be parsed or to be made seems invalid and therefore can...
std::uint64_t totalSize() const
Returns how many bytes will be written when calling the make() method.
bool updateOffsets(std::uint64_t originalOffset, std::uint64_t newOffset)
Sets the offset of the entries with the specified originalOffset to newOffset.
bool updateRelativeOffsets(std::uint64_t referenceOffset, std::uint64_t originalRelativeOffset, std::uint64_t newRelativeOffset)
Sets the relative offset of the entries with the specified originalRelativeOffset and the specified r...
void clear()
Resets the object to its initial state.
void make(std::ostream &stream, Diagnostics &diag)
Writes the previously parsed "Cues"-element with updated positions to the specified stream.
void parse(EbmlElement *cuesElement, Diagnostics &diag)
Parses the specified cuesElement.
EbmlElement * cuesElement() const
Returns the "Cues"-element specified when calling the parse() method.
Contains all classes and functions of the TagInfo library.