From 8511827fa13842befb114bbf4b66fd9acce9d94e Mon Sep 17 00:00:00 2001 From: HomerJau Date: Sat, 9 May 2026 09:15:02 +0200 Subject: [PATCH] Skip Matroska Cues with AudioProperties::Fast and read-only mode When the file is opened in read-only mode, it will not be written and the Cues do not have to be updated. Skipping the Cues will make the reading of large Matroska files over network filesystems (SMB/NFS) faster. --- taglib/matroska/ebml/ebmlmksegment.cpp | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/taglib/matroska/ebml/ebmlmksegment.cpp b/taglib/matroska/ebml/ebmlmksegment.cpp index 1e509e7d..f570315c 100644 --- a/taglib/matroska/ebml/ebmlmksegment.cpp +++ b/taglib/matroska/ebml/ebmlmksegment.cpp @@ -83,6 +83,12 @@ bool EBML::MkSegment::readLimited(File &file, offset_t scanLimit) const offset_t filePos = file.tell(); const offset_t maxOffset = filePos + dataSize; const offset_t maxScanOffset = filePos + std::min(scanLimit, dataSize); + // When scanLimit is less than dataSize, the caller has requested a + // fast/limited scan (e.g. AudioProperties::Fast). In that case and if the + // file has been opened in read-only mode, we skip parsing the Cues element, + // which can be tens of MB on large files, causing severe slowdowns over + // network filesystems, and do not have to be updated in read-only mode. + const bool skipCues = file.readOnly() && scanLimit < dataSize; MasterElement *pendingPaddingTarget = nullptr; offset_t accumulatedPadding = 0; std::unique_ptr element; @@ -139,9 +145,11 @@ bool EBML::MkSegment::readLimited(File &file, offset_t scanLimit) break; } case Id::MkCues: - if(!((cues = readElementAt( - file, absoluteOffset, maxOffset)))) - return false; + if(!skipCues) { + if(!((cues = readElementAt( + file, absoluteOffset, maxOffset)))) + return false; + } break; case Id::MkInfo: if(!((info = readElementAt( @@ -187,9 +195,14 @@ bool EBML::MkSegment::readLimited(File &file, offset_t scanLimit) else if(id == Id::MkCues) { pendingPaddingTarget = nullptr; accumulatedPadding = 0; - cues = element_cast(std::move(element)); - if(!cues->read(file)) - return false; + if(!skipCues) { + cues = element_cast(std::move(element)); + if(!cues->read(file)) + return false; + } + else { + element->skipData(file); + } } else if(id == Id::MkInfo) { pendingPaddingTarget = nullptr;