Udp packet loss using RtcpClient

Topics: Question
Mar 19, 2015 at 10:33 PM
Edited Mar 21, 2015 at 4:24 PM
I'm on Windows 7 with .NET 4.5.2 with 2 year old AMD quad-core processor.

In my application I only need your RtspClient, no server.
In the enclosed code, I'm trying to set the udp receive buffer for the video stream to larger than the default 8192 bytes because I'm getting roughly 10% dropped video packets as revealed by logging sequence numbers in Client_RtpPacketReceived.
(I have not seen any evidence of dropped audio packets).
Wireshark revealed that the video RTP sequence numbers from the Foscam FI 9831W were incrementing correctly.
System.Net.NetworkCredential cred = new System.Net.NetworkCredential("xx", "xx");

RtspClient rtspClient = new RtspClient("rtsp://xx:xx@192.168.0.118:88/videoMain",          RtspClient.ClientProtocolType.Udp, 128 * 1024); // !! Hardwire!!!

rtspClient.Credential = cred;

rtspClient.AuthenticationScheme = System.Net.AuthenticationSchemes.Digest;

rtspClient.Client.RtcpPacketReceieved += new Media.Rtp.RtpClient.RtcpPacketHandler(Client_RtcpPacketReceived);

rtspClient.Client.RtpPacketReceieved  += new Media.Rtp.RtpClient.RtpPacketHandler(Client_RtpPacketReceived);
                    
rtspClient.Client.RtpFrameChanged     += new Media.Rtp.RtpClient.RtpFrameHandler(Client_RtpFrameChanged);
                    
rtspClient.StartPlaying();
However the setting of 128KB buffer doesn't appear to affect the dropped packet rate.
So I looked in the debugger and found a value of 8192 for the socket.ReceiveBufferSize on port 10000. So either I'm doing this incorrectly or there's a bug in the library.

If necessary I can provide Wireshark data and whatever else is needed, but first would like to get a quick look from you as to whether my code is correct.

I'm hoping to get this library working in my application as it would save me from writing a lot of tedious code.

Thanks!
Coordinator
Mar 19, 2015 at 11:00 PM
Edited Mar 19, 2015 at 11:59 PM
Thanks for using the library.

This could be related to a recent change I made to allow dual Tcp Sockets to be used, and or changing the mechanism for calculating TotalMicroseconds.

1) The ReceiveBufferSize is not touched if the RtpClient is given a configured socket. (The RtspClient gives it's socket to the RtpClient) You can try to create the socket with the options you require and then give it to the RtspClient if you need to do that.

Under most circumstances and as per your above example:

2) If the RtspClient creates the Socket then it does set the receive buffer based on the buffer size you give it in the constructor. it also calls ConfigureSocket

Then when each SETUP request is performed if TCP transport is used then that same socket is given to the RtpClient.

I am looking at the possibility of also changing that logic to allow the RtpClient to just create it's own socket instead but more testing is required to ensure that is the optimal route.

None the less after a successful setup the following call is made

Media.Common.ISocketReferenceExtensions.SetReceiveBufferSize(((Media.Common.ISocketReference)this), m_Buffer.Count * m_Buffer.Count);

Which does set the receive buffer for all sockets, this might have to change to just effect the RtpClient

Media.Common.ISocketReferenceExtensions.SetReceiveBufferSize(((Media.Common.ISocketReference)m_RtpClient), m_Buffer.Count * m_Buffer.Count);

But if the socket is shared as I indicated then this will not work, hence why I am probably going to change the RtpClient to create it's own socket all of the time.

I have just double checked and I don't see any bugs expect under TCP where I don't copy the ReceiveBufferSize or SendBufferSize from the duplicate socket.

I just made another release which may help, let me know what you find then.

Also you don't really need the packet events and frame events, this is probably why you need a large buffer, you can reduce the buffer size and just use the frame events which does the copying of the packet data for you as required when required.

You may want to post a Wireshark capture as you may also be experiencing UDP re-ordering which causes the FrameChanged event to fire early, or try TCP to preserve packet ordering.

