예제 #1
0
        internal void OnFrameReceivedEvent(BufferChunk frame)
        {
            framesReceived++;

            // Don't trigger the event if it isn't hooked
            // Although RtpEvents.FireEvent does this same check, we add it here for efficiency
            // As audio / video streams create alot of data, but don't use the FrameReceived event
            if (FrameReceived != null)
            {
                if (framesReceived == 1)
                {
                    OnFirstFrameReceivedEvent();
                }

                object[] args = { this, new FrameReceivedEventArgs(this, frame) };
                EventThrower.QueueUserWorkItem(new RtpEvents.RaiseEvent(RaiseFrameReceivedEvent), args);
            }
            else // Audio and Video
            {
                if (frameReceived)
                {
                    if (framesReceived == 1)
                    {
                        firstFrame = frame.Peek(frame.Index, frame.Length);
                        OnFirstFrameReceivedEvent();
                    }

                    lastFrame     = frame;
                    frameReceived = false;
                    nextFrameEvent.Set();
                }
            }
        }
예제 #2
0
        internal void RaiseInvalidPacketInFrameEvent(string reason)
        {
            ++invalidPacketInFrameEvents;

            object[] args = { this, new RtpEvents.InvalidPacketInFrameEventArgs(this, reason) };
            EventThrower.QueueUserWorkItem(new RtpEvents.RaiseEvent(RtpEvents.RaiseInvalidPacketInFrameEvent), args);
        }
예제 #3
0
        // All of these events are called by Frame, and hence are internal
        // TODO - try to decouple JVE

        #region PacketOutOfSequence

        internal void RaisePacketOutOfSequenceEvent(int packetsLost, string message)
        {
            this.packetsLost += packetsLost;

            object[] args = { this, new RtpEvents.PacketOutOfSequenceEventArgs(this, packetsLost, message) };
            EventThrower.QueueUserWorkItem(new RtpEvents.RaiseEvent(RtpEvents.RaisePacketOutOfSequenceEvent), args);
        }
예제 #4
0
 /// <summary>
 /// Raises the ParticipantStatusChanged event if the data changed
 /// </summary>
 /// <param name="data"></param>
 internal new void UpdateData(SdesData data)
 {
     if (base.UpdateData(data))
     {
         object[] args = { this, new RtpEvents.RtpParticipantEventArgs(this) };
         EventThrower.QueueUserWorkItem(new RtpEvents.RaiseEvent(RtpEvents.RaiseRtpParticipantDataChangedEvent), args);
     }
 }
예제 #5
0
        internal void RaiseFrameOutOfSequenceEvent(int framesLost, string message)
        {
            Trace.Assert(framesLost > 0, "framesLost should be greater than 0");

            this.framesLost += framesLost;

            object[] args = { this, new RtpEvents.FrameOutOfSequenceEventArgs(this, framesLost, message) };
            EventThrower.QueueUserWorkItem(new RtpEvents.RaiseEvent(RtpEvents.RaiseFrameOutOfSequenceEvent), args);
        }
예제 #6
0
        private void ReceivePackets()
        {
            BufferChunk bc = null;

            while (true)
            {
                try
                {
                    bc = GetBuffer();
                    EndPoint ep;

                    rtpNetworkListener.ReceiveFrom(bc, out ep);
                    receivedPackets.Enqueue(new object[] { bc, ep });
                    newPacket.Set();

                    unchecked { pcPackets++; }
                }
                catch (PoolExhaustedException e)
                {
                    LogEvent(e.ToString(), EventLogEntryType.Error, (int)RtpEL.ID.UnboundedGrowth);
                    return; // Exit the thread gracefully
                }
                catch (System.Net.Sockets.SocketException e)
                {
                    ReturnBuffer(bc);

                    // Something other than - No data received before timeout
                    if (e.ErrorCode != 10060)
                    {
                        Object[] args = new Object[] { this, new RtpEvents.HiddenSocketExceptionEventArgs((RtpSession)rtpSession, e) };
                        EventThrower.QueueUserWorkItem(new RtpEvents.RaiseEvent(RtpEvents.RaiseHiddenSocketExceptionEvent), args);

                        LogEvent(e.ToString(), EventLogEntryType.Error, (int)RtpEL.ID.Error);
                    }
                }
                catch (Exception e)
                {
                    if (!(e is ThreadAbortException))
                    {
                        ReturnBuffer(bc);
                        LogEvent(e.ToString(), EventLogEntryType.Error, (int)RtpEL.ID.Error);
                    }
                }
            }
        }
예제 #7
0
 internal void OnDataStoppedEvent()
 {
     object[] args = { this, null };
     EventThrower.QueueUserWorkItem(new RtpEvents.RaiseEvent(RaiseDataStoppedEvent), args);
 }
예제 #8
0
 internal void OnFirstFrameReceivedEvent()
 {
     object[] args = { this, null };
     EventThrower.QueueUserWorkItem(new RtpEvents.RaiseEvent(RaiseFirstFrameReceivedEvent), args);
 }
