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

View File

@@ -25,11 +25,6 @@ static uint8_t opusHeaderByte;
#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 {
LINKED_BLOCKING_QUEUE_ENTRY lentry;
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.
// 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) {
return LastSocketFail();
}

View File

@@ -266,36 +266,45 @@ SOCKET bindUdpSocket(int addrfamily, int bufferSize) {
}
#endif
// We start at the requested recv buffer value and step down until we find
// a value that the OS will accept.
for (;;) {
err = setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*)&bufferSize, sizeof(bufferSize));
if (bufferSize != 0) {
// We start at the requested recv buffer value and step down until we find
// a value that the OS will accept.
for (;;) {
err = setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*)&bufferSize, sizeof(bufferSize));
if (err == 0) {
// Successfully set a buffer size
break;
}
else if (bufferSize <= RCV_BUFFER_SIZE_MIN) {
// Failed to set a buffer size within the allowable range
break;
}
else if (bufferSize - RCV_BUFFER_SIZE_STEP <= RCV_BUFFER_SIZE_MIN) {
// Last shot - we're trying the minimum
bufferSize = RCV_BUFFER_SIZE_MIN;
}
else {
// Lower the requested size by another step
bufferSize -= RCV_BUFFER_SIZE_STEP;
}
}
#if defined(LC_DEBUG)
if (err == 0) {
// Successfully set a buffer size
break;
}
else if (bufferSize <= RCV_BUFFER_SIZE_MIN) {
// Failed to set a buffer size within the allowable range
break;
}
else if (bufferSize - RCV_BUFFER_SIZE_STEP <= RCV_BUFFER_SIZE_MIN) {
// Last shot - we're trying the minimum
bufferSize = RCV_BUFFER_SIZE_MIN;
Limelog("Selected receive buffer size: %d\n", bufferSize);
}
else {
// Lower the requested size by another step
bufferSize -= RCV_BUFFER_SIZE_STEP;
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);
}
}
}
#if defined(LC_DEBUG)
if (err == 0) {
Limelog("Selected receive buffer size: %d\n", bufferSize);
}
else {
Limelog("Unable to set receive buffer size: %d\n", LastSocketError());
}
#endif
}
return s;
}

View File

@@ -73,7 +73,7 @@ int LiFindExternalAddressIP4(const char* stunServer, unsigned short stunPort, un
goto Exit;
}
sock = bindUdpSocket(hints.ai_family, 2048);
sock = bindUdpSocket(hints.ai_family, 0);
if (sock == INVALID_SOCKET) {
err = LastSocketFail();
Limelog("Failed to connect to STUN server: %d\n", err);

View File

@@ -5,8 +5,6 @@
#define FIRST_FRAME_PORT 47996
#define RTP_RECV_BUFFER (512 * 1024)
static RTP_VIDEO_QUEUE rtpQueue;
static SOCKET rtpSocket = INVALID_SOCKET;
@@ -25,6 +23,14 @@ static bool receivedFullFrame;
// the RTP queue will wait for missing/reordered packets.
#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
void initializeVideoStream(void) {
@@ -254,7 +260,7 @@ int startVideoStream(void* rendererContext, int drFlags) {
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) {
VideoCallbacks.cleanup();
return LastSocketError();