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-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 | |
31 | class OggTrack; // forward |
32 | class OggDemux; // forward |
33 | |
34 | class OggFile: public Medium { |
35 | public: |
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 | |
67 | private: |
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 | |
78 | private: |
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 | |
90 | class OggTrack { |
91 | public: |
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* [3]; // "identification", "comment", "setup" |
105 | unsigned [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 () 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 | |
129 | class OggTrackTableIterator { |
130 | public: |
131 | OggTrackTableIterator(class OggTrackTable& ourTable); |
132 | virtual ~OggTrackTableIterator(); |
133 | |
134 | OggTrack* next(); |
135 | |
136 | private: |
137 | HashTable::Iterator* fIter; |
138 | }; |
139 | |
140 | class OggDemux: public Medium { |
141 | public: |
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 | |
154 | protected: |
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 | |
162 | private: |
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 | |
170 | private: |
171 | OggFile& fOurFile; |
172 | class OggFileParser* fOurParser; |
173 | HashTable* fDemuxedTracksTable; |
174 | OggTrackTableIterator* fIter; |
175 | }; |
176 | |
177 | #endif |
178 | |