If you need anything else let me know!
Marked as answer by juliusfriedman on 3/19/2015 at 4:00 PM
Mar 20, 2015 at 5:25 PM
Okay I tried 111192, but got the same results as 111177.

The code that you mentioned:
Media.Common.ISocketReferenceExtensions.SetReceiveBufferSize(((Media.Common.ISocketReference)m_RtpClient), m_Buffer.Count * m_Buffer.Count)
appears to only be called for the TCP sockets(set breakpoint on the function). However the value of the m_BufferCount here is correct (128K).
Incidently, it's curious that it specifies m_Buffer.Count * m_Buffer.Count instead of m_Buffer.Count.

I can't see anywhere else that the RTP (udp) sockets are getting their ReceiveBufferSize set, which is consistent with these sockets ending up with the default 8192 bytes. (Breakpoint on RtpClient.ReceiveData).

Thanks for your interest in getting this solved.
Coordinator
Mar 20, 2015 at 7:44 PM
111197 ensures only UDP sockets get the ReceiveBufferSize set.

111198 ensures ConfigureSockets works for Tcp and Udp Protocols.

Please let me know if you continue to have problems and sorry for the inconvenience.
Marked as answer by juliusfriedman on 3/20/2015 at 12:44 PM
Mar 20, 2015 at 9:43 PM
111198 fixed the problem - thanks!

Next I'll test with HiKVision and Trendnet HD cameras.
Coordinator
Mar 20, 2015 at 11:44 PM
Thanks, if you could also try with the default buffer size and let me know what happens I would appreciate it.

I haven't yet had the need to use such a large buffer size even with multiple mega pixel cameras.

Glad it works though!
Marked as answer by juliusfriedman on 3/20/2015 at 4:44 PM
Mar 21, 2015 at 1:13 AM
Here's the data using the video quality as the subjective measure :

8K Almost undeciferable
32K Visible artifacts
64K Solid
128K For good measure

Camera settings
Foscam: FI 9831W
Resolution: 960P
Bit rate: 1MB
FPS: 20
Key Frame: Every 10th frame
Variable bit rate enabled

Measured bit rate: 5.7Mbps from camera. No other significant network activty.
1490 bytes on the wire per Udp packet. (1448 bytes of RTP payload)

There may be something wrong with my system or network. I got similar results with a scratch RTP client that I wrote a few weeks ago.
I doubt if it has anything to do with your library.
Coordinator
Mar 21, 2015 at 1:37 AM
Thanks for the response.

Can you try one more time with 0 as the buffer size and let me know the results.

Also is this ip 4 or 6 and are you using a firewall?

Thanks.
Mar 21, 2015 at 3:22 AM
With 0 for buffer size the video looks a lot like it did with 8K, maybe a little better.
Using ip4. No firewall - the camera is in my office along with my computer, with 3 ethernet switches between. (No wireless connections)
Coordinator
Mar 21, 2015 at 3:28 AM
Interesting.

Are you using Windows?

Can you do a tracert and ping / pathping and post the results?

I just wanna make sense of the symptoms.

Can you also verify your mtu and the mtu of all switches?

Can you also try with Tcp and compare the results?

Thank you for your feedback.
Marked as answer by juliusfriedman on 3/20/2015 at 8:28 PM
Mar 21, 2015 at 5:13 AM
Unfortunately my application doesn't support TCP for the RTP streams.
Is there a way to log TCP performance metrics from your library? (RTCP Receiver report?)

The ethernet switches are level 2, so they don't speak of IP things.

Here are the other things you requested.
Hope this helps.

Windows 7 64-bit .NET 4.5.2 Realtek PCIe GBE Family Controller

C:\Program Files (x86)\Microsoft Visual Studio 12.0>netsh interface ipv4 show subinterfaces

MTU MediaSenseState Bytes In Bytes Out Interface

4294967295 1 161 9935038 Loopback Pseudo-Interface 1
1500 1 8444663144 2306554684 Local Area Connection


