/// <summary> /// Adds the server media session. /// </summary> /// <param name="streamName">Name of the stream.</param> /// <returns>The ServerMediaSession object.</returns> private ServerMediaSession AddServerMediaSession(string streamName) { ServerMediaSession sms = null; MPEG2TransportFileServerMediaSession mpeg2TransportFileSMS = new MPEG2TransportFileServerMediaSession(streamName); if (mpeg2TransportFileSMS == null) { return(null); // Creates the MPEG2TransportFileServerMediaSubsession failed! } else { sms = mpeg2TransportFileSMS; // Also, sets the file catalog: mpeg2TransportFileSMS.FileCatalog = fileCatalog; } lock (serverMediaSessionTable) { serverMediaSessionTable.Add(streamName, sms); } return(sms); }
/// <summary> /// Handles the setup CMD. /// </summary> /// <param name="cseq">The cseq.</param> /// <param name="urlPreSuffix">The URL pre suffix.</param> /// <param name="urlSuffix">The URL suffix.</param> /// <param name="request">The request string.</param> private void HandleSetupCmd(string cseq, string urlPreSuffix, string urlSuffix, string request) { // Note: At present, I will use only one streaming mode of RTP_UDP // to transfer the data between server and client. // First, judges that the server media session exists or not. if (serverMediaSession == null) { serverMediaSession = rtspServer.LookupServerMediaSession(urlPreSuffix); if (serverMediaSession == null) { HandleNotFoundCmd(cseq); return; } } // Looks for a "Transport:" header in the request string, // to extract client parameters: int clientRtpPort; int clientRtcpPort; bool result = RtspCommon.ParseClientTransportHeader(request, out clientRtpPort, out clientRtcpPort); if (!result) { HandleUnsupportedTransportCmd(cseq); return; } // Then, gets the server parameters from the server media session: streamState = null; string destinationAddr = base.ClientSessionIP; string sourceAddr = Utils.GetLocalAddresses()[0]; int serverRtpPort = rtspServer.GenerateRtpPortNumber(); int serverRtcpPort = serverRtpPort + 1; result = serverMediaSession.GetStreamParameters(base.ClientSessionId, base.ClientSessionIP, clientRtpPort, clientRtcpPort, serverRtpPort, serverRtcpPort, ref streamState); if (!result) { HandleUnsupportedTransportCmd(cseq); return; } // Generates the response information now. StringBuilder sb = new StringBuilder(); sb.Append("RTSP/1.0 200 OK\r\n"); sb.AppendFormat("CSeq: {0}\r\n", cseq); sb.AppendFormat("Date: {0}\r\n", DateTime.Now.ToLocalTime()); sb.Append("Transport: RTP/AVP;unicast;"); sb.AppendFormat("destination={0};source={1};", destinationAddr, sourceAddr); sb.AppendFormat("client_port={0}-{1};", clientRtpPort, clientRtcpPort); sb.AppendFormat("server_port={0}-{1}\r\n", serverRtpPort, serverRtcpPort); sb.AppendFormat("Session: {0}\r\n\r\n", base.ClientSessionId); response = sb.ToString(); }
/// <summary> /// Lookups the server media session. /// </summary> /// <param name="streamName">Name of the stream.</param> /// <returns>The ServerMediaSession object.</returns> public ServerMediaSession LookupServerMediaSession(string streamName) { bool fileExists = false; bool smsExists = false; // First, checks whether the specified "streamName" exists as a local file. string filePath = fileCatalog + streamName; fileExists = File.Exists(filePath); // Next, checks whether we already have a "ServerMediaSession" for this file. ServerMediaSession sms = null; lock (serverMediaSessionTable) { if (serverMediaSessionTable.ContainsKey(streamName)) { sms = serverMediaSessionTable[streamName]; } } // The "ServerMediaSession" exists. if (sms != null) { smsExists = true; } // Handles the four possibilities for "fileExists" and "smsExists". if (!fileExists) { if (smsExists) { // "sms" was created for a file that no longer exists, so removes it. RemoveServerMediaSession(streamName); } } else { if (!smsExists) { // Creates a new "ServerMediaSession" object for streaming from the named file. // And then add it to the table of ServerMediaSession. sms = AddServerMediaSession(streamName); } } return(sms); }
/// <summary> /// Handles the describe CMD. /// </summary> /// <param name="cseq">The cseq.</param> /// <param name="rtspUrl">The rtsp url.</param> /// <param name="urlSuffix">The URL suffix.</param> /// <param name="request">The request string.</param> private void HandleDescribeCmd(string cseq, string rtspUrl, string urlSuffix, string request) { base.StreamName = urlSuffix; // Begins by looking up the "ServerMediaSession" object for the specified "urlSuffix": serverMediaSession = rtspServer.LookupServerMediaSession(urlSuffix); if (serverMediaSession == null) { HandleNotFoundCmd(cseq); return; } // Then, assembles a SDP description for this session: string sdpDescription = serverMediaSession.GenerateSdpDescription(); if (string.IsNullOrEmpty(sdpDescription)) { HandleNotFoundCmd(cseq); return; } int sdpDescriptionSize = sdpDescription.Length; // Generates the response information now. StringBuilder sb = new StringBuilder(); sb.Append("RTSP/1.0 200 OK\r\n"); sb.AppendFormat("CSeq: {0}\r\n", cseq); sb.AppendFormat("Date: {0}\r\n", DateTime.Now.ToLocalTime()); sb.AppendFormat("Content-Base: {0}\r\n", rtspUrl); sb.Append("Content-Type: application/sdp\r\n"); sb.AppendFormat("Content-Length: {0}\r\n\r\n", sdpDescriptionSize); sb.AppendFormat("{0}", sdpDescription); response = sb.ToString(); }