ProxyServerMediaSession.hh 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  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. This library is distributed in the hope that it will be useful, but WITHOUT
  7. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
  9. more details.
  10. You should have received a copy of the GNU Lesser General Public License
  11. along with this library; if not, write to the Free Software Foundation, Inc.,
  12. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  13. **********/
  14. // "liveMedia"
  15. // Copyright (c) 1996-2019 Live Networks, Inc. All rights reserved.
  16. // A subclass of "ServerMediaSession" that can be used to create a (unicast) RTSP servers that acts as a 'proxy' for
  17. // another (unicast or multicast) RTSP/RTP stream.
  18. // C++ header
  19. #ifndef _PROXY_SERVER_MEDIA_SESSION_HH
  20. #define _PROXY_SERVER_MEDIA_SESSION_HH
  21. #ifndef _SERVER_MEDIA_SESSION_HH
  22. #include "ServerMediaSession.hh"
  23. #endif
  24. #ifndef _MEDIA_SESSION_HH
  25. #include "MediaSession.hh"
  26. #endif
  27. #ifndef _RTSP_CLIENT_HH
  28. #include "RTSPClient.hh"
  29. #endif
  30. #ifndef _MEDIA_TRANSCODING_TABLE_HH
  31. #include "MediaTranscodingTable.hh"
  32. #endif
  33. // A subclass of "RTSPClient", used to refer to the particular "ProxyServerMediaSession" object being used.
  34. // It is used only within the implementation of "ProxyServerMediaSession", but is defined here, in case developers wish to
  35. // subclass it.
  36. class ProxyRTSPClient: public RTSPClient {
  37. public:
  38. ProxyRTSPClient(class ProxyServerMediaSession& ourServerMediaSession, char const* rtspURL,
  39. char const* username, char const* password,
  40. portNumBits tunnelOverHTTPPortNum, int verbosityLevel, int socketNumToServer,
  41. unsigned interPacketGapMaxTime = 0);
  42. virtual ~ProxyRTSPClient();
  43. void continueAfterDESCRIBE(char const* sdpDescription);
  44. void continueAfterLivenessCommand(int resultCode, Boolean serverSupportsGetParameter);
  45. void continueAfterSETUP(int resultCode);
  46. void continueAfterPLAY(int resultCode);
  47. void scheduleReset();
  48. private:
  49. void reset();
  50. int connectToServer(int socketNum, portNumBits remotePortNum);
  51. Authenticator* auth() { return fOurAuthenticator; }
  52. void scheduleLivenessCommand();
  53. static void sendLivenessCommand(void* clientData);
  54. void checkInterPacketGaps_(Boolean delayReset);
  55. static void checkInterPacketGaps(void* clientData);
  56. void doReset();
  57. static void doReset(void* clientData);
  58. void scheduleDESCRIBECommand();
  59. static void sendDESCRIBE(void* clientData);
  60. static void subsessionTimeout(void* clientData);
  61. void handleSubsessionTimeout();
  62. private:
  63. friend class ProxyServerMediaSession;
  64. friend class ProxyServerMediaSubsession;
  65. ProxyServerMediaSession& fOurServerMediaSession;
  66. char* fOurURL;
  67. Authenticator* fOurAuthenticator;
  68. Boolean fStreamRTPOverTCP;
  69. class ProxyServerMediaSubsession *fSetupQueueHead, *fSetupQueueTail;
  70. unsigned fNumSetupsDone;
  71. unsigned fNextDESCRIBEDelay; // in seconds
  72. unsigned fTotNumPacketsReceived;
  73. unsigned fInterPacketGapMaxTime; // in seconds
  74. Boolean fServerSupportsGetParameter, fLastCommandWasPLAY, fDoneDESCRIBE;
  75. TaskToken fLivenessCommandTask, fDESCRIBECommandTask, fSubsessionTimerTask, fResetTask, fInterPacketGapsTask;
  76. };
  77. typedef ProxyRTSPClient*
  78. createNewProxyRTSPClientFunc(ProxyServerMediaSession& ourServerMediaSession,
  79. char const* rtspURL,
  80. char const* username, char const* password,
  81. portNumBits tunnelOverHTTPPortNum, int verbosityLevel,
  82. int socketNumToServer, unsigned interPacketGapMaxTime);
  83. ProxyRTSPClient*
  84. defaultCreateNewProxyRTSPClientFunc(ProxyServerMediaSession& ourServerMediaSession,
  85. char const* rtspURL,
  86. char const* username, char const* password,
  87. portNumBits tunnelOverHTTPPortNum, int verbosityLevel,
  88. int socketNumToServer, unsigned interPacketGapMaxTime);
  89. class ProxyServerMediaSession: public ServerMediaSession {
  90. public:
  91. static ProxyServerMediaSession* createNew(UsageEnvironment& env,
  92. GenericMediaServer* ourMediaServer, // Note: We can be used by just one server
  93. char const* inputStreamURL, // the "rtsp://" URL of the stream we'll be proxying
  94. char const* streamName = NULL,
  95. char const* username = NULL, char const* password = NULL,
  96. portNumBits tunnelOverHTTPPortNum = 0,
  97. // for streaming the *proxied* (i.e., back-end) stream
  98. int verbosityLevel = 0,
  99. int socketNumToServer = -1,
  100. MediaTranscodingTable* transcodingTable = NULL,
  101. unsigned interPacketGapMaxTime = 0);
  102. // Hack: "tunnelOverHTTPPortNum" == 0xFFFF (i.e., all-ones) means: Stream RTP/RTCP-over-TCP, but *not* using HTTP
  103. // "verbosityLevel" == 1 means display basic proxy setup info; "verbosityLevel" == 2 means display RTSP client protocol also.
  104. // If "socketNumToServer" is >= 0, then it is the socket number of an already-existing TCP connection to the server.
  105. // (In this case, "inputStreamURL" must point to the socket's endpoint, so that it can be accessed via the socket.)
  106. virtual ~ProxyServerMediaSession();
  107. char const* url() const;
  108. char describeCompletedFlag;
  109. // initialized to 0; set to 1 when the back-end "DESCRIBE" completes.
  110. // (This can be used as a 'watch variable' in "doEventLoop()".)
  111. Boolean describeCompletedSuccessfully() const { return fClientMediaSession != NULL; }
  112. // This can be used - along with "describeCompletdFlag" - to check whether the back-end "DESCRIBE" completed *successfully*.
  113. protected:
  114. ProxyServerMediaSession(UsageEnvironment& env, GenericMediaServer* ourMediaServer,
  115. char const* inputStreamURL, char const* streamName,
  116. char const* username, char const* password,
  117. portNumBits tunnelOverHTTPPortNum, int verbosityLevel,
  118. int socketNumToServer,
  119. MediaTranscodingTable* transcodingTable,
  120. unsigned interPacketGapMaxTime = 0,
  121. createNewProxyRTSPClientFunc* ourCreateNewProxyRTSPClientFunc
  122. = defaultCreateNewProxyRTSPClientFunc,
  123. portNumBits initialPortNum = 6970,
  124. Boolean multiplexRTCPWithRTP = False);
  125. // If you subclass "ProxyRTSPClient", then you will also need to define your own function
  126. // - with signature "createNewProxyRTSPClientFunc" (see above) - that creates a new object
  127. // of this subclass. You should also subclass "ProxyServerMediaSession" and, in your
  128. // subclass's constructor, initialize the parent class (i.e., "ProxyServerMediaSession")
  129. // constructor by passing your new function as the "ourCreateNewProxyRTSPClientFunc"
  130. // parameter.
  131. // Subclasses may redefine the following functions, if they want "ProxyServerSubsession"s
  132. // to create subclassed "Groupsock" and/or "RTCPInstance" objects:
  133. virtual Groupsock* createGroupsock(struct in_addr const& addr, Port port);
  134. virtual RTCPInstance* createRTCP(Groupsock* RTCPgs, unsigned totSessionBW, /* in kbps */
  135. unsigned char const* cname, RTPSink* sink);
  136. virtual Boolean allowProxyingForSubsession(MediaSubsession const& mss);
  137. // By default, this function always returns True. However, a subclass may redefine this
  138. // if it wishes to restrict which subsessions of a stream get proxied - e.g., if it wishes
  139. // to proxy only video tracks, but not audio (or other) tracks.
  140. protected:
  141. GenericMediaServer* fOurMediaServer;
  142. ProxyRTSPClient* fProxyRTSPClient;
  143. MediaSession* fClientMediaSession;
  144. private:
  145. friend class ProxyRTSPClient;
  146. friend class ProxyServerMediaSubsession;
  147. void continueAfterDESCRIBE(char const* sdpDescription);
  148. void resetDESCRIBEState(); // undoes what was done by "contineAfterDESCRIBE()"
  149. private:
  150. int fVerbosityLevel;
  151. class PresentationTimeSessionNormalizer* fPresentationTimeSessionNormalizer;
  152. createNewProxyRTSPClientFunc* fCreateNewProxyRTSPClientFunc;
  153. MediaTranscodingTable* fTranscodingTable;
  154. portNumBits fInitialPortNum;
  155. Boolean fMultiplexRTCPWithRTP;
  156. };
  157. ////////// PresentationTimeSessionNormalizer and PresentationTimeSubsessionNormalizer definitions //////////
  158. // The following two classes are used by proxies to convert incoming streams' presentation times into wall-clock-aligned
  159. // presentation times that are suitable for our "RTPSink"s (for the corresponding outgoing streams).
  160. // (For multi-subsession (i.e., audio+video) sessions, the outgoing streams' presentation times retain the same relative
  161. // separation as those of the incoming streams.)
  162. class PresentationTimeSubsessionNormalizer: public FramedFilter {
  163. public:
  164. void setRTPSink(RTPSink* rtpSink) { fRTPSink = rtpSink; }
  165. private:
  166. friend class PresentationTimeSessionNormalizer;
  167. PresentationTimeSubsessionNormalizer(PresentationTimeSessionNormalizer& parent, FramedSource* inputSource, RTPSource* rtpSource,
  168. char const* codecName, PresentationTimeSubsessionNormalizer* next);
  169. // called only from within "PresentationTimeSessionNormalizer"
  170. virtual ~PresentationTimeSubsessionNormalizer();
  171. static void afterGettingFrame(void* clientData, unsigned frameSize,
  172. unsigned numTruncatedBytes,
  173. struct timeval presentationTime,
  174. unsigned durationInMicroseconds);
  175. void afterGettingFrame(unsigned frameSize,
  176. unsigned numTruncatedBytes,
  177. struct timeval presentationTime,
  178. unsigned durationInMicroseconds);
  179. private: // redefined virtual functions:
  180. virtual void doGetNextFrame();
  181. private:
  182. PresentationTimeSessionNormalizer& fParent;
  183. RTPSource* fRTPSource;
  184. RTPSink* fRTPSink;
  185. char const* fCodecName;
  186. PresentationTimeSubsessionNormalizer* fNext;
  187. };
  188. class PresentationTimeSessionNormalizer: public Medium {
  189. public:
  190. PresentationTimeSessionNormalizer(UsageEnvironment& env);
  191. virtual ~PresentationTimeSessionNormalizer();
  192. PresentationTimeSubsessionNormalizer*
  193. createNewPresentationTimeSubsessionNormalizer(FramedSource* inputSource, RTPSource* rtpSource, char const* codecName);
  194. private: // called only from within "~PresentationTimeSubsessionNormalizer":
  195. friend class PresentationTimeSubsessionNormalizer;
  196. void normalizePresentationTime(PresentationTimeSubsessionNormalizer* ssNormalizer,
  197. struct timeval& toPT, struct timeval const& fromPT);
  198. void removePresentationTimeSubsessionNormalizer(PresentationTimeSubsessionNormalizer* ssNormalizer);
  199. private:
  200. PresentationTimeSubsessionNormalizer* fSubsessionNormalizers;
  201. PresentationTimeSubsessionNormalizer* fMasterSSNormalizer; // used for subsessions that have been RTCP-synced
  202. struct timeval fPTAdjustment; // Added to (RTCP-synced) subsession presentation times to 'normalize' them with wall-clock time.
  203. };
  204. #endif