After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 628214 - Add support to RTSP initiation through SDP files
Add support to RTSP initiation through SDP files
Status: RESOLVED FIXED
Product: GStreamer
Classification: Platform
Component: gst-plugins-good
git master
Other All
: Normal enhancement
: 0.10.26
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2010-08-28 20:55 UTC by Marco Ballesio
Modified: 2010-10-07 10:13 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
test file to be played through gst-launch playbin2 uri=/path/to/sdptest.sdp (666 bytes, application/vnd.stardivision.impress)
2010-08-28 20:55 UTC, Marco Ballesio
  Details
enable rtspsrc to handle the SDP protocol (3.08 KB, patch)
2010-08-28 20:57 UTC, Marco Ballesio
needs-work Details | Review
Bring the SDP protocol into exhistence (713 bytes, patch)
2010-08-28 20:58 UTC, Marco Ballesio
none Details | Review
use rtspsrc as session element is sdpdemux when needed (7.67 KB, patch)
2010-08-28 20:58 UTC, Marco Ballesio
none Details | Review
use rtspsrc as session element is sdpdemux when needed (7.15 KB, patch)
2010-08-29 07:54 UTC, Marco Ballesio
none Details | Review
enable rtspsrc to handle the SDP protocol (2.83 KB, patch)
2010-09-08 11:16 UTC, Marco Ballesio
none Details | Review
Bring the SDP protocol into existence (698 bytes, patch)
2010-09-08 11:19 UTC, Marco Ballesio
none Details | Review
use rtspsrc as session element is sdpdemux when needed (7.78 KB, patch)
2010-09-08 11:20 UTC, Marco Ballesio
none Details | Review
sdpdemux: redirect SDP with rtsp control url (1.94 KB, patch)
2010-09-10 10:13 UTC, Mark Nauwelaerts
none Details | Review
stack trace taken for multiple threads at the deadlock point (4.40 KB, text/plain)
2010-09-28 17:25 UTC, Marco Ballesio
  Details

Description Marco Ballesio 2010-08-28 20:55:44 UTC
Created attachment 168962 [details]
test file to be played through gst-launch playbin2 uri=/path/to/sdptest.sdp

Currently GStreamer is missing support for RTSP initiation from SDP files (as specified in RFC2362, Annex C). This could GStreamer incompatible with RTSP servers which assume RTSP initiation happens through this kind of (pre-shared) files.

The current SDP support is only related to already initiated sessions, but the attached set of patches grants compliance with the above mentioned specifications.

More specifically the patches:

- Add a new protocol, "sdp://"
- Modify the SDP demuxer behaviour to detect files as for RFC2362, annex C and enable it to use the rtspsrc in such a case.
- Modify rtspsrc so to handle the sdp:// protocol.

Still the key issue of state change violations in sdpdemux are remaining. As suggested from Mark, a most proper fix would be to get rid of it and use redirection signals from the sdpdemux element. The signal could then be hndled from the uridecodebin.
Comment 1 Marco Ballesio 2010-08-28 20:57:19 UTC
Created attachment 168963 [details] [review]
enable rtspsrc to handle the SDP protocol
Comment 2 Marco Ballesio 2010-08-28 20:58:00 UTC
Created attachment 168964 [details] [review]
Bring the SDP protocol into exhistence
Comment 3 Marco Ballesio 2010-08-28 20:58:58 UTC
Created attachment 168965 [details] [review]
use rtspsrc as session element is sdpdemux when needed
Comment 4 Marco Ballesio 2010-08-29 07:54:28 UTC
Created attachment 168991 [details] [review]
use rtspsrc as session element is sdpdemux when needed

Improved the number of streams handling.
Comment 5 Wim Taymans 2010-09-06 09:28:14 UTC
> Still the key issue of state change violations in sdpdemux are remaining. 

What do you mean with that?
Comment 6 Wim Taymans 2010-09-06 09:51:57 UTC
Review of attachment 168963 [details] [review]:

This patch needs some work
Comment 7 Wim Taymans 2010-09-06 10:00:29 UTC
Comment on attachment 168963 [details] [review]
enable rtspsrc to handle the SDP protocol 

