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