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 754178 - uridecodebin: gst-discoverer doesn't detect both audio and video of RTSP streams
uridecodebin: gst-discoverer doesn't detect both audio and video of RTSP streams
Status: RESOLVED FIXED
Product: GStreamer
Classification: Platform
Component: gst-plugins-base
git master
Other Linux
: Normal normal
: 1.13.1
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2015-08-27 14:14 UTC by Vivia Nikolaidou
Modified: 2017-07-04 00:12 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
merge topologies from multiple decodebins (3.38 KB, patch)
2015-08-28 06:37 UTC, Vineeth
none Details | Review
uridecodebin: merge topologies from multiple decodebin (5.54 KB, patch)
2015-08-31 05:29 UTC, Vineeth
needs-work Details | Review
alternate method to aggregate toplologies. (3.92 KB, patch)
2015-09-24 06:56 UTC, Vineeth
none Details | Review
uridecodebin: aggregate topology messages (5.68 KB, patch)
2017-06-27 01:00 UTC, Mathieu Duponchelle
needs-work Details | Review
uridecodebin: aggregate topology messages (3.90 KB, patch)
2017-06-29 23:09 UTC, Olivier Crête
none Details | Review
uridecodebin: aggregate topology messages (4.05 KB, patch)
2017-06-29 23:12 UTC, Olivier Crête
committed Details | Review

Description Vivia Nikolaidou 2015-08-27 14:14:57 UTC
Test case:
$ cd gst-rtsp-server/examples
$ ./test-mp4 /file/with/both/audio/and/video.mp4

$ gst-play-1.0 rtsp://localhost:8554/output  <-- confirms that we hear audio and see video

$ gst-discoverer-1.0 rtsp://127.0.0.1:8554/test
Analyzing rtsp://127.0.0.1:8554/test
Done discovering rtsp://127.0.0.1:8554/test

Topology:
  unknown: application/x-rtp
    video: H.264

Properties:
  Duration: 0:25:00.116666666
  Seekable: yes

Where is the audio? :)
Comment 1 Vineeth 2015-08-28 04:24:24 UTC
the issue here is
in case of rtsp, it is adding audio and video streams in two different decodebin

0:00:02.279963303 18739 0xb10020f0 DEBUG          GST_PARENTAGE gstbin.c:1302:gst_bin_add: adding element decodebin0 to bin uridecodebin0
0:00:02.325272571 18739 0xb10020f0 DEBUG          GST_PARENTAGE gstbin.c:1302:gst_bin_add: adding element rtph263pdepay0 to bin decodebin0
0:00:02.334828185 18739 0xb10020f0 DEBUG          GST_PARENTAGE gstbin.c:1302:gst_bin_add: adding element h263parse0 to bin decodebin0
0:00:02.374257166 18739 0xb10020f0 DEBUG          GST_PARENTAGE gstbin.c:1302:gst_bin_add: adding element avdec_h263-0 to bin decodebin0

0:00:02.610085720 18739 0xb6114ec0 DEBUG          GST_PARENTAGE gstbin.c:1302:gst_bin_add: adding element decodebin1 to bin uridecodebin0
0:00:02.633267848 18739 0xb6114ec0 DEBUG          GST_PARENTAGE gstbin.c:1302:gst_bin_add: adding element rtpmp4gdepay0 to bin decodebin1
0:00:02.646833310 18739 0xb6114ec0 DEBUG          GST_PARENTAGE gstbin.c:1302:gst_bin_add: adding element aacparse0 to bin decodebin1
0:00:02.693690282 18739 0xb6114ec0 DEBUG          GST_PARENTAGE gstbin.c:1302:gst_bin_add: adding element avdec_aac0 to bin decodebin1


So it always shows the latest added streams' topology.

probably we should merge the structures for both the stream topologies.
Not sure if this is the right way to proceed
Comment 2 Vineeth 2015-08-28 06:37:30 UTC
Created attachment 310151 [details] [review]
merge topologies from multiple decodebins

