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 475455 - GstBin should use internal_links for state changes
GstBin should use internal_links for state changes
Status: RESOLVED WONTFIX
Product: GStreamer
Classification: Platform
Component: gstreamer (core)
git master
Other Linux
: Normal enhancement
: git master
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2007-09-10 12:45 UTC by Laurent Glayal
Modified: 2018-05-04 08:58 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
debug log (2.77 KB, application/x-gzip)
2007-09-10 12:46 UTC, Laurent Glayal
Details
Information about used pipeline (1.80 KB, text/plain)
2007-09-11 09:13 UTC, Laurent Glayal
Details
gdb bt with G_DEBUG=fatal_criticals (2.08 KB, text/plain)
2007-09-12 08:23 UTC, Laurent Glayal
Details
associated log to G_DEBUG =fatal_criticals (413.46 KB, application/x-gzip)
2007-09-12 08:23 UTC, Laurent Glayal
Details
gdb bt with G_DEBUG=fatal_warnings (1.79 KB, text/plain)
2007-09-12 08:24 UTC, Laurent Glayal
Details
associated log to G_DEBUG=fatal_warnings (385.18 KB, application/x-gzip)
2007-09-12 08:25 UTC, Laurent Glayal
Details

Description Laurent Glayal 2007-09-10 12:45:22 UTC
Hi,
I had a working pipeline (a few weeks ago), this one was doing transcoding and worked properly, even with the loop in the graph.

With the current gstreamer cvs code some elements seems to be wrongly unreffed by
the gstreamer scheduler, here is a a typical result :

(<unknown>:3022): GStreamer-CRITICAL **:
Trying to dispose element mulawdec0, but it is not in the NULL state.
...
 (<unknown>:23228): GStreamer-CRITICAL **: gst_object_unref: assertion `((GObject *) object)->ref_count > 0' failed

The element is unreffed by function gstbin.c:1589 remove_from_queue(), called from
gstbin.c:1669  update_degree()

attached are some debug log about mulawdec0 element (only mulawdec0).

Regards.
Comment 1 Laurent Glayal 2007-09-10 12:46:13 UTC
Created attachment 95277 [details]
debug log
Comment 2 Tim-Philipp Müller 2007-09-10 15:19:31 UTC
Could you run your code with export G_DEBUG=fatal_warnings  in gdb and get a full stack trace with debugging symbols for the warning?

Could you make your code, or a simplified test program that demonstrates the bug, available?
Comment 3 Laurent Glayal 2007-09-11 09:13:26 UTC
Created attachment 95330 [details]
Information about used pipeline
Comment 4 Laurent Glayal 2007-09-12 08:21:37 UTC
Added stack trace and log 
- loop_detected_gdb_bt.txt : gdb bt from G_DEBUG=fatal_warnings
- loop_detected_log.txt.gz : associated log with GST_DEBUG=5

- critical_gdb_bt.txt : gdb bt from G_DEBUG=fatal_criticals (to avoid core dump on warnings from detected loop and some elements unable to answer latency query)
- critical_log.txt.gz : associated log with GST_DEBUG=5
Comment 5 Laurent Glayal 2007-09-12 08:23:03 UTC
Created attachment 95411 [details]
gdb bt with G_DEBUG=fatal_criticals
Comment 6 Laurent Glayal 2007-09-12 08:23:56 UTC
Created attachment 95412 [details]
associated log to G_DEBUG =fatal_criticals
Comment 7 Laurent Glayal 2007-09-12 08:24:28 UTC
Created attachment 95413 [details]
gdb bt with G_DEBUG=fatal_warnings
Comment 8 Laurent Glayal 2007-09-12 08:25:05 UTC
Created attachment 95414 [details]
associated log to G_DEBUG=fatal_warnings
Comment 9 Laurent Glayal 2007-09-12 08:41:26 UTC
Strange case... From the following cmd ::

for elt in `gzip -d -c critical_log.txt.gz |  egrep "add_to_queue|remove_from_queue" | cut -f2 -d\' | sort -u`
do
echo __ $elt __
gzip -d -c critical_log.txt.gz |  egrep "add_to_queue|remove_from_queue" | egrep $elt
done

