live
MatroskaFile.hh
Go to the documentation of this file.
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-2024 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
34class MatroskaTrack; // forward
35class MatroskaDemux; // forward
36
37typedef void MatroskaDemuxOnDeletionFunc(void* objectToNotify, MatroskaDemux* demuxBeingDeleted);
38
39class MatroskaFile: public Medium {
40public:
41 typedef void (onCreationFunc)(MatroskaFile* newFile, void* clientData);
42 static void createNew(UsageEnvironment& env, char const* fileName, onCreationFunc* onCreation, void* onCreationClientData,
43 char const* preferredLanguage = "eng");
44 // Note: Unlike most "createNew()" functions, this one doesn't return a new object immediately. Instead, because this class
45 // requires file reading (to parse the Matroska 'Track' headers) before a new object can be initialized, the creation of a new
46 // object is signalled by calling - from the event loop - an 'onCreationFunc' that is passed as a parameter to "createNew()".
47
48 MatroskaTrack* lookup(unsigned trackNumber) const;
49
50 MatroskaDemux* newDemux(MatroskaDemuxOnDeletionFunc* onDeletionFunc = NULL, void* objectToNotify = NULL);
51 // Creates a demultiplexor for extracting tracks from this file.
52 // (Separate clients will typically have separate demultiplexors.)
53
54 // Parameters of the file ('Segment'); set when the file is parsed:
55 unsigned timecodeScale() { return fTimecodeScale; } // in nanoseconds
56 float segmentDuration() { return fSegmentDuration; } // in units of "timecodeScale()"
57 float fileDuration(); // in seconds
58
59 char const* fileName() const { return fFileName; }
60
64
66 createSourceForStreaming(FramedSource* baseSource, unsigned trackNumber,
67 unsigned& estBitrate, unsigned& numFiltersInFrontOfTrack);
68 // Takes a data source (which must be a demultiplexed track from this file) and returns
69 // a (possibly modified) data source that can be used for streaming.
70
71 char const* trackMIMEType(unsigned trackNumber) const;
72 // in the form "<medium-name>/<CODEC-NAME>", or NULL if no such track exists
73
74 RTPSink* createRTPSinkForTrackNumber(unsigned trackNumber, Groupsock* rtpGroupsock,
75 unsigned char rtpPayloadTypeIfDynamic);
76 // Creates a "RTPSink" object that would be appropriate for streaming the specified track,
77 // or NULL if no appropriate "RTPSink" exists
78
79 FileSink* createFileSinkForTrackNumber(unsigned trackNumber, char const* fileName);
80 // Creates a "FileSink" object that would be appropriate for recording the contents of
81 // the specified track, or NULL if no appropriate "FileSink" exists.
82
83private:
84 MatroskaFile(UsageEnvironment& env, char const* fileName, onCreationFunc* onCreation, void* onCreationClientData,
85 char const* preferredLanguage);
86 // called only by createNew()
87 virtual ~MatroskaFile();
88
89 static void handleEndOfTrackHeaderParsing(void* clientData);
91
92 void addTrack(MatroskaTrack* newTrack, unsigned trackNumber);
93 void addCuePoint(double cueTime, u_int64_t clusterOffsetInFile, unsigned blockNumWithinCluster);
94 Boolean lookupCuePoint(double& cueTime, u_int64_t& resultClusterOffsetInFile, unsigned& resultBlockNumWithinCluster);
95 void printCuePoints(FILE* fid);
96
98
100 u_int8_t*& sps, unsigned& spsSize,
101 u_int8_t*& pps, unsigned& ppsSize);
102 // "sps","pps" are dynamically allocated by this function, and must be delete[]d afterwards
104 u_int8_t*& vps, unsigned& vpsSize,
105 u_int8_t*& sps, unsigned& spsSize,
106 u_int8_t*& pps, unsigned& ppsSize);
107 // "vps","sps","pps" are dynamically allocated by this function, and must be delete[]d afterwards
108
110 u_int8_t*& identificationHeader, unsigned& identificationHeaderSize,
111 u_int8_t*& commentHeader, unsigned& commentHeaderSize,
112 u_int8_t*& setupHeader, unsigned& setupHeaderSize);
113 // "identificationHeader", "commentHeader", "setupHeader" are dynamically allocated by this function, and must be delete[]d afterwards
114
115private:
116 friend class MatroskaFileParser;
117 friend class MatroskaDemux;
118 char const* fFileName;
122
123 unsigned fTimecodeScale; // in nanoseconds
124 float fSegmentDuration; // in units of "fTimecodeScale"
126
127 class MatroskaTrackTable* fTrackTable;
129 class CuePoint* fCuePoints;
132};
133
134// 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:
135// (Note that MATROSKA_TRACK_TYPE_OTHER must be last, and have the largest value.)
136#define MATROSKA_TRACK_TYPE_VIDEO 0x01
137#define MATROSKA_TRACK_TYPE_AUDIO 0x02
138#define MATROSKA_TRACK_TYPE_SUBTITLE 0x04
139#define MATROSKA_TRACK_TYPE_OTHER 0x08
140
142public:
144 virtual ~MatroskaTrack();
145
146 // track parameters
147 unsigned trackNumber;
148 u_int8_t trackType;
151 char* name;
152 char* language;
153 char* codecID;
155 unsigned numChannels;
156 char const* mimeType;
158 u_int8_t* codecPrivate;
159 Boolean codecPrivateUsesH264FormatForH265; // a hack specifically for H.265 video tracks
160 Boolean codecIsOpus; // a hack for Opus audio
163 char const* colorSampling;
164 char const* colorimetry;
165 unsigned pixelWidth;
166 unsigned pixelHeight;
167 unsigned bitDepth;
168 unsigned subframeSizeSize; // 0 means: frames do not have subframes (the default behavior)
169 Boolean haveSubframes() const { return subframeSizeSize > 0; }
170};
171
172class MatroskaDemux: public Medium {
173public:
175 FramedSource* newDemuxedTrack(unsigned& resultTrackNumber);
176 // Returns a new stream ("FramedSource" subclass) that represents the next preferred media
177 // track (video, audio, subtitle - in that order) from the file. (Preferred media tracks
178 // are based on the file's language preference.)
179 // This function returns NULL when no more media tracks exist.
180
182 // As above, but creates a new stream for a specific track number within the Matroska file.
183 // (You should not call this function more than once with the same track number.)
184
185 // Note: We assume that:
186 // - Every track created by "newDemuxedTrack()" is later read
187 // - All calls to "newDemuxedTrack()" are made before any track is read
188
189protected:
190 friend class MatroskaFile;
191 friend class MatroskaFileParser;
192 class MatroskaDemuxedTrack* lookupDemuxedTrack(unsigned trackNumber);
193
194 MatroskaDemux(MatroskaFile& ourFile); // we're created only by a "MatroskaFile" (a friend)
195 virtual ~MatroskaDemux();
196
197private:
199 void removeTrack(unsigned trackNumber);
200 void continueReading(); // called by a demuxed track to tell us that it has a pending read ("doGetNextFrame()")
201 void seekToTime(double& seekNPT);
202 void pause();
203
204 static void handleEndOfFile(void* clientData);
206
208
209private:
213
214 // Used to implement "newServerMediaSubsession()":
216};
217
218#endif
unsigned char Boolean
Definition: Boolean.hh:25
void MatroskaDemuxOnDeletionFunc(void *objectToNotify, MatroskaDemux *demuxBeingDeleted)
Definition: MatroskaFile.hh:37
#define NULL
static void handleEndOfFile(void *clientData)
FramedSource * newDemuxedTrack(unsigned &resultTrackNumber)
class MatroskaFileParser * fOurParser
void continueReading()
void removeTrack(unsigned trackNumber)
void handleEndOfFile()
void resetState()
void seekToTime(double &seekNPT)
virtual ~MatroskaDemux()
MatroskaFile & fOurFile
FramedSource * newDemuxedTrackByTrackNumber(unsigned trackNumber)
FramedSource * newDemuxedTrack()
class MatroskaDemuxedTrack * lookupDemuxedTrack(unsigned trackNumber)
MatroskaDemux(MatroskaFile &ourFile)
HashTable * fDemuxedTracksTable
u_int8_t fNextTrackTypeToCheck
char const * trackMIMEType(unsigned trackNumber) const
class MatroskaFileParser * fParserForInitialization
unsigned fChosenVideoTrackNumber
void getH264ConfigData(MatroskaTrack const *track, u_int8_t *&sps, unsigned &spsSize, u_int8_t *&pps, unsigned &ppsSize)
MatroskaDemux * newDemux(MatroskaDemuxOnDeletionFunc *onDeletionFunc=NULL, void *objectToNotify=NULL)
HashTable * fDemuxesTable
MatroskaFile(UsageEnvironment &env, char const *fileName, onCreationFunc *onCreation, void *onCreationClientData, char const *preferredLanguage)
unsigned chosenSubtitleTrackNumber()
Definition: MatroskaFile.hh:63
unsigned fTimecodeScale
MatroskaTrack * lookup(unsigned trackNumber) const
static void handleEndOfTrackHeaderParsing(void *clientData)
onCreationFunc * fOnCreation
char const * fPreferredLanguage
void addTrack(MatroskaTrack *newTrack, unsigned trackNumber)
float fileDuration()
void() onCreationFunc(MatroskaFile *newFile, void *clientData)
Definition: MatroskaFile.hh:41
void printCuePoints(FILE *fid)
void getH265ConfigData(MatroskaTrack const *track, u_int8_t *&vps, unsigned &vpsSize, u_int8_t *&sps, unsigned &spsSize, u_int8_t *&pps, unsigned &ppsSize)
char const * fileName() const
Definition: MatroskaFile.hh:59
RTPSink * createRTPSinkForTrackNumber(unsigned trackNumber, Groupsock *rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic)
static void createNew(UsageEnvironment &env, char const *fileName, onCreationFunc *onCreation, void *onCreationClientData, char const *preferredLanguage="eng")
float segmentDuration()
Definition: MatroskaFile.hh:56
unsigned timecodeScale()
Definition: MatroskaFile.hh:55
unsigned chosenVideoTrackNumber()
Definition: MatroskaFile.hh:61
u_int64_t fSegmentDataOffset
virtual ~MatroskaFile()
class CuePoint * fCuePoints
void removeDemux(MatroskaDemux *demux)
float fSegmentDuration
void * fOnCreationClientData
Boolean lookupCuePoint(double &cueTime, u_int64_t &resultClusterOffsetInFile, unsigned &resultBlockNumWithinCluster)
void addCuePoint(double cueTime, u_int64_t clusterOffsetInFile, unsigned blockNumWithinCluster)
FramedSource * createSourceForStreaming(FramedSource *baseSource, unsigned trackNumber, unsigned &estBitrate, unsigned &numFiltersInFrontOfTrack)
u_int64_t fClusterOffset
unsigned fChosenAudioTrackNumber
unsigned fChosenSubtitleTrackNumber
void handleEndOfTrackHeaderParsing()
unsigned chosenAudioTrackNumber()
Definition: MatroskaFile.hh:62
u_int64_t fCuesOffset
void getVorbisOrTheoraConfigData(MatroskaTrack const *track, u_int8_t *&identificationHeader, unsigned &identificationHeaderSize, u_int8_t *&commentHeader, unsigned &commentHeaderSize, u_int8_t *&setupHeader, unsigned &setupHeaderSize)
FileSink * createFileSinkForTrackNumber(unsigned trackNumber, char const *fileName)
char const * fFileName
class MatroskaTrackTable * fTrackTable
u_int8_t * codecPrivate
unsigned numChannels
unsigned defaultDuration
Boolean haveSubframes() const
u_int8_t * headerStrippedBytes
Boolean codecIsOpus
unsigned pixelHeight
Boolean isEnabled
Boolean isDefault
unsigned codecPrivateSize
Boolean isForced
char const * mimeType
unsigned subframeSizeSize
unsigned pixelWidth
Boolean codecPrivateUsesH264FormatForH265
char const * colorimetry
char const * colorSampling
unsigned samplingFrequency
u_int8_t trackType
virtual ~MatroskaTrack()
unsigned bitDepth
unsigned headerStrippedBytesSize
unsigned trackNumber
Definition: Media.hh:50