예제 #9
0
        /// <summary>
        /// Collects the Rtcp data from the session, assembles it into CompoundPackets (via the
        /// CompoundPacketBuilder) and sends the packets
        ///
        /// The current design has a "forced" Send occurring on the thread that makes the call, and
        /// a normal Send occurring on the dedicated RtcpSender thread.
        ///
        /// To make sure that multiple threads aren't making the call at the same time, which can
        /// lead to data access exceptions (e.g. Queue empty), we lock here.
        /// </summary>
        /// <param name="forced">Is Send being called due to timing rules, or forced?</param>
        private void Send(bool forced)
        {
            lock (this)
            {
                try
                {
                    // We're Sending despite timing rules
                    if (forced)
                    {
                        lastSendForced = true;
                    }
                    else // We're Sending due to timing rules
                    {
                        // The timing rules may now be in conflict with a previous forced Send
                        // Ask the timing rules to reconsider again before Sending
                        if (lastSendForced)
                        {
                            lastSendForced = false;
                            return;
                        }
                    }

                    CompoundPacketBuilder cpb = rtpSession.RtcpReportIntervalReached();
                    cpb.BuildCompoundPackets();

                    Debug.Assert(cpb.PacketCount > 0);

                    // Send all compound packets (in case there is more than 1)
                    short packetCount = cpb.PacketCount;
                    int   bytes       = 0;

                    foreach (CompoundPacket cp in cpb)
                    {
                        BufferChunk data = cp.Data;
                        bytes += data.Length;
                        rtcpNetworkSender.Send(data);

                        if (diagnosticSender != null)
                        {
                            // andrew: send a "carbon-copy" to the diagnostic server
                            // this is done over unicast to avoid entangling diagnosis with multicast
                            diagnosticSender.Send(data);
                        }
                    }

                    // How long between the last send time and now
                    TimeSpan interval = DateTime.Now - lastSendTime;

                    // Update lastSendTime
                    lastSendTime = DateTime.Now;

                    // Update performance data
                    // Packets before bytes, since packets doesn't have any dependencies
                    // but BytesPerPacket requires a correct reading on the packet count
                    UpdatePerformancePackets(packetCount);
                    UpdatePerformanceBytes(bytes);
                    UpdatePerformanceInterval(interval, forced);
                }
                catch (ThreadAbortException) {}
                catch (Exception e)
                {
                    // AAA debugging only
                    System.Console.WriteLine(e.StackTrace);

                    if (e is System.Net.Sockets.SocketException)
                    {
                        Object[] args = new Object[] { this, new RtpEvents.HiddenSocketExceptionEventArgs((RtpSession)rtpSession,
                                                                                                          (System.Net.Sockets.SocketException)e) };
                        EventThrower.QueueUserWorkItem(new RtpEvents.RaiseEvent(RtpEvents.RaiseHiddenSocketExceptionEvent), args);
                    }

                    rtpSession.LogEvent("RtcpSender", e.ToString(), EventLogEntryType.Error, (int)RtpEL.ID.Error);
                }
            }
        }
예제 #10
0
        public void ListenThread()
        {
            CompoundPacket compoundPacket = new CompoundPacket();
            EndPoint       endPoint       = null;

            while (!disposed)
            {
                try
                {
                    // Reset the packet for the next round of data
                    compoundPacket.Reset();

                    // Wait for data off the wire
                    rtcpNetworkListener.ReceiveFrom(compoundPacket.Buffer, out endPoint);

                    #region Fault Injection
                    #if FaultInjection
                    // Drop packets
                    if (rtpSession.DropPacketsPercent > 0)
                    {
                        if (rtpSession.Rnd.Next(1, 100) <= rtpSession.DropPacketsPercent)
                        {
                            continue;
                        }
                    }
                    #endif
                    #endregion Fault Injection

                    // Parse the data and rigorously validate it
                    compoundPacket.ParseBuffer();

                    // Pass it on to the rtpSession to analyze and distribute data
                    rtpSession.ProcessCompoundPacket(compoundPacket, ((IPEndPoint)endPoint).Address);
                }

                catch (System.Net.Sockets.SocketException e)
                {
                    // No data received before timeout
                    if (e.ErrorCode == 10060)
                    {
                        rtpSession.RaiseNetworkTimeoutEvent("Rtcp");
                    }
                    // We get 10054 socket exceptions in some situations during unicast connections.  Ignore them for now.
                    // Pri2: Find a better solution for the unicast socket exceptions
                    else if (e.ErrorCode == 10054 && !Utility.IsMulticast(rtcpNetworkListener.ExternalInterface))
                    {
                        continue;
                    }
                    else
                    {
                        Object[] args = new Object[] { this, new RtpEvents.HiddenSocketExceptionEventArgs((RtpSession)rtpSession, e) };
                        EventThrower.QueueUserWorkItem(new RtpEvents.RaiseEvent(RtpEvents.RaiseHiddenSocketExceptionEvent), args);

                        LogEvent(e.ToString(), EventLogEntryType.Error, (int)RtpEL.ID.Error);
                    }
                }
                catch (RtcpHeader.RtcpHeaderException e)
                {
                    // TODO - this is a pretty serious error - what should we do - exit thread, squelch? JVE
                    LogEvent(e.ToString(), EventLogEntryType.Error, (int)RtpEL.ID.RtcpHeaderException);
                }
                catch (CompoundPacket.CompoundPacketException e)
                {
                    // TODO - this is a pretty serious error - what should we do - exit thread, squelch? JVE
                    LogEvent(e.ToString(), EventLogEntryType.Error, (int)RtpEL.ID.CompoundPacketException);
                }
                catch (ThreadAbortException) {}
                catch (Exception e)
                {
                    LogEvent(e.ToString(), EventLogEntryType.Error, (int)RtpEL.ID.Error);
                }
            }
        }