| 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 data structure that represents a session that consists of | 
|---|
| 19 | // potentially multiple (audio and/or video) sub-sessions | 
|---|
| 20 | // (This data structure is used for media *streamers* - i.e., servers. | 
|---|
| 21 | //  For media receivers, use "MediaSession" instead.) | 
|---|
| 22 | // C++ header | 
|---|
| 23 |  | 
|---|
| 24 | #ifndef _SERVER_MEDIA_SESSION_HH | 
|---|
| 25 | #define _SERVER_MEDIA_SESSION_HH | 
|---|
| 26 |  | 
|---|
| 27 | #ifndef _RTCP_HH | 
|---|
| 28 | #include "RTCP.hh" | 
|---|
| 29 | #endif | 
|---|
| 30 |  | 
|---|
| 31 | class ServerMediaSubsession; // forward | 
|---|
| 32 |  | 
|---|
| 33 | class ServerMediaSession: public Medium { | 
|---|
| 34 | public: | 
|---|
| 35 | static ServerMediaSession* createNew(UsageEnvironment& env, | 
|---|
| 36 | char const* streamName = NULL, | 
|---|
| 37 | char const* info = NULL, | 
|---|
| 38 | char const* description = NULL, | 
|---|
| 39 | Boolean isSSM = False, | 
|---|
| 40 | char const* miscSDPLines = NULL); | 
|---|
| 41 |  | 
|---|
| 42 | static Boolean lookupByName(UsageEnvironment& env, | 
|---|
| 43 | char const* mediumName, | 
|---|
| 44 | ServerMediaSession*& resultSession); | 
|---|
| 45 |  | 
|---|
| 46 | char* generateSDPDescription(); // based on the entire session | 
|---|
| 47 | // Note: The caller is responsible for freeing the returned string | 
|---|
| 48 |  | 
|---|
| 49 | char const* streamName() const { return fStreamName; } | 
|---|
| 50 |  | 
|---|
| 51 | Boolean addSubsession(ServerMediaSubsession* subsession); | 
|---|
| 52 | unsigned numSubsessions() const { return fSubsessionCounter; } | 
|---|
| 53 |  | 
|---|
| 54 | void testScaleFactor(float& scale); // sets "scale" to the actual supported scale | 
|---|
| 55 | float duration() const; | 
|---|
| 56 | // a result == 0 means an unbounded session (the default) | 
|---|
| 57 | // a result < 0 means: subsession durations differ; the result is -(the largest). | 
|---|
| 58 | // a result > 0 means: this is the duration of a bounded session | 
|---|
| 59 |  | 
|---|
| 60 | virtual void noteLiveness(); | 
|---|
| 61 | // called whenever a client - accessing this media - notes liveness. | 
|---|
| 62 | // The default implementation does nothing, but subclasses can redefine this - e.g., if you | 
|---|
| 63 | // want to remove long-unused "ServerMediaSession"s from the server. | 
|---|
| 64 |  | 
|---|
| 65 | unsigned referenceCount() const { return fReferenceCount; } | 
|---|
| 66 | void incrementReferenceCount() { ++fReferenceCount; } | 
|---|
| 67 | void decrementReferenceCount() { if (fReferenceCount > 0) --fReferenceCount; } | 
|---|
| 68 | Boolean& deleteWhenUnreferenced() { return fDeleteWhenUnreferenced; } | 
|---|
| 69 |  | 
|---|
| 70 | void deleteAllSubsessions(); | 
|---|
| 71 | // Removes and deletes all subsessions added by "addSubsession()", returning us to an 'empty' state | 
|---|
| 72 | // Note: If you have already added this "ServerMediaSession" to a "RTSPServer" then, before calling this function, | 
|---|
| 73 | //   you must first close any client connections that use it, | 
|---|
| 74 | //   by calling "RTSPServer::closeAllClientSessionsForServerMediaSession()". | 
|---|
| 75 |  | 
|---|
| 76 | protected: | 
|---|
| 77 | ServerMediaSession(UsageEnvironment& env, char const* streamName, | 
|---|
| 78 | char const* info, char const* description, | 
|---|
| 79 | Boolean isSSM, char const* miscSDPLines); | 
|---|
| 80 | // called only by "createNew()" | 
|---|
| 81 |  | 
|---|
| 82 | virtual ~ServerMediaSession(); | 
|---|
| 83 |  | 
|---|
| 84 | private: // redefined virtual functions | 
|---|
| 85 | virtual Boolean isServerMediaSession() const; | 
|---|
| 86 |  | 
|---|
| 87 | private: | 
|---|
| 88 | Boolean fIsSSM; | 
|---|
| 89 |  | 
|---|
| 90 | // Linkage fields: | 
|---|
| 91 | friend class ServerMediaSubsessionIterator; | 
|---|
| 92 | ServerMediaSubsession* fSubsessionsHead; | 
|---|
| 93 | ServerMediaSubsession* fSubsessionsTail; | 
|---|
| 94 | unsigned fSubsessionCounter; | 
|---|
| 95 |  | 
|---|
| 96 | char* fStreamName; | 
|---|
| 97 | char* fInfoSDPString; | 
|---|
| 98 | char* fDescriptionSDPString; | 
|---|
| 99 | char* fMiscSDPLines; | 
|---|
| 100 | struct timeval fCreationTime; | 
|---|
| 101 | unsigned fReferenceCount; | 
|---|
| 102 | Boolean fDeleteWhenUnreferenced; | 
|---|
| 103 | }; | 
|---|
| 104 |  | 
|---|
| 105 |  | 
|---|
| 106 | class ServerMediaSubsessionIterator { | 
|---|
| 107 | public: | 
|---|
| 108 | ServerMediaSubsessionIterator(ServerMediaSession& session); | 
|---|
| 109 | virtual ~ServerMediaSubsessionIterator(); | 
|---|
| 110 |  | 
|---|
| 111 | ServerMediaSubsession* next(); // NULL if none | 
|---|
| 112 | void reset(); | 
|---|
| 113 |  | 
|---|
| 114 | private: | 
|---|
| 115 | ServerMediaSession& fOurSession; | 
|---|
| 116 | ServerMediaSubsession* fNextPtr; | 
|---|
| 117 | }; | 
|---|
| 118 |  | 
|---|
| 119 |  | 
|---|
| 120 | class ServerMediaSubsession: public Medium { | 
|---|
| 121 | public: | 
|---|
| 122 | unsigned trackNumber() const { return fTrackNumber; } | 
|---|
| 123 | char const* trackId(); | 
|---|
| 124 | virtual char const* sdpLines() = 0; | 
|---|
| 125 | virtual void getStreamParameters(unsigned clientSessionId, // in | 
|---|
| 126 | netAddressBits clientAddress, // in | 
|---|
| 127 | Port const& clientRTPPort, // in | 
|---|
| 128 | Port const& clientRTCPPort, // in | 
|---|
| 129 | int tcpSocketNum, // in (-1 means use UDP, not TCP) | 
|---|
| 130 | unsigned char rtpChannelId, // in (used if TCP) | 
|---|
| 131 | unsigned char rtcpChannelId, // in (used if TCP) | 
|---|
| 132 | netAddressBits& destinationAddress, // in out | 
|---|
| 133 | u_int8_t& destinationTTL, // in out | 
|---|
| 134 | Boolean& isMulticast, // out | 
|---|
| 135 | Port& serverRTPPort, // out | 
|---|
| 136 | Port& serverRTCPPort, // out | 
|---|
| 137 | void*& streamToken // out | 
|---|
| 138 | ) = 0; | 
|---|
| 139 | virtual void startStream(unsigned clientSessionId, void* streamToken, | 
|---|
| 140 | TaskFunc* rtcpRRHandler, | 
|---|
| 141 | void* rtcpRRHandlerClientData, | 
|---|
| 142 | unsigned short& rtpSeqNum, | 
|---|
| 143 | unsigned& rtpTimestamp, | 
|---|
| 144 | ServerRequestAlternativeByteHandler* serverRequestAlternativeByteHandler, | 
|---|
| 145 | void* serverRequestAlternativeByteHandlerClientData) = 0; | 
|---|
| 146 | virtual void pauseStream(unsigned clientSessionId, void* streamToken); | 
|---|
| 147 | virtual void seekStream(unsigned clientSessionId, void* streamToken, double& seekNPT, | 
|---|
| 148 | double streamDuration, u_int64_t& numBytes); | 
|---|
| 149 | // This routine is used to seek by relative (i.e., NPT) time. | 
|---|
| 150 | // "streamDuration", if >0.0, specifies how much data to stream, past "seekNPT".  (If <=0.0, all remaining data is streamed.) | 
|---|
| 151 | // "numBytes" returns the size (in bytes) of the data to be streamed, or 0 if unknown or unlimited. | 
|---|
| 152 | virtual void seekStream(unsigned clientSessionId, void* streamToken, char*& absStart, char*& absEnd); | 
|---|
| 153 | // This routine is used to seek by 'absolute' time. | 
|---|
| 154 | // "absStart" should be a string of the form "YYYYMMDDTHHMMSSZ" or "YYYYMMDDTHHMMSS.<frac>Z". | 
|---|
| 155 | // "absEnd" should be either NULL (for no end time), or a string of the same form as "absStart". | 
|---|
| 156 | // These strings may be modified in-place, or can be reassigned to a newly-allocated value (after delete[]ing the original). | 
|---|
| 157 | virtual void nullSeekStream(unsigned clientSessionId, void* streamToken, | 
|---|
| 158 | double streamEndTime, u_int64_t& numBytes); | 
|---|
| 159 | // Called whenever we're handling a "PLAY" command without a specified start time. | 
|---|
| 160 | virtual void setStreamScale(unsigned clientSessionId, void* streamToken, float scale); | 
|---|
| 161 | virtual float getCurrentNPT(void* streamToken); | 
|---|
| 162 | virtual FramedSource* getStreamSource(void* streamToken); | 
|---|
| 163 | virtual void getRTPSinkandRTCP(void* streamToken, | 
|---|
| 164 | RTPSink const*& rtpSink, RTCPInstance const*& rtcp) = 0; | 
|---|
| 165 | // Returns pointers to the "RTPSink" and "RTCPInstance" objects for "streamToken". | 
|---|
| 166 | // (This can be useful if you want to get the associated 'Groupsock' objects, for example.) | 
|---|
| 167 | // You must not delete these objects, or start/stop playing them; instead, that is done | 
|---|
| 168 | // using the "startStream()" and "deleteStream()" functions. | 
|---|
| 169 | virtual void deleteStream(unsigned clientSessionId, void*& streamToken); | 
|---|
| 170 |  | 
|---|
| 171 | virtual void testScaleFactor(float& scale); // sets "scale" to the actual supported scale | 
|---|
| 172 | virtual float duration() const; | 
|---|
| 173 | // returns 0 for an unbounded session (the default) | 
|---|
| 174 | // returns > 0 for a bounded session | 
|---|
| 175 | virtual void getAbsoluteTimeRange(char*& absStartTime, char*& absEndTime) const; | 
|---|
| 176 | // Subclasses can reimplement this iff they support seeking by 'absolute' time. | 
|---|
| 177 |  | 
|---|
| 178 | // The following may be called by (e.g.) SIP servers, for which the | 
|---|
| 179 | // address and port number fields in SDP descriptions need to be non-zero: | 
|---|
| 180 | void setServerAddressAndPortForSDP(netAddressBits addressBits, | 
|---|
| 181 | portNumBits portBits); | 
|---|
| 182 |  | 
|---|
| 183 | protected: // we're a virtual base class | 
|---|
| 184 | ServerMediaSubsession(UsageEnvironment& env); | 
|---|
| 185 | virtual ~ServerMediaSubsession(); | 
|---|
| 186 |  | 
|---|
| 187 | char const* rangeSDPLine() const; | 
|---|
| 188 | // returns a string to be delete[]d | 
|---|
| 189 |  | 
|---|
| 190 | ServerMediaSession* fParentSession; | 
|---|
| 191 | netAddressBits fServerAddressForSDP; | 
|---|
| 192 | portNumBits fPortNumForSDP; | 
|---|
| 193 |  | 
|---|
| 194 | private: | 
|---|
| 195 | friend class ServerMediaSession; | 
|---|
| 196 | friend class ServerMediaSubsessionIterator; | 
|---|
| 197 | ServerMediaSubsession* fNext; | 
|---|
| 198 |  | 
|---|
| 199 | unsigned fTrackNumber; // within an enclosing ServerMediaSession | 
|---|
| 200 | char const* fTrackId; | 
|---|
| 201 | }; | 
|---|
| 202 |  | 
|---|
| 203 | #endif | 
|---|
| 204 |  | 
|---|