ProxyServerMediaSession.hh 10 KB

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