From bacd92274dccbea39dd9224c393f3ef0c5ded36a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 6 Oct 2022 15:02:22 +0300 Subject: [PATCH] rtspsrc: Retry SETUP with non-compliant URL resolution on "Bad Request" and "Not found" Various RTSP servers/cameras assume base and control URL to be simply appended instead of being resolved according to the relative URL resolution algorithm as mandated by the RTSP specification. To work around this, try using such a non-compliant control URL if the server didn't like the URL used in the first SETUP request. Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1447 Fixes https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/issues/922 Part-of: --- .../gst-plugins-good/gst/rtsp/gstrtspsrc.c | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/subprojects/gst-plugins-good/gst/rtsp/gstrtspsrc.c b/subprojects/gst-plugins-good/gst/rtsp/gstrtspsrc.c index a6eec4382c..fe34dd2227 100644 --- a/subprojects/gst-plugins-good/gst/rtsp/gstrtspsrc.c +++ b/subprojects/gst-plugins-good/gst/rtsp/gstrtspsrc.c @@ -7402,6 +7402,7 @@ gst_rtspsrc_setup_streams_start (GstRTSPSrc * src, gboolean async) GstRTSPConnInfo *conninfo; gchar *transports; gint retry = 0; + gboolean tried_non_compliant_url = FALSE; guint mask = 0; gboolean selected; GstCaps *caps; @@ -7594,6 +7595,47 @@ gst_rtspsrc_setup_streams_start (GstRTSPSrc * src, gboolean async) continue; else goto retry; + case GST_RTSP_STS_BAD_REQUEST: + case GST_RTSP_STS_NOT_FOUND: + /* There are various non-compliant servers that don't require control + * URLs that are not resolved correctly but instead are just appended. + * See e.g. + * https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/issues/922 + * https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1447 + */ + if (!tried_non_compliant_url && stream->control_url + && !g_str_has_prefix (stream->control_url, "rtsp://")) { + const gchar *base; + + gst_rtsp_message_unset (&request); + gst_rtsp_message_unset (&response); + gst_rtspsrc_stream_free_udp (stream); + + g_free (stream->conninfo.location); + base = get_aggregate_control (src); + + /* Make sure to not accumulate too many `/` */ + if ((g_str_has_suffix (base, "/") + && !g_str_has_suffix (stream->control_url, "/")) + || (!g_str_has_suffix (base, "/") + && g_str_has_suffix (stream->control_url, "/")) + ) + stream->conninfo.location = + g_strconcat (base, stream->control_url, NULL); + else if (g_str_has_suffix (base, "/") + && g_str_has_suffix (stream->control_url, "/")) + stream->conninfo.location = + g_strconcat (base, stream->control_url + 1, NULL); + else + stream->conninfo.location = + g_strconcat (base, "/", stream->control_url, NULL); + + tried_non_compliant_url = TRUE; + + goto retry; + } + + /* fall through */ default: /* cleanup of leftover transport and move to the next stream */ gst_rtspsrc_stream_free_udp (stream);