Improve progress updates when making Mkv file

This commit is contained in:
Martchus 2017-09-21 23:30:01 +02:00
parent dc32ca77fb
commit d717913e99
1 changed files with 28 additions and 8 deletions

View File

@ -892,7 +892,7 @@ void MatroskaContainer::internalMakeFile()
// -> content and size denotation length of string sub elements // -> content and size denotation length of string sub elements
ebmlHeaderDataSize += m_doctype.size(); ebmlHeaderDataSize += m_doctype.size();
ebmlHeaderDataSize += EbmlElement::calculateSizeDenotationLength(m_doctype.size()); ebmlHeaderDataSize += EbmlElement::calculateSizeDenotationLength(m_doctype.size());
uint64 ebmlHeaderSize = 4 + EbmlElement::calculateSizeDenotationLength(ebmlHeaderDataSize) + ebmlHeaderDataSize; const uint64 ebmlHeaderSize = 4 + EbmlElement::calculateSizeDenotationLength(ebmlHeaderDataSize) + ebmlHeaderDataSize;
try { try {
// calculate size of "Tags"-element // calculate size of "Tags"-element
@ -989,7 +989,7 @@ void MatroskaContainer::internalMakeFile()
throw; throw;
} }
updateStatus("Calculating segment data ...", 0.0); updateStatus("Calculating offsets of elements before cluster ...", 0.0);
calculateSegmentData: calculateSegmentData:
// define variables to store sizes, offsets and other information required to make a header and "Segment"-elements // define variables to store sizes, offsets and other information required to make a header and "Segment"-elements
// -> current "pretent" write offset // -> current "pretent" write offset
@ -1163,9 +1163,12 @@ calculateSegmentSize:
goto calculateSegmentSize; goto calculateSegmentSize;
} else { } else {
// add size of "Cues"-element // add size of "Cues"-element
updateStatus("Calculating cluster offsets and index size ...", 0.0);
addCuesElementSize: addCuesElementSize:
segment.totalDataSize += segment.cuesUpdater.totalSize(); segment.totalDataSize += segment.cuesUpdater.totalSize();
} }
} else {
updateStatus("Calculating cluster offsets ...", 0.0);
} }
// decided whether it is necessary to rewrite the entire file (if not already rewriting) // decided whether it is necessary to rewrite the entire file (if not already rewriting)
@ -1200,12 +1203,16 @@ nonRewriteCalculations:
} }
// -> update offset of "Cluster"-element in "Cues"-element and get end offset of last "Cluster"-element // -> update offset of "Cluster"-element in "Cues"-element and get end offset of last "Cluster"-element
bool cuesInvalidated = false; bool cuesInvalidated = false;
for(; level1Element; level1Element = level1Element->siblingById(MatroskaIds::Cluster)) { for(index = 0; level1Element; level1Element = level1Element->siblingById(MatroskaIds::Cluster), ++index) {
clusterReadOffset = level1Element->startOffset() - level0Element->dataOffset() + readOffset; clusterReadOffset = level1Element->startOffset() - level0Element->dataOffset() + readOffset;
segment.clusterEndOffset = level1Element->endOffset(); segment.clusterEndOffset = level1Element->endOffset();
if(segment.cuesElement && segment.cuesUpdater.updateOffsets(clusterReadOffset, level1Element->startOffset() - 4 - segment.sizeDenotationLength - ebmlHeaderSize) && newCuesPos == ElementPosition::BeforeData) { if(segment.cuesElement && segment.cuesUpdater.updateOffsets(clusterReadOffset, level1Element->startOffset() - 4 - segment.sizeDenotationLength - ebmlHeaderSize) && newCuesPos == ElementPosition::BeforeData) {
cuesInvalidated = true; cuesInvalidated = true;
} }
// update the progress percentage (using offset / file size should be accurate enough)
if((index % 50 == 0) && fileInfo().size()) {
updatePercentage(static_cast<double>(level1Element->dataOffset()) / fileInfo().size());
}
} }
if(cuesInvalidated) { if(cuesInvalidated) {
segment.totalDataSize = offset; segment.totalDataSize = offset;
@ -1213,6 +1220,8 @@ nonRewriteCalculations:
} }
segment.totalDataSize = segment.clusterEndOffset - currentOffset - 4 - segment.sizeDenotationLength; segment.totalDataSize = segment.clusterEndOffset - currentOffset - 4 - segment.sizeDenotationLength;
updateStatus("Calculating offsets of elements after cluster ...", 0.0);
// pretend writing "Cues"-element // pretend writing "Cues"-element
if(newCuesPos == ElementPosition::AfterData && segment.cuesElement) { if(newCuesPos == ElementPosition::AfterData && segment.cuesElement) {
// update offset of "Cues"-element in "SeekHead"-element // update offset of "Cues"-element in "SeekHead"-element
@ -1299,7 +1308,7 @@ nonRewriteCalculations:
goto calculateSegmentData; goto calculateSegmentData;
} }
} else { } else {
// if rewrite is required pretend writing the remaining elements to compute total segment size // if rewrite is required, pretend writing the remaining elements to compute total segment size
// pretend writing "Void"-element (only if there is at least one "Cluster"-element in the segment) // pretend writing "Void"-element (only if there is at least one "Cluster"-element in the segment)
if(!segmentIndex && rewriteRequired && (level1Element = level0Element->childById(MatroskaIds::Cluster))) { if(!segmentIndex && rewriteRequired && (level1Element = level0Element->childById(MatroskaIds::Cluster))) {
@ -1340,8 +1349,13 @@ nonRewriteCalculations:
} }
segment.clusterSizes.push_back(clusterSize); segment.clusterSizes.push_back(clusterSize);
segment.totalDataSize += 4 + EbmlElement::calculateSizeDenotationLength(clusterSize) + clusterSize; segment.totalDataSize += 4 + EbmlElement::calculateSizeDenotationLength(clusterSize) + clusterSize;
} }
} }
// update the progress percentage (using offset / file size should be accurate enough)
if((index % 50 == 0) && fileInfo().size()) {
updatePercentage(static_cast<double>(level1Element->dataOffset()) / fileInfo().size());
}
} }
// check whether the total size of the "Cues"-element has been invalidated and recompute cluster if required // check whether the total size of the "Cues"-element has been invalidated and recompute cluster if required
if(cuesInvalidated) { if(cuesInvalidated) {
@ -1350,6 +1364,8 @@ nonRewriteCalculations:
goto addCuesElementSize; goto addCuesElementSize;
} }
updateStatus("Calculating offsets of elements after cluster ...", 0.0);
// pretend writing "Cues"-element // pretend writing "Cues"-element
if(newCuesPos == ElementPosition::AfterData && segment.cuesElement) { if(newCuesPos == ElementPosition::AfterData && segment.cuesElement) {
// update offset of "Cues"-element in "SeekHead"-element // update offset of "Cues"-element in "SeekHead"-element
@ -1654,10 +1670,11 @@ nonRewriteCalculations:
if(isAborted()) { if(isAborted()) {
throw OperationAbortedException(); throw OperationAbortedException();
} }
updateStatus("Writing clusters ...", static_cast<double>(static_cast<uint64>(outputStream.tellp()) - offset) / segment.totalDataSize); updateStatus("Writing cluster ...", static_cast<double>(static_cast<uint64>(outputStream.tellp()) - offset) / segment.totalDataSize);
// write "Cluster"-element // write "Cluster"-element
for(auto clusterSizesIterator = segment.clusterSizes.cbegin(); auto clusterSizesIterator = segment.clusterSizes.cbegin();
level1Element; level1Element = level1Element->siblingById(MatroskaIds::Cluster), ++clusterSizesIterator) { unsigned int index = 0;
for(;level1Element; level1Element = level1Element->siblingById(MatroskaIds::Cluster), ++clusterSizesIterator, ++index) {
// calculate position of cluster in segment // calculate position of cluster in segment
clusterSize = currentPosition + (static_cast<uint64>(outputStream.tellp()) - offset); clusterSize = currentPosition + (static_cast<uint64>(outputStream.tellp()) - offset);
// write header; checking whether clusterSizesIterator is valid shouldn't be necessary // write header; checking whether clusterSizesIterator is valid shouldn't be necessary
@ -1680,12 +1697,13 @@ nonRewriteCalculations:
// update percentage, check whether the operation has been aborted // update percentage, check whether the operation has been aborted
if(isAborted()) { if(isAborted()) {
throw OperationAbortedException(); throw OperationAbortedException();
} else { } else if(index % 50 == 0) {
updatePercentage(static_cast<double>(static_cast<uint64>(outputStream.tellp()) - offset) / segment.totalDataSize); updatePercentage(static_cast<double>(static_cast<uint64>(outputStream.tellp()) - offset) / segment.totalDataSize);
} }
} }
} else { } else {
// can't just skip existing "Cluster"-elements: "Position"-elements must be updated // can't just skip existing "Cluster"-elements: "Position"-elements must be updated
updateStatus("Updateing cluster ...", static_cast<double>(static_cast<uint64>(outputStream.tellp()) - offset) / segment.totalDataSize);
for(; level1Element; level1Element = level1Element->nextSibling()) { for(; level1Element; level1Element = level1Element->nextSibling()) {
for(level2Element = level1Element->firstChild(); level2Element; level2Element = level2Element->nextSibling()) { for(level2Element = level1Element->firstChild(); level2Element; level2Element = level2Element->nextSibling()) {
switch(level2Element->id()) { switch(level2Element->id()) {
@ -1712,6 +1730,8 @@ nonRewriteCalculations:
outputStream.seekp(segment.clusterEndOffset); outputStream.seekp(segment.clusterEndOffset);
} }
updateStatus("Writing segment tail ...");
// write "Cues"-element // write "Cues"-element
if(newCuesPos == ElementPosition::AfterData && segment.cuesElement) { if(newCuesPos == ElementPosition::AfterData && segment.cuesElement) {
try { try {