public RTPSendConnection(IPEndPoint ipe) { this.m_Participant = new RtpParticipant(Guid.NewGuid().ToString(), "Classroom Playback"); this.m_Session = new RtpSession(ipe, this.m_Participant, true, false); this.m_Sender = this.m_Session.CreateRtpSenderFec("Classroom Presenter", PayloadType.dynamicPresentation, null, 0, 100); this.m_Queue = new SendingQueue(this); }
protected override void Dispose(bool disposing) { base.Dispose(disposing); if (disposing) { m_Disposing = true; m_SendQueueWait.Set(); this.m_BeaconService.Dispose(); if (m_RtpSender != null) { m_RtpSender.Dispose(); m_RtpSender = null; } if (m_RtpSession != null) { try { m_RtpSession.Dispose(); } catch { } m_RtpSession = null; } m_RtpParticipant = null; if (m_SendThread != null) { if (!m_SendThread.Join(5000)) { m_SendThread.Abort(); } } } }
static void Main(string[] args) { RtpParticipant part = new RtpParticipant("*****@*****.**", "SENDER"); RtpSession session = new RtpSession(ip, part, true, true); session.PacketTransform = new EncryptionTransform("You are a big freak!"); //session.PacketTransform = new XorTransform(); RtpSender sender = session.CreateRtpSender("My sender", PayloadType.Test, null); Stream fs = File.OpenRead("data.txt"); int length = (int)fs.Length; Console.Out.WriteLine("Opening file of length: " + length); byte[] buffer = new byte[length]; int bytesRead = 0; while (bytesRead < length) { bytesRead += fs.Read(buffer, bytesRead, Math.Min(16384, (length - bytesRead))); } for (int i = 0; i < 5; i++) { Console.Out.WriteLine("Sending buffer to address: " + ip); sender.Send(buffer); Thread.Sleep(1000); } }
/// <summary> /// Starts recording a conference. Sets up the conference data and then records all streams received until told to stop. /// </summary> public void RecordConference(string conferenceDescription, string venueIdentifier, IPEndPoint venue) { if (conferenceDescription.Length >= Constants.MaxDBStringSize || venueIdentifier.Length >= Constants.MaxDBStringSize) { throw new ArgumentException("String longer than accepted by database."); } recording = true; venueIPE = venue; streams = new Hashtable(Constants.InitialStreams); participants = new Hashtable(); conferenceID = DBHelper.CreateConference(conferenceDescription, venueIdentifier, DateTime.Now); // Store info about this conference to the instance, for debugging reference (mostly) this.conferenceDescription = conferenceDescription; this.venueIdentifier = venueIdentifier; this.venue = venue; // Create our performance counter perfCounter = new ConferenceRecorderPC(venueIdentifier + " : " + conferenceDescription); // Set up RTCP properties RtpEvents.RtpParticipantAdded += new MSR.LST.Net.Rtp.RtpEvents.RtpParticipantAddedEventHandler(this.OnNewRtpParticipant); RtpEvents.RtpStreamAdded += new MSR.LST.Net.Rtp.RtpEvents.RtpStreamAddedEventHandler(this.OnNewRtpStream); RtpEvents.RtpStreamRemoved += new MSR.LST.Net.Rtp.RtpEvents.RtpStreamRemovedEventHandler(this.OnRtpStreamRemoved); // Start listening RtpParticipant rtpMe = new RtpParticipant(Constants.PersistenceCName, Constants.PersistenceName + " (RECORDING)"); rtpSession = new RtpSession(venue, rtpMe, true, true); }
public RTPReceiveConnection(IPEndPoint ip, NetworkArchiver na) { RtpEvents.RtpStreamAdded += new MSR.LST.Net.Rtp.RtpEvents.RtpStreamAddedEventHandler(this.handleRtpStreamAdded); RtpEvents.RtpStreamRemoved += new MSR.LST.Net.Rtp.RtpEvents.RtpStreamRemovedEventHandler(this.handleRtpStreamRemoved); this.m_Participant = new RtpParticipant("Recorder", "Recorder"); this.m_Session = new RtpSession(ip, this.m_Participant, true, true); this.m_archiver = na; }
public SimpleTest() { // Create participant RtpParticipant rtpParticipant = null; //rtpParticipant.SetTool(true); // Create session with Participant and Rtp data rtpSession = new RtpSession(new IPEndPoint(IPAddress.Parse(addr), rtpPort), rtpParticipant, false, true); }
/// <summary> /// Creates a <see cref="ParticipantModel"/> and <see cref="RTPMessageReceiver"/> /// whenever a new stream is connected to the venue. The <see cref="ParticipantModel"/> /// is added to the current <see cref="ClassroomModel"/>. /// </summary> private void HandleStreamAdded(object sender, RtpEvents.RtpStreamEventArgs args) { using (Synchronizer.Lock(this.m_Sender.m_Classroom.SyncRoot)) { using (Synchronizer.Lock(this)) { if (this.m_Disposed) { throw new ObjectDisposedException("RTPMessageSender"); } RtpStream stream = args.RtpStream; // Ignore streams that are not part of our session. if (this.m_Sender.m_RtpSession.ContainsStream(stream)) { // Ignore streams that are not DynamicPresentations. if (stream.PayloadType == PayloadType.dynamicPresentation) { // Ignore our own stream, but create a listener for all others. if (stream.SSRC != this.m_Sender.m_RtpSender.SSRC) { // If we've not seen this client before, create a new ParticipantModel, // identified by the participant's CName, which, if the participant // is running Classroom Presenter, is a Guid string. string cname = stream.Properties.CName; // It's possible for a participant to generate more than one Rtp stream, // so we need to keep a different table for m_Participants than m_Receivers. ParticipantModel participant = ((ParticipantModel)this.m_Participants[cname]); if (participant == null) { // Also get the remote client's HumanName from the participant data. RtpParticipant client = this.m_Sender.m_RtpSession.Participants[cname]; participant = new ParticipantModel(new Guid(cname), client.Name); // Add the participant to our table. this.m_Participants.Add(cname, participant); } // Add the participant to the classroom if it is not already a member. if (!this.m_Sender.m_Classroom.Participants.Contains(participant)) { this.m_Sender.m_Classroom.Participants.Add(participant); } // Create a receiver for this specific stream (there may be more than one stream per participant) // and add it to the table of receivers so it can be disposed when the stream is removed. RTPMessageReceiver receiver = new RTPMessageReceiver(this.m_Sender, stream, this.m_Sender.m_Model, this.m_Sender.m_Classroom, participant); this.m_Receivers.Add(stream, receiver); } } } } } }
public UnicastToMulticastBridge(PresenterModel model) { GetConfig(); //Prepare for RTP sending m_RtpParticipant = new RtpParticipant(m_Cname, m_Name); try { m_RtpSession = new RtpSession(m_MulticastEndpoint, m_RtpParticipant, true, false); } catch (Exception e) { Trace.WriteLine(e.ToString()); m_RtpSession = null; m_RtpParticipant = null; return; } try { /// Notes about FEC: There are two types supported by the MSR RTP stack: Frame-based and Packet-based. /// Setting cDataPx to zero forces frame-based. In this case cFecPx is a percentage. It must be greater than zero, but can be /// very large, eg. 1000. Frame-based FEC appears to be better for large frames (which the stack splits into multiple packets) /// possibly because the FEC packets for the frame are not interlaced in time sequence with the frame packets. /// If cDataPx is not zero, packet-based FEC is used. In this mode cDataPx and cFecPx are a ratio of data packets to fec packets. /// For single packet frames, 1:1 and 0:100 are identical. Single packet frames are frames smaller than /// the MTU which is normally 1500 bytes. Presenter's Chunk encoder creates frames up to 16kbytes. Many frames are smaller /// than this, but only a few are below the MTU. For this reason we will always use Frame-based FEC. Usful values are expected to /// be from around 10 up to around 100. More than 100 might be good in some cases, but might impact performance. /// More than 500 would probably never be advised. m_RtpSender = m_RtpSession.CreateRtpSenderFec("Classroom Presenter Unicast to Multicast Bridge", PayloadType.dynamicPresentation, null, 0, m_Fec); m_RtpSender.DelayBetweenPackets = m_InterpacketDelay; } catch (Exception e) { Trace.WriteLine(e.ToString()); try { m_RtpSession.Dispose(); } catch { } m_RtpParticipant = null; m_RtpSession = null; m_RtpSender = null; return; } //Prepare the beacon this.m_ChunkSequence = 0; this.m_Encoder = new Chunk.ChunkEncoder(); this.m_BeaconService = new Beacons.BridgeBeaconService(this, model); //Prepare the queue and sending thread m_Disposing = false; m_SendQueueWait = new EventWaitHandle(false, EventResetMode.AutoReset); m_SendQueue = new PriorityQueue <BridgeMessage>(); m_SendThread = new Thread(new ThreadStart(SendThread)); m_SendThread.Start(); }
internal void Receive(object data, RtpParticipant rtpParticipant) { //Drop messages received from the local node if (this.m_Capability.RtpSender.RtcpProperties.CName.Equals(rtpParticipant.CName)) { return; } //If this is the first message from a given node, attempt to create the receiver for it. if (!this.m_Receivers.ContainsKey(rtpParticipant.CName)) { if (data is CapabilityMessageWrapper) { Guid sender_id = ((CapabilityMessageWrapper)data).SenderId; bool sender_is_instructor = ((CapabilityMessageWrapper)data).SenderIsInstructor; ParticipantModel participant = new ParticipantModel(sender_id, rtpParticipant.Name); m_Participants.Add(rtpParticipant.CName, participant); //Add to classroom if the local node is instructor if (m_Capability.IsSender) { using (Synchronizer.Lock(m_Classroom.SyncRoot)) { this.m_Classroom.Participants.Add(participant); } } this.m_SsrcToSenderId.Add(rtpParticipant.SSRC, sender_id); this.m_Receivers.Add(rtpParticipant.CName, new CXPCapabilityMessageReceiver(this, rtpParticipant.SSRC, m_Model, m_Classroom, participant)); //Set the Network Association only if local node is not an instructor, and the remote node is Instructor. if ((!m_Capability.IsSender) && (sender_is_instructor)) { m_AssociationCname = rtpParticipant.CName; using (Synchronizer.Lock(this.m_Model.Network.SyncRoot)) { this.m_Model.Network.Association = participant; } } //Debug.WriteLine("Created new receiver on message receipt: ssrc=" + rtpParticipant.SSRC.ToString() + ";cname=" + rtpParticipant.CName); } else { //Trace.WriteLine("Dropping message of type " + data.GetType().ToString() + " from " + rtpParticipant.CName + " because we don't yet have the sender's Guid."); return; } } this.m_Receivers[rtpParticipant.CName].Receive(data); }
static void Main(string[] args) { RtpEvents.RtpStreamAdded += new RtpEvents.RtpStreamAddedEventHandler(OnNewRtpStream); RtpParticipant part = new RtpParticipant("*****@*****.**", "Receiver"); session = new RtpSession(ip, part, true, true); //session.PacketTransform = new XorTransform(); session.PacketTransform = new EncryptionTransform("You are a big freak!"); // make sure this thing doesn't terminate while (true) { Thread.Sleep(10000); } }
/// <summary> /// Create a listener if there isn't already one for this endpoint. /// If we fail, write eventlog entry and return null. /// </summary> /// <param name="other">The other (possible) listener</param> /// <param name="venue">New IP endpoint to use</param> private RtpSession CreateListener(RtpSession other, UWVenue venue) { if (other != null) { if (CompareIPEndPoints(other.RtpEndPoint, venue.IpEndpoint)) { return(other); } } RtpParticipant p = new RtpParticipant(myCname, myFriendlyName); RtpSession s; IPEndPoint refEP; if (this.reflectorEnabled) { try { refEP = new IPEndPoint(System.Net.Dns.GetHostEntry(this.reflectorAddress).AddressList[0], this.reflectorPort); s = new RtpSession(venue.IpEndpoint, p, true, true, refEP); s.VenueName = venue.Name; } catch (Exception e) { eventLog.WriteEntry("Failed to create RtpSession with Reflector enabled. " + e.ToString(), EventLogEntryType.Error, 1002); s = null; } } else { try { s = new RtpSession(venue.IpEndpoint, p, true, true); s.VenueName = venue.Name; } catch (Exception e) { eventLog.WriteEntry("Failed to create RtpSession. " + e.ToString(), EventLogEntryType.Error, 1002); s = null; } } return(s); }
private void HandleStreamRemoved(object sender, MSR.LST.Net.Rtp.RtpEvents.RtpStreamEventArgs args) { using (Synchronizer.Lock(this.m_Sender.m_Classroom.SyncRoot)) { using (Synchronizer.Lock(this)) { // Do not check (or care) whether the RTPMessageSender has been disposed, // because we will get lots of RtpStreamRemoved events when the RtpSession is closed. RtpStream stream = args.RtpStream; RTPMessageReceiver receiver = ((RTPMessageReceiver)this.m_Receivers[stream]); if (receiver != null) { receiver.Dispose(); this.m_Receivers.Remove(stream); } // Discard all pending Nacks so the NackManager doesn't keep nacking them forever. this.m_Sender.NackManager.Discard(stream.SSRC, Range.UNIVERSE); // If this was the last stream for the participant, unregister the ParticipantModel // and remove it from the classroom. string cname = stream.Properties.CName; RtpParticipant client = this.m_Sender.m_RtpSession.Participants[cname]; if (client == null || client.SSRCs.Count <= 0) { ParticipantModel participant = ((ParticipantModel)this.m_Participants[cname]); if (participant != null) { // Remove the participant from the classroom. if (this.m_Sender.m_Classroom.Participants.Contains(participant)) { this.m_Sender.m_Classroom.Participants.Remove(participant); } } // Remove the participant from the table. this.m_Participants.Remove(cname); } } } }
private void OnNewRtpParticipant(object sender, RtpEvents.RtpParticipantEventArgs ea) { if (this.rtpSession != sender) { return; } RtpParticipant participant = ea.RtpParticipant; Trace.WriteLine("New participant: " + participant.CName); // we want to ignore ourselves if (participant.CName != Constants.PersistenceCName) { // Make sure this isn't someone who briefly lost connectivity. if (!participants.ContainsKey(participant.CName)) { string newPartName = participant.Name; if (newPartName == null || newPartName == String.Empty) { newPartName = participant.CName; } int participantID = DBHelper.CreateParticipant( conferenceID, participant.CName, newPartName); participants.Add(participant.CName, new ParticipantWrapper(participant, participantID)); } foreach (uint ssrc in participant.SSRCs) { OnNewRtpStream(sender, new RtpEvents.RtpStreamEventArgs(rtpSession.Streams[ssrc])); } } }
private void OnNewRtpParticipant(object sender, RtpEvents.RtpParticipantEventArgs ea) { try { RtpParticipant participant = ea.RtpParticipant; eventLog.WriteEntry("OnNewRtpParticipant: " + participant.CName, EventLogEntryType.Information, ArchiveServiceEventLog.ID.Information); if (this.rtpSession != sender) { eventLog.WriteEntry("OnNewRtpParticipant: this.rtpSession and sender don't match.", EventLogEntryType.Information, ArchiveServiceEventLog.ID.Information); if (this.rtpSession == null) { //Note this can happen because participants are added during the rtpSession constructor!! eventLog.WriteEntry("OnNewRtpParticipant: this.rtpSession is null.", EventLogEntryType.Information, ArchiveServiceEventLog.ID.Information); } if (sender == null) { eventLog.WriteEntry("OnNewRtpParticipant: sender is null.", EventLogEntryType.Information, ArchiveServiceEventLog.ID.Information); } //return; } //eventLog.WriteEntry(string.Format(CultureInfo.CurrentCulture, "New participant: {0}", participant.CName)); // we want to ignore ourselves if (participant.CName != Constants.PersistenceCName) { // Make sure this isn't someone who briefly lost connectivity. if (!participants.ContainsKey(participant.CName)) { string newPartName = participant.Name; if (newPartName == null || newPartName == String.Empty) { newPartName = participant.CName; } int participantID = DBHelper.CreateParticipant( conferenceID, participant.CName, newPartName); participants.Add(participant.CName, new ParticipantWrapper(participant, participantID)); eventLog.WriteEntry("OnNewRtpParticipant completed participant Add.", EventLogEntryType.Information, ArchiveServiceEventLog.ID.Information); } else { eventLog.WriteEntry("OnNewRtpParticipant already in participants hashtable ", EventLogEntryType.Information, ArchiveServiceEventLog.ID.Information); } foreach (uint ssrc in participant.SSRCs) { if (this.rtpSession == null) { eventLog.WriteEntry("OnNewRtpParticipant: Failed to add streams because this.rtpSession is null.", EventLogEntryType.Warning, ArchiveServiceEventLog.ID.Warning); } else { OnNewRtpStream(this.rtpSession, new RtpEvents.RtpStreamEventArgs(rtpSession.Streams[ssrc])); } } } else { eventLog.WriteEntry("OnNewRtpParticipant ignoring ourself. ", EventLogEntryType.Information, ArchiveServiceEventLog.ID.Information); } } catch (Exception e) { eventLog.WriteEntry("OnNewRtpParticipant exception: " + e.ToString(), EventLogEntryType.Warning, ArchiveServiceEventLog.ID.Warning); } }
public void Play(IPEndPoint venue, int[] streams, bool receiveData) { if (this.playing) { throw new InvalidOperationException(Strings.PlayerAlreadyPlayingError); } if (streams == null) { throw new ArgumentNullException(Strings.StreamsCannotBeNull); } venueIPE = venue; // Create an RtpSession RtpParticipant me = new RtpParticipant(Constants.PersistenceCName, string.Format(CultureInfo.CurrentCulture, Strings.Playing, Constants.PersistenceName)); rtpSession = new RtpSession(venue, me, true, receiveData); // andrew: connect to diagnostic server rtpSession.VenueName = "Archived: " + venue.ToString(); // Hook the static stream-ended event StreamPlayer.EndOfStreamReached += new EventHandler(EndOfStreamReached); // Create a new perf counter for this ConferencePlayer instance this.perfCounter = new ConferencePlayerPC(venue.ToString()); // Keep track of the streamPlayers ArrayList avStreams = new ArrayList(); ArrayList otherStreams = new ArrayList(); // Find the first stored ticks of all the streams while creating them... this.firstStoredTick = long.MaxValue; // Create all of our StreamPlayers (one per stream...) for (int i = 0; i < streams.Length; i++) { StreamPlayer newStream = null; try { newStream = new StreamPlayer(rtpSession, streams[i], perfCounter); } catch (Exception ex) { eventLog.WriteEntry(String.Format(CultureInfo.CurrentCulture, Strings.StreamWithBadDataReached, streams[i], ex.ToString()), EventLogEntryType.Warning, ArchiveServiceEventLog.ID.BadStreamInDB); } if (newStream != null) { perfCounter.AddInstanceForCollection(newStream); if (newStream.FirstStreamsTicks < this.firstStoredTick) { this.firstStoredTick = newStream.FirstStreamsTicks; } // Add the new StreamPlayer to the right collection // Pri3: Consider other methods here. Maybe a smarter detection of large frame sizes, // or initializing the stream so it has enough packets ahead of time? if (newStream.Payload == PayloadType.dynamicAudio || newStream.Payload == PayloadType.dynamicVideo) { avStreams.Add(newStream); } else // RTDocs stream or other large-payload stream, most likely { otherStreams.Add(newStream); } } } // Start the StreamsGroupPlayers // Pri2: Change this to be compatable with use of the "playback speed" feature. long startTime = DateTime.Now.Ticks + 1500 * Constants.TicksPerMs; // we'll start in 1.5 seconds (for init time) // Create the StreamsGroupPlayer(s) avPlayer = new StreamsGroupPlayer(avStreams, this.firstStoredTick, startTime); otherPlayer = new StreamsGroupPlayer(otherStreams, this.firstStoredTick, startTime); this.playing = true; }
private void JoinRtpSession() { RtpParticipant participant = new RtpParticipant("Video" + pb1.Handle.ToInt32(), "Video"); rtpSession = new RtpSession(ep, participant, true, true); }
public ParticipantWrapper(RtpParticipant participant, int id) { this.participant = participant; participantID = id; }