- most elements are added to queue but not removed
- some elements are added and removed from queue (NetRtpBin,VoIPRtpBin)
- one element (alawdec0) is removed from queue but not added (or not with add_to_queue() !?)
Comment 10 Wim Taymans 2007-09-13 02:50:23 UTC
Seems like the loop might have caused the problem. With pipelines like that we should really use the internal_links function to walk the graph (it is then does not really contain a loop).
Comment 11 Laurent Glayal 2007-09-18 11:54:22 UTC
A quick and dirty patch could be this one :

static void
remove_from_queue (GstBinSortIterator * bit, GstElement * element)
{
  if (g_queue_find(bit->queue, element)) {
      GST_DEBUG_OBJECT (bit->bin, "removing '%s' from queue",
          GST_ELEMENT_NAME (element));
      g_queue_remove (bit->queue, element);
      gst_object_unref (element);
  } else {
      GST_DEBUG_OBJECT (bit->bin, "unable to remove '%s' from queue - not inserted",
          GST_ELEMENT_NAME (element));
  }
}

that is quite unefficient as we scan all the queue for all elements.
A more efficient solution could be to use the result of the g_queue_find to issue a remove with a g_queue_delete_link().

But it's just a workaround.
Comment 12 Wim Taymans 2007-10-09 16:21:49 UTC
I commited your workaround, it's better than crashing and burning hard.

        * gst/gstbin.c: (remove_from_queue):
        Work around a problem with pipelines containing (semi)loops until a 
        proper, more complicated solution is ready. See #475455.
Comment 13 Sebastian Dröge (slomo) 2009-08-21 17:03:07 UTC
Wouldn't an implementation over internal_links also fix bug #563828? There the problem is, that there is

a ! multiqueue ! b ! multiqueue ! c

Where the same multiqueue is used. In reality there's no loop ;) But then, bug #563828 should also be fixed in decodebin2 because linking twice to the multiqueue is suboptimal.
Comment 14 Sebastian Dröge (slomo) 2009-08-22 13:25:31 UTC
(In reply to comment #10)
> Seems like the loop might have caused the problem. With pipelines like that we
> should really use the internal_links function to walk the graph (it is then
> does not really contain a loop).

How exactly would that work?

When walking the graph via pad connections (i.e. ... ---> sinkpad --- internal_links ---> srcpad --- peer ---> sinkpad ) we would have a graph with pads as nodes. For every pad it's possible to get the parent element of course.

Here it must be ensured that there is no cycle in the pads graph but there could be cycles when transforming the pads graph to the corresponding elements graph. Right?

For iterating over all elements in topological order we would then walk this pad graph from the sink element's sink pads.



But when do we change the state of an element that owns a pad? The first time when all "dependencies" for at least one srcpad are done? Example: a(src1,src2) and (sink1)b, a.src1 is linked to b.sink1. After b has changed the state a can change the state too, no matter what the peer element of a.src2 does.
Comparison: currently we require that all srcpad "dependencies" are done.
Does this work as expected? Probably not, because example:  a(src1,src2), (sink1)b, (sink1)c. a.src1->b.sink1 and a.src2->c.sink1. a could then change state already once b or c has changed the state. Which would in the end mean, that a is trying to push data to an element in the wrong state (say a and b are PAUSED, c is still READY).
If we allow to change state when at least one srcpad dependency is done but require that for every bin state changes are done for those elements with the least remaining srcpad dependencies, would this work? But isn't this then the same behaviour as we have now?

If we require all srcpad dependencies to be done before changing the state there should be no difference which graph is walked. Unless I'm missing something the rtpbin<---->rtpbin loop example would then still not work because both rtpbin would wait for the other.
Comment 15 Olivier Crête 2009-08-22 15:31:15 UTC
I think the solution here is to split the element and instead have them share a common structure (so instead of having a single multiqueue element have multiple singlequeues that are all connected by some shared object. And/or having a sink that gives its buffer to a separate source element (so they could even be separate gst pipelines if they dont have to be synchronized).
Comment 16 Sebastian Dröge (slomo) 2014-02-13 14:41:05 UTC
Should we still worry about implement the state change stuff in GstBin with iterate_internal_links instead of what we do now? It shouldn't matter unless we want to allow loops in the element graph that are no loops in the link graph.
Comment 17 Wim Taymans 2014-02-13 15:04:39 UTC
I'm not so worried, we could mark this as an enhancement..
Comment 18 Sebastian Dröge (slomo) 2018-05-04 08:58:46 UTC
Let's close this then, does not seem that useful after all and non-trivial/impossible to implement.