1/**********
2This library is free software; you can redistribute it and/or modify it under
3the terms of the GNU Lesser General Public License as published by the
4Free Software Foundation; either version 3 of the License, or (at your
5option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
6
7This library is distributed in the hope that it will be useful, but WITHOUT
8ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
10more details.
11
12You should have received a copy of the GNU Lesser General Public License
13along with this library; if not, write to the Free Software Foundation, Inc.,
1451 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15**********/
16// "liveMedia"
17// Copyright (c) 1996-2020 Live Networks, Inc. All rights reserved.
18// A parser for a Matroska file.
19// C++ header
20
21#ifndef _MATROSKA_FILE_PARSER_HH
22
23#ifndef _STREAM_PARSER_HH
24#include "StreamParser.hh"
25#endif
26#ifndef _MATROSKA_FILE_HH
27#include "MatroskaFile.hh"
28#endif
29#ifndef _EBML_NUMBER_HH
30#include "EBMLNumber.hh"
31#endif
32
33// An enum representing the current state of the parser:
34enum MatroskaParseState {
35 PARSING_START_OF_FILE,
36 LOOKING_FOR_TRACKS,
37 PARSING_TRACK,
38 PARSING_CUES,
39 LOOKING_FOR_CLUSTER,
40 LOOKING_FOR_BLOCK,
41 PARSING_BLOCK,
42 DELIVERING_FRAME_WITHIN_BLOCK,
43 DELIVERING_FRAME_BYTES
44};
45
46class MatroskaFileParser: public StreamParser {
47public:
48 MatroskaFileParser(MatroskaFile& ourFile, FramedSource* inputSource,
49 FramedSource::onCloseFunc* onEndFunc, void* onEndClientData,
50 MatroskaDemux* ourDemux = NULL);
51 virtual ~MatroskaFileParser();
52
53 void seekToTime(double& seekNPT);
54
55 // StreamParser 'client continue' function:
56 static void continueParsing(void* clientData, unsigned char* ptr, unsigned size, struct timeval presentationTime);
57 void continueParsing();
58
59private:
60 // Parsing functions:
61 Boolean parse();
62 // returns True iff we have finished parsing to the end of all 'Track' headers (on initialization)
63
64 Boolean parseStartOfFile();
65 void lookForNextTrack();
66 Boolean parseTrack();
67 Boolean parseCues();
68
69 void lookForNextBlock();
70 void parseBlock();
71 Boolean deliverFrameWithinBlock();
72 void deliverFrameBytes();
73
74 void getCommonFrameBytes(MatroskaTrack* track, u_int8_t* to, unsigned numBytesToGet, unsigned numBytesToSkip);
75
76 Boolean parseEBMLNumber(EBMLNumber& num);
77 Boolean parseEBMLIdAndSize(EBMLId& id, EBMLDataSize& size);
78 Boolean parseEBMLVal_unsigned64(EBMLDataSize& size, u_int64_t& result);
79 Boolean parseEBMLVal_unsigned(EBMLDataSize& size, unsigned& result);
80 Boolean parseEBMLVal_float(EBMLDataSize& size, float& result);
81 Boolean parseEBMLVal_string(EBMLDataSize& size, char*& result);
82 // Note: "result" is dynamically allocated; the caller must delete[] it later
83 Boolean parseEBMLVal_binary(EBMLDataSize& size, u_int8_t*& result);
84 // Note: "result" is dynamically allocated; the caller must delete[] it later
85 void skipHeader(EBMLDataSize const& size);
86 void skipRemainingHeaderBytes(Boolean isContinuation);
87
88 void setParseState();
89
90 void seekToFilePosition(u_int64_t offsetInFile);
91 void seekToEndOfFile();
92 void resetStateAfterSeeking(); // common code, called by both of the above
93
94private: // redefined virtual functions
95 virtual void restoreSavedParserState();
96
97private:
98 // General state for parsing:
99 MatroskaFile& fOurFile;
100 FramedSource* fInputSource;
101 FramedSource::onCloseFunc* fOnEndFunc;
102 void* fOnEndClientData;
103 MatroskaDemux* fOurDemux;
104 MatroskaParseState fCurrentParseState;
105 u_int64_t fCurOffsetInFile, fSavedCurOffsetInFile, fLimitOffsetInFile;
106
107 // For skipping over (possibly large) headers:
108 u_int64_t fNumHeaderBytesToSkip;
109
110 // For parsing 'Seek ID's:
111 EBMLId fLastSeekId;
112
113 // Parameters of the most recently-parsed 'Cluster':
114 unsigned fClusterTimecode;
115
116 // Parameters of the most recently-parsed 'Block':
117 unsigned fBlockSize;
118 unsigned fBlockTrackNumber;
119 short fBlockTimecode;
120 unsigned fNumFramesInBlock;
121 unsigned* fFrameSizesWithinBlock;
122
123 // Parameters of the most recently-parsed frame within a 'Block':
124 double fPresentationTimeOffset;
125 unsigned fNextFrameNumberToDeliver;
126 unsigned fCurOffsetWithinFrame, fSavedCurOffsetWithinFrame; // used if track->haveSubframes()
127
128 // Parameters of the (sub)frame that's currently being delivered:
129 u_int8_t* fCurFrameTo;
130 unsigned fCurFrameNumBytesToGet;
131 unsigned fCurFrameNumBytesToSkip;
132};
133
134#endif
135