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 server demultiplexor for a Ogg file
19// Implementation
20
21#include "OggFileServerDemux.hh"
22#include "OggFileServerMediaSubsession.hh"
23
24void OggFileServerDemux
25::createNew(UsageEnvironment& env, char const* fileName,
26 onCreationFunc* onCreation, void* onCreationClientData) {
27 (void)new OggFileServerDemux(env, fileName,
28 onCreation, onCreationClientData);
29}
30
31ServerMediaSubsession* OggFileServerDemux::newServerMediaSubsession() {
32 u_int32_t dummyResultTrackNumber;
33 return newServerMediaSubsession(dummyResultTrackNumber);
34}
35
36ServerMediaSubsession* OggFileServerDemux
37::newServerMediaSubsession(u_int32_t& resultTrackNumber) {
38 resultTrackNumber = 0;
39
40 OggTrack* nextTrack = fIter->next();
41 if (nextTrack == NULL) return NULL;
42
43 return newServerMediaSubsessionByTrackNumber(nextTrack->trackNumber);
44}
45
46ServerMediaSubsession* OggFileServerDemux
47::newServerMediaSubsessionByTrackNumber(u_int32_t trackNumber) {
48 OggTrack* track = fOurOggFile->lookup(trackNumber);
49 if (track == NULL) return NULL;
50
51 ServerMediaSubsession* result = OggFileServerMediaSubsession::createNew(*this, track);
52 if (result != NULL) {
53#ifdef DEBUG
54 fprintf(stderr, "Created 'ServerMediaSubsession' object for track #%d: (%s)\n", track->trackNumber, track->mimeType);
55#endif
56 }
57
58 return result;
59}
60
61FramedSource* OggFileServerDemux::newDemuxedTrack(unsigned clientSessionId, u_int32_t trackNumber) {
62 OggDemux* demuxToUse = NULL;
63
64 if (clientSessionId != 0 && clientSessionId == fLastClientSessionId) {
65 demuxToUse = fLastCreatedDemux; // use the same demultiplexor as before
66 // Note: This code relies upon the fact that the creation of streams for different
67 // client sessions do not overlap - so all demuxed tracks are created for one "OggDemux" at a time.
68 // Also, the "clientSessionId != 0" test is a hack, because 'session 0' is special; its audio and video streams
69 // are created and destroyed one-at-a-time, rather than both streams being
70 // created, and then (later) both streams being destroyed (as is the case
71 // for other ('real') session ids). Because of this, a separate demultiplexor is used for each 'session 0' track.
72 }
73
74 if (demuxToUse == NULL) demuxToUse = fOurOggFile->newDemux();
75
76 fLastClientSessionId = clientSessionId;
77 fLastCreatedDemux = demuxToUse;
78
79 return demuxToUse->newDemuxedTrackByTrackNumber(trackNumber);
80}
81
82OggFileServerDemux
83::OggFileServerDemux(UsageEnvironment& env, char const* fileName,
84 onCreationFunc* onCreation, void* onCreationClientData)
85 : Medium(env),
86 fFileName(fileName), fOnCreation(onCreation), fOnCreationClientData(onCreationClientData),
87 fIter(NULL/*until the OggFile is created*/),
88 fLastClientSessionId(0), fLastCreatedDemux(NULL) {
89 OggFile::createNew(env, fileName, onOggFileCreation, this);
90}
91
92OggFileServerDemux::~OggFileServerDemux() {
93 Medium::close(fOurOggFile);
94
95 delete fIter;
96}
97
98void OggFileServerDemux::onOggFileCreation(OggFile* newFile, void* clientData) {
99 ((OggFileServerDemux*)clientData)->onOggFileCreation(newFile);
100}
101
102void OggFileServerDemux::onOggFileCreation(OggFile* newFile) {
103 fOurOggFile = newFile;
104
105 fIter = new OggTrackTableIterator(fOurOggFile->trackTable());
106
107 // Now, call our own creation notification function:
108 if (fOnCreation != NULL) (*fOnCreation)(this, fOnCreationClientData);
109}
110