Tune SO_RCVBUF logic

- Calculate desired SO_RCVBUF by packet size for the video socket
- Use the OS default SO_RCVBUF for audio and STUN sockets
This commit is contained in:
Cameron Gutman
2023-07-25 18:30:19 -05:00
parent 70a2e305bc
commit 77c5d5c282
4 changed files with 45 additions and 35 deletions
+1 -6
View File
@@ -25,11 +25,6 @@ static uint8_t opusHeaderByte;
#define MAX_PACKET_SIZE 1400 #define MAX_PACKET_SIZE 1400
// This is much larger than we should typically have buffered, but
// it needs to be. We need a cushion in case our thread gets blocked
// for longer than normal.
#define RTP_RECV_BUFFER (64 * 1024)
typedef struct _QUEUE_AUDIO_PACKET_HEADER { typedef struct _QUEUE_AUDIO_PACKET_HEADER {
LINKED_BLOCKING_QUEUE_ENTRY lentry; LINKED_BLOCKING_QUEUE_ENTRY lentry;
int size; int size;
@@ -88,7 +83,7 @@ int initializeAudioStream(void) {
// For GFE 3.22 compatibility, we must start the audio ping thread before the RTSP handshake. // For GFE 3.22 compatibility, we must start the audio ping thread before the RTSP handshake.
// It will not reply to our RTSP PLAY request until the audio ping has been received. // It will not reply to our RTSP PLAY request until the audio ping has been received.
rtpSocket = bindUdpSocket(RemoteAddr.ss_family, RTP_RECV_BUFFER); rtpSocket = bindUdpSocket(RemoteAddr.ss_family, 0);
if (rtpSocket == INVALID_SOCKET) { if (rtpSocket == INVALID_SOCKET) {
return LastSocketFail(); return LastSocketFail();
} }
+9
View File
@@ -266,6 +266,7 @@ SOCKET bindUdpSocket(int addrfamily, int bufferSize) {
} }
#endif #endif
if (bufferSize != 0) {
// We start at the requested recv buffer value and step down until we find // We start at the requested recv buffer value and step down until we find
// a value that the OS will accept. // a value that the OS will accept.
for (;;) { for (;;) {
@@ -295,7 +296,15 @@ SOCKET bindUdpSocket(int addrfamily, int bufferSize) {
else { else {
Limelog("Unable to set receive buffer size: %d\n", LastSocketError()); Limelog("Unable to set receive buffer size: %d\n", LastSocketError());
} }
{
SOCKADDR_LEN len = sizeof(bufferSize);
if (getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*)&bufferSize, &len) == 0) {
Limelog("Actual receive buffer size: %d\n", bufferSize);
}
}
#endif #endif
}
return s; return s;
} }
+1 -1
View File
@@ -73,7 +73,7 @@ int LiFindExternalAddressIP4(const char* stunServer, unsigned short stunPort, un
goto Exit; goto Exit;
} }
sock = bindUdpSocket(hints.ai_family, 2048); sock = bindUdpSocket(hints.ai_family, 0);
if (sock == INVALID_SOCKET) { if (sock == INVALID_SOCKET) {
err = LastSocketFail(); err = LastSocketFail();
Limelog("Failed to connect to STUN server: %d\n", err); Limelog("Failed to connect to STUN server: %d\n", err);
+9 -3
View File
@@ -5,8 +5,6 @@
#define FIRST_FRAME_PORT 47996 #define FIRST_FRAME_PORT 47996
#define RTP_RECV_BUFFER (512 * 1024)
static RTP_VIDEO_QUEUE rtpQueue; static RTP_VIDEO_QUEUE rtpQueue;
static SOCKET rtpSocket = INVALID_SOCKET; static SOCKET rtpSocket = INVALID_SOCKET;
@@ -25,6 +23,14 @@ static bool receivedFullFrame;
// the RTP queue will wait for missing/reordered packets. // the RTP queue will wait for missing/reordered packets.
#define RTP_QUEUE_DELAY 10 #define RTP_QUEUE_DELAY 10
// This is the desired number of video packets that can be
// stored in the socket's receive buffer. 2048 is chosen
// because it should be large enough for all reasonable
// frame sizes (probably 2 or 3 frames) without using too
// much kernel memory with larger packet sizes. It also
// can smooth over transient pauses in network traffic
// and subsequent packet/frame bursts that follow.
#define RTP_RECV_PACKETS_BUFFERED 2048
// Initialize the video stream // Initialize the video stream
void initializeVideoStream(void) { void initializeVideoStream(void) {
@@ -254,7 +260,7 @@ int startVideoStream(void* rendererContext, int drFlags) {
return err; return err;
} }
rtpSocket = bindUdpSocket(RemoteAddr.ss_family, RTP_RECV_BUFFER); rtpSocket = bindUdpSocket(RemoteAddr.ss_family, RTP_RECV_PACKETS_BUFFERED * (StreamConfig.packetSize + MAX_RTP_HEADER_SIZE));
if (rtpSocket == INVALID_SOCKET) { if (rtpSocket == INVALID_SOCKET) {
VideoCallbacks.cleanup(); VideoCallbacks.cleanup();
return LastSocketError(); return LastSocketError();