| 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 | |