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 722767 - element: add function to sync element state with target state of the parent
element: add function to sync element state with target state of the parent
Status: RESOLVED OBSOLETE
Product: GStreamer
Classification: Platform
Component: gstreamer (core)
1.x
Other Linux
: Normal enhancement
: git master
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2014-01-22 13:23 UTC by Miguel París Díaz
Modified: 2018-11-03 12:19 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
gstelement: add function to synchronize with parent target state (2.67 KB, patch)
2014-01-28 13:15 UTC, Miguel París Díaz
needs-work Details | Review
Sync state of a children with its parent target state. (2.11 KB, patch)
2014-02-10 11:08 UTC, Miguel París Díaz
none Details | Review

Description Miguel París Díaz 2014-01-22 13:23:15 UTC
I suggest adding a function to set the element state to the target state of its parent. This is useful for avoiding race condition problems in dynamic pipelines.

gboolean
gst_element_sync_target_state_with_parent (GstElement * element)
{
  GstElement *parent;
  GstState target;
  GstStateChangeReturn ret;

  g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);

  parent = GST_ELEMENT_CAST (gst_element_get_parent (element));

  if (element == NULL) {
    GST_DEBUG_OBJECT (element, "element has no parent");
    return FALSE;
  }

  GST_OBJECT_LOCK (parent);
  target = GST_STATE_TARGET (parent);
  GST_OBJECT_UNLOCK (parent);

  GST_DEBUG_OBJECT (element,
      "setting parent (%s) target state %s",
      GST_ELEMENT_NAME (parent),
      gst_element_state_get_name (target));

  gst_object_unref (parent);

  ret = gst_element_set_state (element, target);
  if (ret == GST_STATE_CHANGE_FAILURE) {
    GST_DEBUG_OBJECT (element,
        "setting target state failed (%s)",
        gst_element_state_change_return_get_name (ret));

    return FALSE;
  }

  return TRUE;
}
Comment 1 Stefan Sauer (gstreamer, gtkdoc dev) 2014-01-25 18:54:25 UTC
parent = GST_ELEMENT_CAST (gst_element_get_parent (element));

  if (element == NULL) {
    GST_DEBUG_OBJECT (element, "element has no parent");
    return FALSE;
  }

This should be: if (parent == NULL) { ...

In any way, please post this as a patch, so that we can properly review it :)
Comment 2 Miguel París Díaz 2014-01-28 13:15:38 UTC
Created attachment 267402 [details] [review]
gstelement: add function to synchronize with parent target state

OK, I attach the patch in this comment.
Also, I think that we can do a common code for this function and for the already existing gst_element_sync_state_with_parent function.
Comment 3 Sebastian Dröge (slomo) 2014-02-04 12:29:34 UTC
Review of attachment 267402 [details] [review]:

::: gst/gstelement.c
@@ +2016,3 @@
+ * Returns: TRUE, if the element's state could be synced to the parent's state.
+ *
+ * MT safe.

Please add a "Since: 1.4" line here

@@ +2044,3 @@
+  gst_object_unref (parent);
+
+  ret = gst_element_set_state (element, target);

Shouldn't we sync the state with the parent's state, but at the same time set the target to the parent's target state instead? Would be another option... but I guess what you do here right now makes most sense actually.
Comment 4 Miguel París Díaz 2014-02-10 11:08:31 UTC
Created attachment 268655 [details] [review]
Sync state of a children with its parent target state.

I have been thinking that a better solution is change the connotation of gst_element_sync_state_with_parent to avoid the users have concurrence problems.
I think that the users want use this function to sync the state of a element with the target state of its parent, not the current or the pending one, because these are variable.
Comment 5 Sebastian Dröge (slomo) 2014-02-11 20:20:19 UTC
The problem I see with this is that it can cause the child element to run ahead of the parent bin, e.g.

1) set_state(bin, PLAYING)
2) bin goes to READY
3) child is added, sync_state_with_parent() => set_state(child, PLAYING)
4) child goes to PLAYING directly
...
5) bin goes to PAUSED


Not sure if that is a problem. It seems weird though. And we need to check the code in GstBin to see if it could cause the child element in the above example to go from PLAYING to PAUSED, and then later back to PLAYING.
Comment 6 Miguel París Díaz 2014-02-12 21:18:01 UTC
In other hand, with the current implementation we have the next problem with a sinkelement if it does not receive the preroll:

1) set_state(bin, PLAYING)
2) bin goes to PLAYING
3) sinkelement (child_0) is added, sync_state_with_parent() => set_state(child_0, PLAYING)
4) child_0 goes to READY (blocked waiting for preroll), so parent syncs with its child and goes to READY.
5) another element (child_1) is added, sync_state_with_parent() => set_state(child_1, READY)
6) child_1 goes to READY
...

If the sink element does not receive a preroll the other elements in the bin are blocked, and if the generation of buffers (so the preroll) depends on a expected state never reached, the pipe has a "deadlock".
Comment 7 Sebastian Dröge (slomo) 2015-02-10 10:40:18 UTC
I just had a case where this also caused a pipeline to never go to PLAYING.
Comment 8 Miguel París Díaz 2015-02-11 11:54:51 UTC
Hello Sebastian,
could you explain your case, please?
Comment 9 Sebastian Dröge (slomo) 2015-02-12 15:57:33 UTC
This would be the simplified version:

Live pipeline in PLAYING with a tee. Two sinks (async=true) are added, synced state with parent. First sink gets set to PLAYING by sync_state(), pipeline goes to PAUSED (pending=PAUSED) because it loses state because the sink is going async to PAUSED. Second sink gets set to PAUSED by sync_state() (because pipeline is pending=PAUSED). Both sinks get a buffer, nothing ever sets the second sink to PLAYING (it still has target state PAUSED).
Comment 10 Miguel París Díaz 2015-02-17 23:21:31 UTC
Hi, sorry for the delay.

Yes, this is another case that would be solve with my proposal because it use the target state of the parent to set the state of the children, isn't it?

Moreover, I have to say that I am using this function in some cases and by the moment I have not got any problem:
https://github.com/Kurento/kms-core/blob/develop/src/gst-plugins/commons/kmsutils.c#L70
Comment 11 Sebastian Dröge (slomo) 2015-02-18 08:13:28 UTC
Yeah, it's probably not the worst idea. But then people are probably already expecting the existing function to do exactly that :)

OTOH it might be better to just deprecate the function and let people call gst_element_set_state() directly. That's more explicit then and no hidden surprises.
Comment 12 Sebastian Dröge (slomo) 2015-02-23 18:43:13 UTC
Any other opinions here? Should we just change sync_state() to use the target state?
Comment 13 Sebastian Dröge (slomo) 2015-02-24 09:04:23 UTC
Some related discussion on IRC

<wtay_> slomo, target state seems weird, you could set elements to playing already when the pipeline is still prerolling
<slomo> wtay_: yes, but is that a problem? without you have the same problem the other way around, just that it there can cause things to never go to PLAYING ;)
<wtay_> I don't know
<slomo> so maybe a new function to set the target state instead? but otoh that will probably confuse people as they'll never know which one to use
<slomo> wtay_: a problem could possibly be if the child element expects to go to PLAYING only from the surrounding pipeline and expects to have a clock and proper base time set at that point
<slomo> wtay_: but then this is going to break in other situations too currently... when people explicitly set the state to PLAYING instead of syncing with the parent state for example. which would be the recommended way of doing things considering the never-go-to-PLAYING bug with sync_state_with_parent()
Comment 14 GStreamer system administrator 2018-11-03 12:19:50 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/50.