> static gchar **
> gst_rtspsrc_uri_get_protocols (void)
> {
>-  static const gchar *protocols[] = { "rtsp", "rtspu", "rtspt", "rtsph", NULL };
>+  static const gchar *protocols[] =
>+      { "sdp", "rtsp", "rtspu", "rtspt", "rtsph", NULL };
> 
>   return (gchar **) protocols;
> }

Please make a new rtsp-sdp:// uri which is less likely to conflict with an existing
uri.

>+static const gchar *
>+gst_rtspsrc_init_from_sdp (GstRTSPSrc * src, const gchar * sdpstr)
>+{
>+  int i, l = strlen (sdpstr);
>+  gchar *string = g_malloc (l + 1);
>+  const gchar *control_url = NULL;
>+  strcpy (string, sdpstr);
>+
>+  for (i = 0; i < l; i++)
>+    if (string[i] == ';' && string[i + 1] > 'a' && string[i + 1] < 'z'
>+        && string[i + 2] == '=')
>+      string[i] = '\n';

Why this cleanup of the SDP? I would pass a base64 encoded version of the raw
SDP in the rtsp-sdp:// uri.

>+
>+  if (src->sdp != NULL) {
>+    GST_ERROR_OBJECT (src, "SDP already existing");
>+  } else {

Setting a new rtsp-sdp:// overrides the previous one.

>+    GST_DEBUG_OBJECT (src, "SDP protocol, extracting SDP data");
>+    if (gst_sdp_message_new (&src->sdp) == GST_SDP_OK &&
>+        gst_sdp_message_parse_buffer ((guchar *) string, l,
>+            src->sdp) == GST_SDP_OK) {
>+      GST_DEBUG_OBJECT (src, "got SDP message:\n%s", string);
>+
>+      for (i = 0;; i++) {
>+        control_url =
>+            gst_sdp_message_get_attribute_val_n (src->sdp, "control", i);
>+        if (control_url == NULL)
>+          break;
>+
>+        /* only take fully qualified urls */
>+        if (g_str_has_prefix (control_url, "rtsp://"))
>+          break;
>+      }
>+    } else {
>+      GST_ERROR_OBJECT (src, "unable to create SDP message");
>+    }
>+  }

There is no need to parse the control url, this will happen later.

> 
>+  if (g_str_has_prefix (uri, "sdp://")) {
>+    if ((uri = gst_rtspsrc_init_from_sdp (src, uri + 6)) == NULL)
>+      GST_ERROR ("unable to initialize from give SDP data");
>+  }
>+
>   /* try to parse */
>   if ((res = gst_rtsp_url_parse (uri, &newurl)) < 0)
>     goto parse_error;
> 

There is no need to retrieve the control url from the SDP and so there is also
no need to parse the control url.
Comment 8 Wim Taymans 2010-09-06 10:02:31 UTC
(In reply to comment #4)
> Created an attachment (id=168991) [details] [review]
> use rtspsrc as session element is sdpdemux when needed
> 
> Improved the number of streams handling.

This should simply use a redirect to an rtsp-sdp:// url.
Comment 9 Marco Ballesio 2010-09-06 11:35:47 UTC
(In reply to comment #7)

Thank you for the review, my notes below.

> (From update of attachment 168963 [details] [review])
> > static gchar **
> > gst_rtspsrc_uri_get_protocols (void)
> > {
> >-  static const gchar *protocols[] = { "rtsp", "rtspu", "rtspt", "rtsph", NULL };
> >+  static const gchar *protocols[] =
> >+      { "sdp", "rtsp", "rtspu", "rtspt", "rtsph", NULL };
> > 
> >   return (gchar **) protocols;
> > }
> 
> Please make a new rtsp-sdp:// uri which is less likely to conflict with an
> existing
> uri.
> 

Agreed.

> >+static const gchar *
> >+gst_rtspsrc_init_from_sdp (GstRTSPSrc * src, const gchar * sdpstr)
> >+{
> >+  int i, l = strlen (sdpstr);
> >+  gchar *string = g_malloc (l + 1);
> >+  const gchar *control_url = NULL;
> >+  strcpy (string, sdpstr);
> >+
> >+  for (i = 0; i < l; i++)
> >+    if (string[i] == ';' && string[i + 1] > 'a' && string[i + 1] < 'z'
> >+        && string[i + 2] == '=')
> >+      string[i] = '\n';
> 
> Why this cleanup of the SDP? I would pass a base64 encoded version of the raw
> SDP in the rtsp-sdp:// uri.

In sdpdemux the '\n' are converted with ';' . It's useful, for instance, to easily pass the uri from command line. They're then converted back to '\n' to let SDPMessage parse the content properly. It's trivial for me to remove all the mangling/demangling if we so decide.

> 
> >+
> >+  if (src->sdp != NULL) {
> >+    GST_ERROR_OBJECT (src, "SDP already existing");
> >+  } else {
> 
> Setting a new rtsp-sdp:// overrides the previous one.

But it's not clear to me what would happen if we set the SDP content after the streaming has already been initiated. I guess it would be more proper to check the state of the element here.

> 
> >+    GST_DEBUG_OBJECT (src, "SDP protocol, extracting SDP data");
> >+    if (gst_sdp_message_new (&src->sdp) == GST_SDP_OK &&
> >+        gst_sdp_message_parse_buffer ((guchar *) string, l,
> >+            src->sdp) == GST_SDP_OK) {
> >+      GST_DEBUG_OBJECT (src, "got SDP message:\n%s", string);
> >+
> >+      for (i = 0;; i++) {
> >+        control_url =
> >+            gst_sdp_message_get_attribute_val_n (src->sdp, "control", i);
> >+        if (control_url == NULL)
> >+          break;
> >+
> >+        /* only take fully qualified urls */
> >+        if (g_str_has_prefix (control_url, "rtsp://"))
> >+          break;
> >+      }
> >+    } else {
> >+      GST_ERROR_OBJECT (src, "unable to create SDP message");
> >+    }
> >+  }
> 
> There is no need to parse the control url, this will happen later.

If the control url is not set properly the function gst_rtspsrc_open_from_sdp will not find the control information and thus attempt to open a connection on the 'sdp://' uri (which, of course, cannot be handled). After this fails, no connection will be available to propagate further RTSP messages (e.g. SETUP).

> 
> > 
> >+  if (g_str_has_prefix (uri, "sdp://")) {
> >+    if ((uri = gst_rtspsrc_init_from_sdp (src, uri + 6)) == NULL)
> >+      GST_ERROR ("unable to initialize from give SDP data");
> >+  }
> >+
> >   /* try to parse */
> >   if ((res = gst_rtsp_url_parse (uri, &newurl)) < 0)
> >     goto parse_error;
> > 
> 
> There is no need to retrieve the control url from the SDP and so there is also
> no need to parse the control url.

See my comment above.
Comment 10 Marco Ballesio 2010-09-06 11:37:22 UTC
(In reply to comment #8)
> (In reply to comment #4)
> > Created an attachment (id=168991) [details] [review] [details] [review]
> > use rtspsrc as session element is sdpdemux when needed
> > 
> > Improved the number of streams handling.
> 
> This should simply use a redirect to an rtsp-sdp:// url.

So are you suggesting to:

1) handle rtsp in sdpdemux sending a redirection message
AND
2) handle redirection in uridecodebin?
Comment 11 Marco Ballesio 2010-09-06 11:39:37 UTC
(In reply to comment #5)
> > Still the key issue of state change violations in sdpdemux are remaining. 
> 
> What do you mean with that?

The 'session' element is added when the pipeline is already in PLAYING state and the set to PAUSED and PLAYING by the sdpdemux (not by the pipeline). The way through this suggested by Mark would be to use redirection, but this would mean to implement the handling of the signal in e.g. uridecodebin if we want to make the operation transparent to the application.
Comment 12 Wim Taymans 2010-09-06 11:50:01 UTC
(In reply to comment #9)
> (In reply to comment #7)
> 
> Thank you for the review, my notes below.
> 
> 
> In sdpdemux the '\n' are converted with ';' . It's useful, for instance, to
> easily pass the uri from command line. They're then converted back to '\n' to
> let SDPMessage parse the content properly. It's trivial for me to remove all
> the mangling/demangling if we so decide.

OK, I didn't realize that you want to pass an SDP from the command line like that. You can just as well cut and paste an SDP into a property with \n and all. Also, unfortunately, ; can be part of any string in the SDP (Appendix A, safe) 

> 
> But it's not clear to me what would happen if we set the SDP content after the
> streaming has already been initiated. I guess it would be more proper to check
> the state of the element here.

Yeah, just like any property that doesn't take immediate effect after a certain state change (like the location property) we mark them with the right flags on the paramspec. Checking the state of the element is not needed. 

> > There is no need to parse the control url, this will happen later.
> 
> If the control url is not set properly the function gst_rtspsrc_open_from_sdp
> will not find the control information and thus attempt to open a connection on
> the 'sdp://' uri (which, of course, cannot be handled). After this fails, no
> connection will be available to propagate further RTSP messages (e.g. SETUP).

The second thing that _open_from_sdp does is parse the control url from the SDP.
http://cgit.freedesktop.org/gstreamer/gst-plugins-good/tree/gst/rtsp/gstrtspsrc.c#n5172
Comment 13 Marco Ballesio 2010-09-08 07:20:18 UTC
(In reply to comment #12)
> 
> OK, I didn't realize that you want to pass an SDP from the command line like
> that. You can just as well cut and paste an SDP into a property with \n and
> all. Also, unfortunately, ; can be part of any string in the SDP (Appendix A,
> safe) 

I agree with you, fwiw it's more complex to pass from the command-line a string with '\n' through an option than to translate them with ';' and then re-convert back to '\n' with the heuristic in my implementation. To conclude I must admit that, being it an heuristic, it will fail in some possible cases, so I'll go the way you've proposed.

> 
> > 
> > But it's not clear to me what would happen if we set the SDP content after the
> > streaming has already been initiated. I guess it would be more proper to check
> > the state of the element here.
> 
> Yeah, just like any property that doesn't take immediate effect after a certain
> state change (like the location property) we mark them with the right flags on
> the paramspec. Checking the state of the element is not needed. 
> 
> > > There is no need to parse the control url, this will happen later.
> > 
> > If the control url is not set properly the function gst_rtspsrc_open_from_sdp
> > will not find the control information and thus attempt to open a connection on
> > the 'sdp://' uri (which, of course, cannot be handled). After this fails, no
> > connection will be available to propagate further RTSP messages (e.g. SETUP).
> 
> The second thing that _open_from_sdp does is parse the control url from the
> SDP.
> http://cgit.freedesktop.org/gstreamer/gst-plugins-good/tree/gst/rtsp/gstrtspsrc.c#n5172

Yes, but the problem here is originated from gst_rtspsrc_uri_set_uri which sets the uri containing the sdp:// address in the first stance. After that, gst_rtsp_conninfo_connect attempts to connect to that URI which is, as I already pointed out, quite difficult. The control URI parsing is the "less invasive" approach to address the issue.
Comment 14 Marco Ballesio 2010-09-08 11:16:08 UTC
Created attachment 169754 [details] [review]
enable rtspsrc to handle the SDP protocol

For the happiness of the command-liners, removed the de-mangling from ';' to '\n' ;).

Modified the protocol to use rtsp-sdp.

Other minor cosmetic improvements.
Comment 15 Marco Ballesio 2010-09-08 11:19:16 UTC
Created attachment 169755 [details] [review]
Bring the SDP protocol into existence

modified the uri identifier from "sdp://" to "rtsp-sdp://"
Comment 16 Marco Ballesio 2010-09-08 11:20:16 UTC
Created attachment 169756 [details] [review]
use rtspsrc as session element is sdpdemux when needed

modified the protocol identifier and some minor cosmetic changes.
Comment 17 Mark Nauwelaerts 2010-09-10 10:13:04 UTC
Created attachment 169936 [details] [review]
sdpdemux: redirect SDP with rtsp control url

FWIW, attached patch issues a plain rtsp:// redirect for some cases that might allow it.  Other cases may still need more "sdp-based" redirecting as discussed above.
Comment 18 Wim Taymans 2010-09-10 10:15:59 UTC
commit ae84ae1b36201f997fed6cabd3322fe37c103174
Author: Wim Taymans <wim.taymans@collabora.co.uk>
Date:   Fri Sep 10 11:55:26 2010 +0200

    rtspsrc: add rtsp-sdp protocol support
    
    Allow setting an SDP with the rtsp-sdp:// url.
    
    Based on patch from Marco Ballesio.
    
    See #628214
Comment 19 Wim Taymans 2010-09-10 11:04:39 UTC
interestingly: http://tools.ietf.org/html/draft-fujikawa-sdp-url-01
Comment 20 Wim Taymans 2010-09-10 16:09:26 UTC
OK, the way forward here is to use something resembling that (old) draft. The following patch allows conversion between SDP and an uri:

commit f5cbb6047fec82c72eff9965413ecb3e7c502eda
Author: Wim Taymans <wim.taymans@collabora.co.uk>
Date:   Fri Sep 10 17:55:46 2010 +0200

    sdp: add methods to convert between uri and message
    
    Add methods to convert between uri and sdpmessages, loosly based on
    http://tools.ietf.org/html/draft-fujikawa-sdp-url-01
    
    API: GstSDPMessage::gst_sdp_message_parse_uri
    API: GstSDPMessage::gst_sdp_message_as_uri
Comment 21 Wim Taymans 2010-09-10 16:39:16 UTC
And finally redirect in sdpdemux with the rtsp-sdp:// url.

commit 3daea4a085d34d5c1bc33fec2f2c04206621b41b
Author: Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Date:   Fri Sep 10 18:35:27 2010 +0200

    sdpdemux: redirect SDP with an rtsp control URL
    
    When we find an SDP with an rtsp:// url as the global control attribute or when
    all streams have an rtsp:// control attribute, post an redirect message with an
    rtsp-sdp:// url containing the SDP.
    
    Fixes #628214
Comment 22 Marco Ballesio 2010-09-10 20:23:22 UTC
So is the final decision to rely on the application to handle the redirection? Or is the redirection already handled at uridecodebin level? Or do we need a bug to add the latter?
Comment 23 Wim Taymans 2010-09-11 10:08:44 UTC
(In reply to comment #22)
> So is the final decision to rely on the application to handle the redirection?

Applications 'should' already do this now. The problem is that the redirect is not an official GStreamer core message so we can't really officially demand this.
Most notably qtdemux and mmssrc will post redirects on some files that will otherwise just fail.

> Or is the redirection already handled at uridecodebin level? Or do we need a
> bug to add the latter?

These redirects are usually caused by something inside the datastream and are thus emitted from the streaming threads. They however need to be handled from the main thread and that makes it difficult to implement this in uridecodebin.

In this particular case, I would not find it too disgusting to embed the rtspsrc inside sdpdemux (it already embeds the rtpbin and it's just one element and there are no application decisions to be made about bitrates). It just makes things more complicated wrt state changes and errors caused by the embedded elements that it makes me avoid it.
Comment 24 Marco Ballesio 2010-09-11 15:01:45 UTC
(In reply to comment #23)
> In this particular case, I would not find it too disgusting to embed the
> rtspsrc inside sdpdemux (it already embeds the rtpbin and it's just one element
> and there are no application decisions to be made about bitrates). It just
> makes things more complicated wrt state changes and errors caused by the
> embedded elements that it makes me avoid it.

I agree, so imho the patch:

https://bugzilla.gnome.org/attachment.cgi?id=169756

should follow the traditional implementation in sdpdemux more closely than:

https://bugzilla.gnome.org/attachment.cgi?id=169936
(which I understand you've applied).

moreover the former would not require applications to handle redirections (aka "it's transparent for the application").

I think it may be easy to make the two patches survive together if we want to: we may add a property in sdpdemux in order to make it either sending a redirection signal or handling rtsp contents the "traditional" way depending on the applications' needs.
Comment 25 Marco Ballesio 2010-09-24 15:45:26 UTC
Wim, loos like you forgot to push:

https://bugzilla.gnome.org/attachment.cgi?id=169755

without it the whole rtsp session in sdpdemux exercise is useless ;)
Comment 26 Marco Ballesio 2010-09-24 21:13:15 UTC
Ok, after a few I understand it's not because of this missing patch the feature is not working. Interestingly enough, launching:

gst-launch playbin2 uri=file:///media/devpen/dev/multimedia/hacknest/sdptests/sdptest.sdp

leaves the pipeline stuck right before going to playing. Trying to debug it with gdb:

gdb --args gst-launch playbin2 uri=file:///media/devpen/dev/multimedia/hacknest/sdptests/sdptest.sdp

instead works fine. I'd bet we've a race condition. Fortunately, it appears not to happen with my original patches.
Comment 27 Wim Taymans 2010-09-27 09:04:50 UTC
Seems to work fine here. Please attach backtrace of when it hangs.
Comment 28 Marco Ballesio 2010-09-27 20:24:30 UTC
Here it is:

  • #0 ??
    from /lib/ld-linux.so.2
  • #0 ??
    from /lib/ld-linux.so.2
  • #1 poll
    from /lib/tls/i686/cmov/libc.so.6
  • #2 g_poll
    from /lib/libglib-2.0.so.0
  • #3 ??
    from /lib/libglib-2.0.so.0
  • #4 g_main_loop_run
    from /lib/libglib-2.0.so.0
  • #5 gst_bus_poll
    at gstbus.c line 1059
  • #6 event_loop
    at gst-launch.c line 427
  • #7 main
    at gst-launch.c line 929

The process has been terminated with a SIGABRT. Unfortunately, it appears the stack is not much indicative though.
Comment 29 Marco Ballesio 2010-09-27 20:26:23 UTC
The logic of the bug statuses in GStreamer surpasses me. And I got really good evaluations at Computer Science Engineering though :D.
Comment 30 Wim Taymans 2010-09-28 08:26:24 UTC
You posted a backtrace of the mainloop (that is waiting for something to happen). You probably want a backtrace of the other threads like with: 

thr apply all bt
Comment 31 Marco Ballesio 2010-09-28 17:25:11 UTC
Created attachment 171284 [details]
stack trace taken for multiple threads at the deadlock point

Thanks for the hint. Here's the complete stack trace.
Comment 32 Mark Nauwelaerts 2010-10-04 15:30:54 UTC
Looks like the problem can be reproduced (almost certainly) by adding a 
  sleep (2);
at the top of gst_sdp_demux_start.
That will delay the streaming thread and arrange for the mainloop to have completed state change to PLAYING before other stuff happens.

The other stuff happening is then sdpdemux picking rtspsrc as manager, performing setup and setting it to state PLAYING.  It turns out that this does not make it past PAUSED as follows.  At some point, rtspsrc adds udpsrc, which is live, which makes gst_bin_add_func call upon bin_handle_async_done.
AFAICS, the latter then decides that rtspsrc is not a top level bin and discards the pending PLAYING state, leaving up to parents to do so.  However, those do not particularly care, as they have no pending state either (already reached PLAYING).
Comment 33 Marco Ballesio 2010-10-04 17:00:13 UTC
I can reproduce it easily without the need of any artificial delay on my development laptop (asus eeepc 701) which is pretty slow. Replacing the last patches on sdpdemux from Wim with mine (attached to bug 630046) the deadlock does not occur anymore. So far I haven't had much time to check why though.
Comment 34 Mark Nauwelaerts 2010-10-05 10:02:15 UTC
See bug #630046 for additional comment/patch.
Comment 35 Mark Nauwelaerts 2010-10-07 10:13:32 UTC
Race as discussed above has been settled in bug #630046.