C:\Program Files (x86)\Microsoft Visual Studio 12.0>ping 192.168.0.118

Pinging 192.168.0.118 with 32 bytes of data:
Reply from 192.168.0.118: bytes=32 time=2ms TTL=64
Reply from 192.168.0.118: bytes=32 time=1ms TTL=64
Reply from 192.168.0.118: bytes=32 time<1ms TTL=64
Reply from 192.168.0.118: bytes=32 time<1ms TTL=64

Ping statistics for 192.168.0.118:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 2ms, Average = 0ms
C:\Program Files (x86)\Microsoft Visual Studio 12.0>ping 192.168.0.118

Pinging 192.168.0.118 with 32 bytes of data:
Reply from 192.168.0.118: bytes=32 time=3ms TTL=64
Reply from 192.168.0.118: bytes=32 time=2ms TTL=64
Reply from 192.168.0.118: bytes=32 time<1ms TTL=64
Reply from 192.168.0.118: bytes=32 time<1ms TTL=64

Ping statistics for 192.168.0.118:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 3ms, Average = 1ms
C:\Program Files (x86)\Microsoft Visual Studio 12.0>pathping 192.168.0.118

Tracing route to 192.168.0.118 over a maximum of 30 hops

0 Osprey [192.168.0.101]
1 192.168.0.118

Computing statistics for 25 seconds...
        Source to Here   This Node/Link
Hop RTT Lost/Sent = Pct Lost/Sent = Pct Address
0 Osprey [192.168.0.101]
                            0/ 100 =  0%   |
1 0ms 0/ 100 = 0% 0/ 100 = 0% 192.168.0.118

Trace complete.

C:\Program Files (x86)\Microsoft Visual Studio 12.0>pathping 192.168.0.118

Tracing route to 192.168.0.118 over a maximum of 30 hops

0 Osprey [192.168.0.101]
1 192.168.0.118

Computing statistics for 25 seconds...
        Source to Here   This Node/Link
Hop RTT Lost/Sent = Pct Lost/Sent = Pct Address
0 Osprey [192.168.0.101]
                            0/ 100 =  0%   |
1 0ms 0/ 100 = 0% 0/ 100 = 0% 192.168.0.118

Trace complete.

C:\Program Files (x86)\Microsoft Visual Studio 12.0>tracert 192.168.0.118

Tracing route to 192.168.0.118 over a maximum of 30 hops

1 <1 ms <1 ms <1 ms 192.168.0.118

Trace complete.

C:\Program Files (x86)\Microsoft Visual Studio 12.0>
Coordinator
Mar 21, 2015 at 3:13 PM
General Tcp metrics can be obtained by using the TotalBytesSent or TotalBytesReceived, if your looking for loss information then yes the Rtcp reports would be the way to determine that.

As far as your issue goes, now that I know level two switching is used it kind of makes more sense because Layer 2 switches won't handle IP Fragmentation, they simply deliver the packets to layer 3.

In this particular case am willing to bet that the actual Interface Speed of one of the switches is different that that of one of your connections, workstation or the camera.

E.g. the Switch is Gigabit and your connection is 100 MBPS or the other way around.

If so than that would be why this occurs.

You may be able to force the switch to use the same speed for all interfaces or at the very least change your NIC settings in the Device Manager to only use a speed that which is appropriate for the switch on the other end of the connection (don't select auto negotiate, specify full or half duplex appropriately).

Let me know if that helps as I see no other reason for this to occur, if you want you can include a Wireshark capture and I will take another look at that just to be sure.

If you need anything else please just let me know and thanks for getting back to me!
Marked as answer by juliusfriedman on 3/21/2015 at 8:13 AM
Mar 21, 2015 at 4:29 PM
Thanks for your time and insights. I'll look into this more eventually.
Coordinator
Mar 21, 2015 at 7:05 PM
Likewise, and if you need anything else let me know.
Marked as answer by juliusfriedman on 3/21/2015 at 12:05 PM