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 class that encapsulates an Ogg file
19// C++ header
20
21#ifndef _OGG_FILE_HH
22#define _OGG_FILE_HH
23
24#ifndef _RTP_SINK_HH
25#include "RTPSink.hh"
26#endif
27#ifndef _HASH_TABLE_HH
28#include "HashTable.hh"
29#endif
30
31class OggTrack; // forward
32class OggDemux; // forward
33
34class OggFile: public Medium {
35public:
36 typedef void (onCreationFunc)(OggFile* newFile, void* clientData);
37 static void createNew(UsageEnvironment& env, char const* fileName,
38 onCreationFunc* onCreation, void* onCreationClientData);
39 // Note: Unlike most "createNew()" functions, this one doesn't return a new object
40 // immediately. Instead, because this class requires file reading (to parse the
41 // Ogg track headers) before a new object can be initialized, the creation of a new object
42 // is signalled by calling - from the event loop - an 'onCreationFunc' that is passed as
43 // a parameter to "createNew()".
44
45 OggTrack* lookup(u_int32_t trackNumber);
46
47 OggDemux* newDemux();
48 // Creates a demultiplexor for extracting tracks from this file.
49 // (Separate clients will typically have separate demultiplexors.)
50
51 char const* fileName() const { return fFileName; }
52 unsigned numTracks() const;
53
54 FramedSource*
55 createSourceForStreaming(FramedSource* baseSource, u_int32_t trackNumber,
56 unsigned& estBitrate, unsigned& numFiltersInFrontOfTrack);
57 // Takes a data source (which must be a demultiplexed track from this file) and returns
58 // a (possibly modified) data source that can be used for streaming.
59
60 RTPSink* createRTPSinkForTrackNumber(u_int32_t trackNumber, Groupsock* rtpGroupsock,
61 unsigned char rtpPayloadTypeIfDynamic);
62 // Creates a "RTPSink" object that would be appropriate for streaming the specified track,
63 // or NULL if no appropriate "RTPSink" exists
64
65 class OggTrackTable& trackTable() { return *fTrackTable; }
66
67private:
68 OggFile(UsageEnvironment& env, char const* fileName, onCreationFunc* onCreation, void* onCreationClientData);
69 // called only by createNew()
70 virtual ~OggFile();
71
72 static void handleEndOfBosPageParsing(void* clientData);
73 void handleEndOfBosPageParsing();
74
75 void addTrack(OggTrack* newTrack);
76 void removeDemux(OggDemux* demux);
77
78private:
79 friend class OggFileParser;
80 friend class OggDemux;
81 char const* fFileName;
82 onCreationFunc* fOnCreation;
83 void* fOnCreationClientData;
84
85 class OggTrackTable* fTrackTable;
86 HashTable* fDemuxesTable;
87 class OggFileParser* fParserForInitialization;
88};
89
90class OggTrack {
91public:
92 OggTrack();
93 virtual ~OggTrack();
94
95 // track parameters
96 u_int32_t trackNumber; // bitstream serial number
97 char const* mimeType; // NULL if not known
98
99 unsigned samplingFrequency, numChannels; // for audio tracks
100 unsigned estBitrate; // estimate, in kbps (for RTCP)
101
102 // Special headers for Vorbis audio, Theora video, and Opus audio tracks:
103 struct _vtoHdrs {
104 u_int8_t* header[3]; // "identification", "comment", "setup"
105 unsigned headerSize[3];
106
107 // Fields specific to Vorbis audio:
108 unsigned blocksize[2]; // samples per frame (packet)
109 unsigned uSecsPerPacket[2]; // computed as (blocksize[i]*1000000)/samplingFrequency
110 unsigned vorbis_mode_count;
111 unsigned ilog_vorbis_mode_count_minus_1;
112 u_int8_t* vorbis_mode_blockflag;
113 // an array (of size "vorbis_mode_count") of indexes into the (2-entry) "blocksize" array
114
115 // Fields specific to Theora video:
116 u_int8_t KFGSHIFT;
117 unsigned uSecsPerFrame;
118
119 } vtoHdrs;
120
121 Boolean weNeedHeaders() const {
122 return
123 vtoHdrs.header[0] == NULL ||
124 vtoHdrs.header[1] == NULL ||
125 (vtoHdrs.header[2] == NULL && strcmp(mimeType, "audio/OPUS") != 0);
126 }
127};
128
129class OggTrackTableIterator {
130public:
131 OggTrackTableIterator(class OggTrackTable& ourTable);
132 virtual ~OggTrackTableIterator();
133
134 OggTrack* next();
135
136private:
137 HashTable::Iterator* fIter;
138};
139
140class OggDemux: public Medium {
141public:
142 FramedSource* newDemuxedTrack(u_int32_t& resultTrackNumber);
143 // Returns a new stream ("FramedSource" subclass) that represents the next media track
144 // from the file. This function returns NULL when no more media tracks exist.
145
146 FramedSource* newDemuxedTrackByTrackNumber(unsigned trackNumber);
147 // As above, but creates a new stream for a specific track number within the Matroska file.
148 // (You should not call this function more than once with the same track number.)
149
150 // Note: We assume that:
151 // - Every track created by "newDemuxedTrack()" is later read
152 // - All calls to "newDemuxedTrack()" are made before any track is read
153
154protected:
155 friend class OggFile;
156 friend class OggFileParser;
157 class OggDemuxedTrack* lookupDemuxedTrack(u_int32_t trackNumber);
158
159 OggDemux(OggFile& ourFile);
160 virtual ~OggDemux();
161
162private:
163 friend class OggDemuxedTrack;
164 void removeTrack(u_int32_t trackNumber);
165 void continueReading(); // called by a demuxed track to tell us that it has a pending read ("doGetNextFrame()")
166
167 static void handleEndOfFile(void* clientData);
168 void handleEndOfFile();
169
170private:
171 OggFile& fOurFile;
172 class OggFileParser* fOurParser;
173 HashTable* fDemuxedTracksTable;
174 OggTrackTableIterator* fIter;
175};
176
177#endif
178