Tried to fix the issue by adding all the different topologies into a dummy container and show them..


Before the change it was like
Topology:
  unknown: application/x-rtp
    audio: MPEG-4 AAC

After this change it shows as below
Topology:
  container: (null)
    unknown: application/x-rtp
      video: ITU H.26n
    unknown: application/x-rtp
      audio: MPEG-4 AAC

Not sure if there is any other simpler way to do it..


Please check if this is fine.
We can probably live without this change as well :)...
Comment 3 Sebastian Dröge (slomo) 2015-08-28 07:04:24 UTC
Review of attachment 310151 [details] [review]:

I think the merging should better take place inside uridecodebin

::: gst-libs/gst/pbutils/gstdiscoverer.c
@@ +1233,3 @@
 
+    if (dc->priv->current_topology) {
+      if (g_list_length (dc->priv->current_topology) > 1) {

> 1? Not > 0? You need to merge once there already is one topology and a new one arrives, no?

@@ +1238,3 @@
+            g_object_new (GST_TYPE_DISCOVERER_CONTAINER_INFO, NULL);
+
+        dc->priv->current_info->stream_info = (GstDiscovererStreamInfo *) cont;

Now if another topology arrives afterwards, you would add this container here and the new topology into yet another container. I think it would be better to merge them into the same container instead.
Comment 4 Vineeth 2015-08-28 07:17:29 UTC
(In reply to Sebastian Dröge (slomo) from comment #3)
> Review of attachment 310151 [details] [review] [review]:
> 
> I think the merging should better take place inside uridecodebin
> 
I am guessing that topology is used only in case of discover? If that is the case i felt, it is not that important to make the changes in uridecodebin..
But yeah that will help in consistency..


> ::: gst-libs/gst/pbutils/gstdiscoverer.c
> @@ +1233,3 @@
>  
> +    if (dc->priv->current_topology) {
> +      if (g_list_length (dc->priv->current_topology) > 1) {
> 
> > 1? Not > 0? You need to merge once there already is one topology and a new one arrives, no?
> 
> @@ +1238,3 @@
> +            g_object_new (GST_TYPE_DISCOVERER_CONTAINER_INFO, NULL);
> +
> +        dc->priv->current_info->stream_info = (GstDiscovererStreamInfo *)
> cont;
> 
> Now if another topology arrives afterwards, you would add this container
> here and the new topology into yet another container. I think it would be
> better to merge them into the same container instead.

In ideal cases, discoverer_collect will be called after all the topologies are received. The reason i am checking for >1 is, a new container should be created only if there are more than one topology.
Comment 5 Sebastian Dröge (slomo) 2015-08-28 08:00:32 UTC
(In reply to Vineeth from comment #4)
> (In reply to Sebastian Dröge (slomo) from comment #3)
> > Review of attachment 310151 [details] [review] [review] [review]:
> > 
> > I think the merging should better take place inside uridecodebin
> > 
> I am guessing that topology is used only in case of discover? If that is the
> case i felt, it is not that important to make the changes in uridecodebin..
> But yeah that will help in consistency..

We don't know what else it using it :) 

> > ::: gst-libs/gst/pbutils/gstdiscoverer.c
> > @@ +1233,3 @@
> >  
> > +    if (dc->priv->current_topology) {
> > +      if (g_list_length (dc->priv->current_topology) > 1) {
> > 
> > > 1? Not > 0? You need to merge once there already is one topology and a new one arrives, no?
> > 
> > @@ +1238,3 @@
> > +            g_object_new (GST_TYPE_DISCOVERER_CONTAINER_INFO, NULL);
> > +
> > +        dc->priv->current_info->stream_info = (GstDiscovererStreamInfo *)
> > cont;
> > 
> > Now if another topology arrives afterwards, you would add this container
> > here and the new topology into yet another container. I think it would be
> > better to merge them into the same container instead.
> 
> In ideal cases, discoverer_collect will be called after all the topologies
> are received. The reason i am checking for >1 is, a new container should be
> created only if there are more than one topology.

What does "ideal case" mean here? Is it always called after everything is collected right before exposing the information or can it be callde multiple times? :)
Comment 6 Vineeth 2015-08-28 08:04:21 UTC
i could not find any cases where another new topology arrives after discoverer_collect is called. 
from the code, discover collect will be called only for EOS, ASYNC_DONE.
Or even if it is called before, it checks if stream is available, which will not be available until a pad is added.

i maybe wrong :)
Comment 7 Sebastian Dröge (slomo) 2015-08-28 08:05:48 UTC
Seems ok to do it like that then, but still the message merging should happen in uridecodebin :) It's the place where there are multiple decodebins and its always the bins job to merge messages of the child elements as required.
Comment 8 Vineeth 2015-08-31 05:29:20 UTC
Created attachment 310324 [details] [review]
uridecodebin: merge topologies from multiple decodebin

I have made the changes in uridecodebin..

Here i am just ignoring the message posted from decodebin and instead as soon as all the decodebin elements are added, getting the topology for each decodebin and merging all of them into a structure and posting the message.

Have a little doubt if i am calling it in the right place..

Please review :)
Comment 9 Sebastian Dröge (slomo) 2015-09-23 08:22:35 UTC
Review of attachment 310324 [details] [review]:

I think this is not the right approach. In uridecodebin (and playbin for that matter too, it can have two uridecodebin) you should catch the messages with the topology. But only forward the message with the topology once all decodebins have posted theirs, and the forwarded message then contains all topologies merged together.

It should still all be triggered by messages, just that you aggregate them. Similar to what is done with the buffering messages.
Comment 10 Vineeth 2015-09-24 06:47:44 UTC
(In reply to Sebastian Dröge (slomo) from comment #9)
> Review of attachment 310324 [details] [review] [review]:
> 
> I think this is not the right approach. In uridecodebin (and playbin for
> that matter too, it can have two uridecodebin) you should catch the messages
> with the topology. But only forward the message with the topology once all
> decodebins have posted theirs, and the forwarded message then contains all
> topologies merged together.
> 
> It should still all be triggered by messages, just that you aggregate them.
> Similar to what is done with the buffering messages.

I was not sure when to post the message after aggregating.

I mean how will uridecodebin come to know that there are no more decodebin messages being posted??.

no_more_pads_full is the function where we know if there are no more decodebins being added. But the element message is being posted after this.


One way i can think of is,
keep aggregating and keep posting the message..
This way once first decodebin message gets posted it will be forwarded..
when the second decodebin posts message, then both first and second will be aggregated and forwarded.



Please guide if there is any better way to know when uridecodebin will be sure that no more messages will be posted from decodebin


PS: I tried posting on paused_to_playing state change.. But that seems to be too late and discoverer doesn't get the message.
Comment 11 Vineeth 2015-09-24 06:56:10 UTC
Created attachment 312002 [details] [review]
alternate method to aggregate toplologies.

As mentioned in the previous comment, 
this is another method by which we can aggregate and post the message.


The best way is post a single message after aggregating all the messages if that is possible. But i am not able to find any such place where all this works :)
Comment 12 Sebastian Dröge (slomo) 2015-09-24 08:03:22 UTC
I think it should work the following way: you post the first aggregated message once each decodebin has posted a message, from then on you post an aggregated message whenever a decodebin tells you about any changes.
When uridecodebin goes back to READY, and then PAUSED/PLAYING again, you wait again until each decodebin has posted the message.
Comment 13 Vivia Nikolaidou 2016-02-17 14:59:00 UTC
Hi, do you have any progress here? I could pick up work on it if you're not interested anymore, but if you're still planning to finish this patch, just let me know :)
Comment 14 Vineeth 2016-02-18 00:21:47 UTC
Hi i wont be able to work on this particular issue at least for a week or two..
please free to work on it if you are interested :)..
Comment 15 Vivia Nikolaidou 2016-06-03 10:26:37 UTC
Now it works even worse. RTSP detects neither the audio nor the video:

vivia@erato /u/l/s/g/h/g/examples (master)> ./test-video
stream ready at rtsp://127.0.0.1:8554/test

vivia@erato /u/l/s/g/h/gst-plugins-bad (master) [141]> 
gst-discoverer-1.0 rtsp://127.0.0.1:8554/test
Analyzing rtsp://127.0.0.1:8554/test
Done discovering rtsp://127.0.0.1:8554/test
Comment 16 Mathieu Duponchelle 2017-05-31 03:29:55 UTC
Vivia, that last issue is fixed (https://bugzilla.gnome.org/show_bug.cgi?id=754178).

Regarding this specific issue, I'm actually unsure what the best thing to do is to be honest.

What you propose, Sebastian, means that we will always get a bogus top-level "container" that isn't actually a container.

Even if we start special-casing things, like in that case, it seems weird to me to say that the streams discovered for a rtsp uri are *contained* by something, doesn't it ?

So unless we decide that a protocol is a "container", we need to figure out how to let the discoverer know that the decoded uri maps to several streams / containers IMHO.

Curious to know your thoughts, I'm willing to work on this, just not sure what end result we're actually after, apart from "We want to see the information for all the streams" :)
Comment 17 Sebastian Dröge (slomo) 2017-05-31 07:14:19 UTC
(In reply to Mathieu Duponchelle from comment #16)

> Even if we start special-casing things, like in that case, it seems weird to
> me to say that the streams discovered for a rtsp uri are *contained* by
> something, doesn't it ?

It seems not too far fetched to say that the streams are "contained" in the SDP from the server, but yes we have no actual pad for this. So discoverer would indeed need a way to have several top-level streams.
Comment 18 Mathieu Duponchelle 2017-06-27 01:00:52 UTC
Created attachment 354539 [details] [review]
uridecodebin: aggregate topology messages
Comment 19 Mathieu Duponchelle 2017-06-27 01:06:34 UTC
Here's yet another take on this, as Sebastian asked previously, this patch only posts a topology once all the decodebins have posted theirs, then posts a new, correctly updated topology every time a decodebin posts a new topology (the old topology is replaced with the new one).

As for the whole "container" issue, I'm afraid we can't do much without breaking an unfortunate amount of programs calling that API.

The previously proposed patch had all discoveries wrapped in a dummy container, this new patch at least retains the old behavior for the standard case where a single topology was obtained and propagated upstream, the only case where we do have a dummy container is the previously-broken case, such as the one this issue was about.

Here's an example output:

 meh   master  ~  devel  sandbox  gst-build-master  GST_DEBUG=0 gst-discoverer-1.0 -v rtsp://184.72.239.149/vod/mp4:BigBuckBunny_115k.mov
Analyzing rtsp://184.72.239.149/vod/mp4:BigBuckBunny_115k.mov
Done discovering rtsp://184.72.239.149/vod/mp4:BigBuckBunny_115k.mov

Topology:
  container: text/x-uri
    unknown: application/x-rtp, media=(string)video, payload=(int)97, clock-rate=(int)90000, encoding-name=(string)H264, packetization-mode=(string)1, profile-level-id=(string)42C01E, sprop-parameter-sets=(string)"Z0LAHtkDxWhAAAADAEAAAAwDxYuS\,aMuMsg\=\=", a-framesize=(string)240-160, a-sdplang=(string)en, a-cliprect=(string)"0\,0\,160\,240", a-framerate=(string)24.0, ssrc=(uint)695662262, clock-base=(uint)0, seqnum-base=(uint)1, npt-start=(guint64)0, npt-stop=(guint64)596480000000, play-speed=(double)1, play-scale=(double)1
      video: video/x-h264, stream-format=(string)avc, alignment=(string)au, codec_data=(buffer)0142c01effe100156742c01ed903c56840000003004000000c03c58b9201000468cb8cb2, level=(string)3, profile=(string)constrained-baseline, width=(int)240, height=(int)160, framerate=(fraction)0/1, interlace-mode=(string)progressive, parsed=(boolean)true
        Tags:
          video codec: H.264 (Constrained Baseline Profile)
        
        Codec:
          video/x-h264, stream-format=(string)avc, alignment=(string)au, codec_data=(buffer)0142c01effe100156742c01ed903c56840000003004000000c03c58b9201000468cb8cb2, level=(string)3, profile=(string)constrained-baseline, width=(int)240, height=(int)160, framerate=(fraction)0/1, interlace-mode=(string)progressive, parsed=(boolean)true
        Additional info:
          None
        Stream ID: b62e9a00f1bd1881d4e436344e14b135d8ac17373100c4fe9903286bb006129a/video:0:0:RTP:AVP:97
        Width: 240
        Height: 160
        Depth: 24
        Frame rate: 0/1
        Pixel aspect ratio: 1/1
        Interlaced: false
        Bitrate: 0
        Max bitrate: 0
    unknown: application/x-rtp, media=(string)audio, payload=(int)96, clock-rate=(int)12000, encoding-name=(string)MPEG4-GENERIC, encoding-params=(string)2, profile-level-id=(string)1, mode=(string)AAC-hbr, sizelength=(string)13, indexlength=(string)3, indexdeltalength=(string)3, config=(string)1490, a-sdplang=(string)en, ssrc=(uint)969373029, clock-base=(uint)0, seqnum-base=(uint)1, npt-start=(guint64)0, npt-stop=(guint64)596480000000, play-speed=(double)1, play-scale=(double)1
      audio: audio/mpeg, mpegversion=(int)4, stream-format=(string)raw, codec_data=(buffer)1490, framed=(boolean)true, level=(string)1, base-profile=(string)lc, profile=(string)lc, rate=(int)12000, channels=(int)2
        Tags:
          audio codec: MPEG-4 AAC
        
        Codec:
          audio/mpeg, mpegversion=(int)4, stream-format=(string)raw, codec_data=(buffer)1490, framed=(boolean)true, level=(string)1, base-profile=(string)lc, profile=(string)lc, rate=(int)12000, channels=(int)2
        Additional info:
          None
        Stream ID: b9049c323800fa1dbf0c9c2f5d6dcf0e63b50fc2c5030d1c14e44a893d14e333/audio:0:0:RTP:AVP:96
        Language: <unknown>
        Channels: 2
        Sample rate: 12000
        Depth: 32
        Bitrate: 0
        Max bitrate: 0

Properties:
  Duration: 0:09:56.480000000
  Seekable: yes
  Tags: 
      audio codec: MPEG-4 AAC
      video codec: H.264 (Constrained Baseline Profile)

 meh   master  ~  devel  sandbox  gst-build-master 
Comment 20 Mathieu Duponchelle 2017-06-27 01:10:05 UTC
I'd argue that container with `text/x-uri` sort of makes sense a weird way, but I'm a bit biased, I guess follow-up patches could be made to have gst-discoverer interpret this as a newly-defined `GST_DISCOVERER_STREAM_COLLECTION_INFO` or somesuch, but I'm afraid this could break existing users of the API, thoughts on that ?
Comment 21 Olivier Crête 2017-06-29 22:36:50 UTC
Review of attachment 354539 [details] [review]:

I also wonder if you shouldn't drop the counter and just iterate over the whoel list of decodebins every time, this is probably less error-prone.

::: gst/playback/gsturidecodebin.c
@@ +118,3 @@
   guint64 ring_buffer_max_size; /* 0 means disabled */
+
+  gint pending_topologies;

How is this counter locked?

@@ +2467,3 @@
+      sttype = gst_structure_get_name_id (structure);
+
+      if (sttype == topology_structure_name) {

Why not just use gst_message_has_name() ?

@@ +2471,3 @@
+        GstElement *element = GST_ELEMENT (GST_MESSAGE_SRC (msg));
+
+        gst_message_unref (msg);

After this structure is no longer valid, you need to keep the message alive... it owns the GstStructure

@@ +2483,3 @@
+
+        g_object_set_data (G_OBJECT (element), "topology",
+            gst_structure_copy (structure));

Since you free'd msg, the GstStructure pointer is not valid anymore.

Also, I think that will leak the structure.. Mabye you want to use g_object_set_data_full() instead. Then you can also drop the gst_structure_free() in remove_decoders().
Comment 22 Olivier Crête 2017-06-29 23:09:22 UTC
Created attachment 354714 [details] [review]
uridecodebin: aggregate topology messages

This is based on Matthieu's commit, I tried to simplify it a bit. The only thing I'm not sure about is the text/x-uri as the container name. I'd love ot have somethign like network/rtsp.
Comment 23 Olivier Crête 2017-06-29 23:12:08 UTC
Created attachment 354715 [details] [review]
uridecodebin: aggregate topology messages

Same as my previous patch, but does "application/<uri's protocol>" as the caps for the pseudo-container, what do you think?
Comment 24 Mathieu Duponchelle 2017-06-30 16:09:27 UTC
Review of attachment 354715 [details] [review]:

This looks like a good improvement, there was indeed no need for ->pending_topologies

::: gst/playback/gsturidecodebin.c
@@ +2461,3 @@
+        gboolean has_all_topo = TRUE;
+
+        if (dec->pending || (dec->decodebins && dec->decodebins->next != NULL)) {

Why do we need to check for dec->pending here ?
Comment 25 Sebastian Dröge (slomo) 2017-07-03 06:31:36 UTC
The idea of using such a "pseudo" container makes sense IMHO, didn't look at the implementation though. Would be nice to get this fixed, thanks for working on it.
Comment 26 Olivier Crête 2017-07-03 18:14:48 UTC
(In reply to Mathieu Duponchelle from comment #24)
> Why do we need to check for dec->pending here ?

Because we need for the no-more-pads from the source I think, otherwise we get an empty topology for RTSP. I think it's basically the same thing that was done with the redundant pending_topologies.
Comment 27 Mathieu Duponchelle 2017-07-03 22:35:44 UTC
(In reply to Olivier Crête from comment #26)
> (In reply to Mathieu Duponchelle from comment #24)
> > Why do we need to check for dec->pending here ?
> 
> Because we need for the no-more-pads from the source I think, otherwise we
> get an empty topology for RTSP. I think it's basically the same thing that
> was done with the redundant pending_topologies.

I don't understand that, where do we "get an empty topology" ? In discoverer ? If so, how can it be empty, as what now triggers uuridecodebin to post a topology is getting a (presumably non-empty) topology from one of its decodebins.

As we increment ->pending along with prepending to the list of decodebins, I think checking for it and for "all_topos" is redundant ?
Comment 28 Mathieu Duponchelle 2017-07-03 22:41:40 UTC
> As we increment ->pending along with prepending to the list of decodebins, I
> think checking for it and for "all_topos" is redundant ?

Actually I just realized pending was also incremented when the source has dynamic pads, which is our case here, and this protects us from a race where the first decodebin would post a topology before the source had exposed all its pads, leading to a not empty but still incomplete topology, accepted commit now then :D
Comment 29 Mathieu Duponchelle 2017-07-03 22:42:06 UTC
Review of attachment 354715 [details] [review]:

No more comments :)
Comment 30 Olivier Crête 2017-07-04 00:11:02 UTC
Merged

commit bfba2134377b2864a6dbf4f7c13967ec603c037e
Author: Mathieu Duponchelle <mathieu.duponchelle@collabora.com>
Date:   Tue Jun 27 02:21:22 2017 +0200

    uridecodebin: aggregate topology messages
    
    This makes it possible for GstDiscoverer to work with sources that
    have multiple source pads and hence will trigger the creation of multiple
    decodebin instances such as rtspsrc.
    
    Based on the work of Vineeth TM <vineeth.tm@samsung.com>
    
    https://bugzilla.gnome.org/show_bug.cgi?id=754178