live
MatroskaFile.hh
Go to the documentation of this file.
1 /**********
2 This library is free software; you can redistribute it and/or modify it under
3 the terms of the GNU Lesser General Public License as published by the
4 Free Software Foundation; either version 3 of the License, or (at your
5 option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
6 
7 This library is distributed in the hope that it will be useful, but WITHOUT
8 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
10 more details.
11 
12 You should have received a copy of the GNU Lesser General Public License
13 along with this library; if not, write to the Free Software Foundation, Inc.,
14 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15 **********/
16 // "liveMedia"
17 // Copyright (c) 1996-2021 Live Networks, Inc. All rights reserved.
18 // A class that encapsulates a Matroska file.
19 // C++ header
20 
21 #ifndef _MATROSKA_FILE_HH
22 #define _MATROSKA_FILE_HH
23 
24 #ifndef _RTP_SINK_HH
25 #include "RTPSink.hh"
26 #endif
27 #ifndef _FILE_SINK_HH
28 #include "FileSink.hh"
29 #endif
30 #ifndef _HASH_TABLE_HH
31 #include "HashTable.hh"
32 #endif
33 
34 class MatroskaTrack; // forward
35 class MatroskaDemux; // forward
36 
37 class MatroskaFile: public Medium {
38 public:
39  typedef void (onCreationFunc)(MatroskaFile* newFile, void* clientData);
40  static void createNew(UsageEnvironment& env, char const* fileName, onCreationFunc* onCreation, void* onCreationClientData,
41  char const* preferredLanguage = "eng");
42  // Note: Unlike most "createNew()" functions, this one doesn't return a new object immediately. Instead, because this class
43  // requires file reading (to parse the Matroska 'Track' headers) before a new object can be initialized, the creation of a new
44  // object is signalled by calling - from the event loop - an 'onCreationFunc' that is passed as a parameter to "createNew()".
45 
46  MatroskaTrack* lookup(unsigned trackNumber) const;
47 
48  // Create a demultiplexor for extracting tracks from this file. (Separate clients will typically have separate demultiplexors.)
50 
51  // Parameters of the file ('Segment'); set when the file is parsed:
52  unsigned timecodeScale() { return fTimecodeScale; } // in nanoseconds
53  float segmentDuration() { return fSegmentDuration; } // in units of "timecodeScale()"
54  float fileDuration(); // in seconds
55 
56  char const* fileName() const { return fFileName; }
57 
61 
63  createSourceForStreaming(FramedSource* baseSource, unsigned trackNumber,
64  unsigned& estBitrate, unsigned& numFiltersInFrontOfTrack);
65  // Takes a data source (which must be a demultiplexed track from this file) and returns
66  // a (possibly modified) data source that can be used for streaming.
67 
68  char const* trackMIMEType(unsigned trackNumber) const;
69  // in the form "<medium-name>/<CODEC-NAME>", or NULL if no such track exists
70 
71  RTPSink* createRTPSinkForTrackNumber(unsigned trackNumber, Groupsock* rtpGroupsock,
72  unsigned char rtpPayloadTypeIfDynamic);
73  // Creates a "RTPSink" object that would be appropriate for streaming the specified track,
74  // or NULL if no appropriate "RTPSink" exists
75 
76  FileSink* createFileSinkForTrackNumber(unsigned trackNumber, char const* fileName);
77  // Creates a "FileSink" object that would be appropriate for recording the contents of
78  // the specified track, or NULL if no appropriate "FileSink" exists.
79 
80 private:
81  MatroskaFile(UsageEnvironment& env, char const* fileName, onCreationFunc* onCreation, void* onCreationClientData,
82  char const* preferredLanguage);
83  // called only by createNew()
84  virtual ~MatroskaFile();
85 
86  static void handleEndOfTrackHeaderParsing(void* clientData);
88 
89  void addTrack(MatroskaTrack* newTrack, unsigned trackNumber);
90  void addCuePoint(double cueTime, u_int64_t clusterOffsetInFile, unsigned blockNumWithinCluster);
91  Boolean lookupCuePoint(double& cueTime, u_int64_t& resultClusterOffsetInFile, unsigned& resultBlockNumWithinCluster);
92  void printCuePoints(FILE* fid);
93 
94  void removeDemux(MatroskaDemux* demux);
95 
96  void getH264ConfigData(MatroskaTrack const* track,
97  u_int8_t*& sps, unsigned& spsSize,
98  u_int8_t*& pps, unsigned& ppsSize);
99  // "sps","pps" are dynamically allocated by this function, and must be delete[]d afterwards
100  void getH265ConfigData(MatroskaTrack const* track,
101  u_int8_t*& vps, unsigned& vpsSize,
102  u_int8_t*& sps, unsigned& spsSize,
103  u_int8_t*& pps, unsigned& ppsSize);
104  // "vps","sps","pps" are dynamically allocated by this function, and must be delete[]d afterwards
105 
106  void getVorbisOrTheoraConfigData(MatroskaTrack const* track,
107  u_int8_t*& identificationHeader, unsigned& identificationHeaderSize,
108  u_int8_t*& commentHeader, unsigned& commentHeaderSize,
109  u_int8_t*& setupHeader, unsigned& setupHeaderSize);
110  // "identificationHeader", "commentHeader", "setupHeader" are dynamically allocated by this function, and must be delete[]d afterwards
111 
112 private:
113  friend class MatroskaFileParser;
114  friend class MatroskaDemux;
115  char const* fFileName;
118  char const* fPreferredLanguage;
119 
120  unsigned fTimecodeScale; // in nanoseconds
121  float fSegmentDuration; // in units of "fTimecodeScale"
123 
124  class MatroskaTrackTable* fTrackTable;
126  class CuePoint* fCuePoints;
129 };
130 
131 // We define our own track type codes as bits (powers of 2), so we can use the set of track types as a bitmap, representing a set:
132 // (Note that MATROSKA_TRACK_TYPE_OTHER must be last, and have the largest value.)
133 #define MATROSKA_TRACK_TYPE_VIDEO 0x01
134 #define MATROSKA_TRACK_TYPE_AUDIO 0x02
135 #define MATROSKA_TRACK_TYPE_SUBTITLE 0x04
136 #define MATROSKA_TRACK_TYPE_OTHER 0x08
137 
139 public:
140  MatroskaTrack();
141  virtual ~MatroskaTrack();
142 
143  // track parameters
144  unsigned trackNumber;
145  u_int8_t trackType;
147  unsigned defaultDuration;
148  char* name;
149  char* language;
150  char* codecID;
152  unsigned numChannels;
153  char const* mimeType;
155  u_int8_t* codecPrivate;
156  Boolean codecPrivateUsesH264FormatForH265; // a hack specifically for H.265 video tracks
157  Boolean codecIsOpus; // a hack for Opus audio
160  char const* colorSampling;
161  char const* colorimetry;
162  unsigned pixelWidth;
163  unsigned pixelHeight;
164  unsigned bitDepth;
165  unsigned subframeSizeSize; // 0 means: frames do not have subframes (the default behavior)
166  Boolean haveSubframes() const { return subframeSizeSize > 0; }
167 };
168 
169 class MatroskaDemux: public Medium {
170 public:
172  FramedSource* newDemuxedTrack(unsigned& resultTrackNumber);
173  // Returns a new stream ("FramedSource" subclass) that represents the next preferred media
174  // track (video, audio, subtitle - in that order) from the file. (Preferred media tracks
175  // are based on the file's language preference.)
176  // This function returns NULL when no more media tracks exist.
177 
178  FramedSource* newDemuxedTrackByTrackNumber(unsigned trackNumber);
179  // As above, but creates a new stream for a specific track number within the Matroska file.
180  // (You should not call this function more than once with the same track number.)
181 
182  // Note: We assume that:
183  // - Every track created by "newDemuxedTrack()" is later read
184  // - All calls to "newDemuxedTrack()" are made before any track is read
185 
186 protected:
187  friend class MatroskaFile;
188  friend class MatroskaFileParser;
189  class MatroskaDemuxedTrack* lookupDemuxedTrack(unsigned trackNumber);
190 
191  MatroskaDemux(MatroskaFile& ourFile); // we're created only by a "MatroskaFile" (a friend)
192  virtual ~MatroskaDemux();
193 
194 private:
195  friend class MatroskaDemuxedTrack;
196  void removeTrack(unsigned trackNumber);
197  void continueReading(); // called by a demuxed track to tell us that it has a pending read ("doGetNextFrame()")
198  void seekToTime(double& seekNPT);
199  void pause();
200 
201  static void handleEndOfFile(void* clientData);
202  void handleEndOfFile();
203 
204  void resetState();
205 
206 private:
210 
211  // Used to implement "newServerMediaSubsession()":
213 };
214 
215 #endif
Boolean isDefault
unsigned char Boolean
Definition: Boolean.hh:25
char const * fFileName
FramedSource * createSourceForStreaming(FramedSource *baseSource, unsigned trackNumber, unsigned &estBitrate, unsigned &numFiltersInFrontOfTrack)
void() onCreationFunc(MatroskaFile *newFile, void *clientData)
Definition: MatroskaFile.hh:39
void printCuePoints(FILE *fid)
class CuePoint * fCuePoints
u_int64_t fSegmentDataOffset
void addTrack(MatroskaTrack *newTrack, unsigned trackNumber)
HashTable * fDemuxedTracksTable
MatroskaDemux * newDemux()
Boolean isForced
unsigned timecodeScale()
Definition: MatroskaFile.hh:52
char const * trackMIMEType(unsigned trackNumber) const
void handleEndOfTrackHeaderParsing()
unsigned chosenAudioTrackNumber()
Definition: MatroskaFile.hh:59
char const * fPreferredLanguage
char const * fileName() const
Definition: MatroskaFile.hh:56
u_int64_t fClusterOffset
virtual ~MatroskaTrack()
FileSink * createFileSinkForTrackNumber(unsigned trackNumber, char const *fileName)
Boolean lookupCuePoint(double &cueTime, u_int64_t &resultClusterOffsetInFile, unsigned &resultBlockNumWithinCluster)
void * fOnCreationClientData
class MatroskaFileParser * fParserForInitialization
void handleEndOfFile()
unsigned pixelWidth
unsigned subframeSizeSize
RTPSink * createRTPSinkForTrackNumber(unsigned trackNumber, Groupsock *rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic)
class MatroskaDemuxedTrack * lookupDemuxedTrack(unsigned trackNumber)
void getH265ConfigData(MatroskaTrack const *track, u_int8_t *&vps, unsigned &vpsSize, u_int8_t *&sps, unsigned &spsSize, u_int8_t *&pps, unsigned &ppsSize)
float fSegmentDuration
u_int8_t trackType
void addCuePoint(double cueTime, u_int64_t clusterOffsetInFile, unsigned blockNumWithinCluster)
class MatroskaTrackTable * fTrackTable
char const * mimeType
void getH264ConfigData(MatroskaTrack const *track, u_int8_t *&sps, unsigned &spsSize, u_int8_t *&pps, unsigned &ppsSize)
u_int8_t fNextTrackTypeToCheck
HashTable * fDemuxesTable
onCreationFunc * fOnCreation
unsigned fChosenAudioTrackNumber
void getVorbisOrTheoraConfigData(MatroskaTrack const *track, u_int8_t *&identificationHeader, unsigned &identificationHeaderSize, u_int8_t *&commentHeader, unsigned &commentHeaderSize, u_int8_t *&setupHeader, unsigned &setupHeaderSize)
u_int64_t fCuesOffset
MatroskaFile(UsageEnvironment &env, char const *fileName, onCreationFunc *onCreation, void *onCreationClientData, char const *preferredLanguage)
unsigned fChosenSubtitleTrackNumber
unsigned bitDepth
FramedSource * newDemuxedTrackByTrackNumber(unsigned trackNumber)
char const * colorSampling
float fileDuration()
MatroskaFile & fOurFile
u_int8_t * headerStrippedBytes
Boolean codecIsOpus
void resetState()
Boolean haveSubframes() const
void removeDemux(MatroskaDemux *demux)
Definition: Media.hh:50
unsigned fTimecodeScale
void removeTrack(unsigned trackNumber)
MatroskaDemux(MatroskaFile &ourFile)
unsigned headerStrippedBytesSize
FramedSource * newDemuxedTrack()
char const * colorimetry
unsigned numChannels
void continueReading()
void seekToTime(double &seekNPT)
unsigned trackNumber
Boolean isEnabled
class MatroskaFileParser * fOurParser
unsigned pixelHeight
static void createNew(UsageEnvironment &env, char const *fileName, onCreationFunc *onCreation, void *onCreationClientData, char const *preferredLanguage="eng")
u_int8_t * codecPrivate
unsigned codecPrivateSize
unsigned chosenSubtitleTrackNumber()
Definition: MatroskaFile.hh:60
unsigned samplingFrequency
virtual ~MatroskaDemux()
float segmentDuration()
Definition: MatroskaFile.hh:53
MatroskaTrack * lookup(unsigned trackNumber) const
unsigned fChosenVideoTrackNumber
unsigned chosenVideoTrackNumber()
Definition: MatroskaFile.hh:58
unsigned defaultDuration
Boolean codecPrivateUsesH264FormatForH265
virtual ~MatroskaFile()