Parse the ports from RTSP SETUP instead of RTSP DESCRIBE

RTSP SETUP is better because it can provide multiple IP+port candidates
This commit is contained in:
Cameron Gutman 2021-07-02 00:28:48 -05:00
parent f05be47ed8
commit 46887c0447

View File

@ -525,55 +525,34 @@ static int parseOpusConfigFromParamString(char* paramStr, int channelCount, POPU
return 0; return 0;
} }
static bool parseMediaEntry(PRTSP_MESSAGE response, const char* mediaType, const char* transport, uint16_t* port) { // Parse the server port from the Transport header
char paramsPrefix[128]; // Example: unicast;server_port=48000-48001;source=192.168.35.177
char paramsSuffix[128]; static bool parseServerPortFromTransport(PRTSP_MESSAGE response, uint16_t* port) {
char* paramStart; char* transport;
char* portStart;
sprintf(paramsPrefix, "m=%s ", mediaType); transport = getOptionContent(response->options, "Transport");
sprintf(paramsSuffix, " %s", transport); if (transport == NULL) {
return false;
// Look for the next match
paramStart = response->payload;
while ((paramStart = strstr(paramStart, paramsPrefix)) != NULL) {
// Skip the prefix
paramStart += strlen(paramsPrefix);
// The first part should be the port number
char* nextToken;
long int rawPort = strtol(paramStart, &nextToken, 10);
if (rawPort <= 0 || rawPort >= 65535) {
continue;
}
// Skip this entry if the transport isn't what we expect
if (strncmp(nextToken, paramsSuffix, strlen(paramsSuffix)) != 0) {
continue;
}
// This entry is a match
*port = (uint16_t)rawPort;
return true;
} }
// No match for this media type and transport // Look for the server_port= entry in the Transport option
return false; portStart = strstr(transport, "server_port=");
} if (portStart == NULL) {
return false;
static void parsePortConfigurations(PRTSP_MESSAGE response) {
// Don't parse ports on very old GFE versions
if (!APP_VERSION_AT_LEAST(7, 0, 0)) {
return;
} }
parseMediaEntry(response, "video", "RTP/AVP", &VideoPortNumber); // Skip the prefix
parseMediaEntry(response, "audio", "RTP/AVP", &AudioPortNumber); portStart += strlen("server_port=");
if (!parseMediaEntry(response, "application", "udp", &ControlPortNumber)) { // Validate the port number
if (!parseMediaEntry(response, "application", "udp_enc", &ControlPortNumber)) { long int rawPort = strtol(portStart, NULL, 10);
parseMediaEntry(response, "application", "udp_ag", &ControlPortNumber); if (rawPort <= 0 || rawPort >= 65535) {
} return false;
} }
*port = (uint16_t)rawPort;
return true;
} }
// Parses the Opus configuration from an RTSP DESCRIBE response // Parses the Opus configuration from an RTSP DESCRIBE response
@ -824,14 +803,6 @@ int performRtspHandshake(void) {
} }
} }
// Parse audio, video, and control ports out of the RTSP DESCRIBE response.
parsePortConfigurations(&response);
// Let the audio stream know the port number is now finalized.
// NB: This is needed because audio stream init happens before RTSP,
// which is not the case for the video stream.
notifyAudioPortNegotiationComplete();
// Parse the Opus surround parameters out of the RTSP DESCRIBE response. // Parse the Opus surround parameters out of the RTSP DESCRIBE response.
ret = parseOpusConfigurations(&response); ret = parseOpusConfigurations(&response);
if (ret != 0) { if (ret != 0) {
@ -861,6 +832,14 @@ int performRtspHandshake(void) {
goto Exit; goto Exit;
} }
// Parse the audio port out of the RTSP SETUP response
parseServerPortFromTransport(&response, &AudioPortNumber);
// Let the audio stream know the port number is now finalized.
// NB: This is needed because audio stream init happens before RTSP,
// which is not the case for the video stream.
notifyAudioPortNegotiationComplete();
sessionId = getOptionContent(response.options, "Session"); sessionId = getOptionContent(response.options, "Session");
if (sessionId == NULL) { if (sessionId == NULL) {
@ -905,6 +884,9 @@ int performRtspHandshake(void) {
goto Exit; goto Exit;
} }
// Parse the video port out of the RTSP SETUP response
parseServerPortFromTransport(&response, &VideoPortNumber);
freeMessage(&response); freeMessage(&response);
} }
@ -927,6 +909,9 @@ int performRtspHandshake(void) {
goto Exit; goto Exit;
} }
// Parse the control port out of the RTSP SETUP response
parseServerPortFromTransport(&response, &ControlPortNumber);
freeMessage(&response); freeMessage(&response);
} }