3030
3131using namespace TagLib ;
3232
33+ namespace {
34+
35+ template <EBML::Element::Id Id, typename ElementType>
36+ std::unique_ptr<ElementType> readElementAt (File &file,
37+ offset_t offset,
38+ offset_t maxOffset)
39+ {
40+ if (offset < 0 || offset >= maxOffset) {
41+ return nullptr ;
42+ }
43+
44+ file.seek (offset);
45+ auto element = EBML::Element::factory (file);
46+ if (!element || element->getId () != Id) {
47+ return nullptr ;
48+ }
49+
50+ auto typed = EBML::element_cast<Id>(std::move (element));
51+ if (!typed || !typed->read (file)) {
52+ return nullptr ;
53+ }
54+ return typed;
55+ }
56+
57+ } // namespace
58+
3359EBML::MkSegment::MkSegment (int sizeLength, offset_t dataSize, offset_t offset):
3460 MasterElement(Id::MkSegment, sizeLength, dataSize, offset)
3561{
@@ -51,14 +77,55 @@ bool EBML::MkSegment::read(File &file)
5177{
5278 const offset_t maxOffset = file.tell () + dataSize;
5379 std::unique_ptr<Element> element;
54- int i = 0 ;
55- int seekHeadIndex = -1 ;
5680 while ((element = findNextElement (file, maxOffset))) {
5781 if (const Id id = element->getId (); id == Id::MkSeekHead) {
58- seekHeadIndex = i;
5982 seekHead = element_cast<Id::MkSeekHead>(std::move (element));
6083 if (!seekHead->read (file))
6184 return false ;
85+ // We have a seek head, let's use it for faster access to the other elements
86+ if (const auto elementAfterSeekHead = findNextElement (file, maxOffset);
87+ elementAfterSeekHead && elementAfterSeekHead->getId () == Id::VoidElement)
88+ seekHead->setPadding (elementAfterSeekHead->getSize ());
89+ const offset_t segDataOffset = segmentDataOffset ();
90+ const auto matroskaSeekHead = parseSeekHead ();
91+ for (const auto &[idValue, relativeOffset] : matroskaSeekHead->entryList ()) {
92+ const offset_t absoluteOffset = segDataOffset + relativeOffset;
93+ switch (static_cast <Id>(idValue)) {
94+ case Id::MkCues:
95+ if (!((cues = readElementAt<Id::MkCues, MkCues>(
96+ file, absoluteOffset, maxOffset))))
97+ return false ;
98+ break ;
99+ case Id::MkInfo:
100+ if (!((info = readElementAt<Id::MkInfo, MkInfo>(
101+ file, absoluteOffset, maxOffset))))
102+ return false ;
103+ break ;
104+ case Id::MkTracks:
105+ if (!((tracks = readElementAt<Id::MkTracks, MkTracks>(
106+ file, absoluteOffset, maxOffset))))
107+ return false ;
108+ break ;
109+ case Id::MkTags:
110+ if (!((tags = readElementAt<Id::MkTags, MkTags>(
111+ file, absoluteOffset, maxOffset))))
112+ return false ;
113+ break ;
114+ case Id::MkAttachments:
115+ if (!((attachments = readElementAt<Id::MkAttachments, MkAttachments>(
116+ file, absoluteOffset, maxOffset))))
117+ return false ;
118+ break ;
119+ case Id::MkChapters:
120+ if (!((chapters = readElementAt<Id::MkChapters, MkChapters>(
121+ file, absoluteOffset, maxOffset))))
122+ return false ;
123+ break ;
124+ default :
125+ break ;
126+ }
127+ }
128+ return true ;
62129 }
63130 else if (id == Id::MkCues) {
64131 cues = element_cast<Id::MkCues>(std::move (element));
@@ -91,14 +158,8 @@ bool EBML::MkSegment::read(File &file)
91158 return false ;
92159 }
93160 else {
94- if (id == Id::VoidElement
95- && seekHead
96- && seekHeadIndex == i - 1 )
97- seekHead->setPadding (element->getSize ());
98-
99161 element->skipData (file);
100162 }
101- i++;
102163 }
103164 return true ;
104165}
0 commit comments