Commit 2f1ed653 authored by Wim Taymans's avatar Wim Taymans

pad: Merge pad mode activation functions

Add the pad mode to the activate function so that we can reuse the same function
for all activation modes. This makes the core logic smaller and allows for some
elements to make their activation code easier. It would allow us to add more
scheduling modes later without having to add more activate functions.
parent 9e3aa102
......@@ -1000,11 +1000,9 @@ gst_ghost_pad_construct
gst_ghost_pad_unlink_default
gst_ghost_pad_link_default
gst_ghost_pad_activate_pull_default
gst_ghost_pad_activate_push_default
gst_ghost_pad_activate_mode_default
gst_ghost_pad_internal_activate_push_default
gst_ghost_pad_internal_activate_pull_default
gst_ghost_pad_internal_activate_mode_default
gst_proxy_pad_get_internal
......@@ -1642,8 +1640,7 @@ gst_pad_proxy_query_accept_caps
gst_pad_set_activate_function
GstPadActivateFunction
gst_pad_set_activatepush_function
gst_pad_set_activatepull_function
gst_pad_set_activatemode_function
GstPadActivateModeFunction
gst_pad_check_reconfigure
......@@ -1653,8 +1650,7 @@ gst_pad_push
gst_pad_push_event
gst_pad_push_list
gst_pad_pull_range
gst_pad_activate_pull
gst_pad_activate_push
gst_pad_activate_mode
gst_pad_send_event
gst_pad_event_default
......@@ -1728,7 +1724,7 @@ gst_pad_link_return_get_type
gst_pad_link_check_get_type
gst_pad_presence_get_type
gst_flow_return_get_type
gst_activate_mode_get_type
gst_pad_mode_get_type
gst_probe_return_get_type
gst_probe_type_get_type
......
......@@ -458,61 +458,31 @@ G_DEFINE_TYPE (GstGhostPad, gst_ghost_pad, GST_TYPE_PROXY_PAD);
static void gst_ghost_pad_dispose (GObject * object);
/**
* gst_ghost_pad_internal_activate_push_default:
* @pad: the #GstPad to activate or deactivate.
* @parent: the parent of @pad or NULL
* @active: whether the pad should be active or not.
*
* Invoke the default activate push function of a proxy pad that is
* owned by a ghost pad.
*
* Returns: %TRUE if the operation was successful.
*
* Since: 0.10.36
*/
gboolean
static gboolean
gst_ghost_pad_internal_activate_push_default (GstPad * pad, GstObject * parent,
gboolean active)
{
gboolean ret;
GstPad *other;
g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
GST_LOG_OBJECT (pad, "%sactivate push on %s:%s, we're ok",
(active ? "" : "de"), GST_DEBUG_PAD_NAME (pad));
/* in both cases (SRC and SINK) we activate just the internal pad. The targets
* will be activated later (or already in case of a ghost sinkpad). */
other = GST_PROXY_PAD_INTERNAL (pad);
ret = gst_pad_activate_push (other, active);
ret = gst_pad_activate_mode (other, GST_PAD_MODE_PUSH, active);
return ret;
}
/**
* gst_ghost_pad_internal_activate_pull_default:
* @pad: the #GstPad to activate or deactivate.
* @parent: the parent of @pad or NULL
* @active: whether the pad should be active or not.
*
* Invoke the default activate pull function of a proxy pad that is
* owned by a ghost pad.
*
* Returns: %TRUE if the operation was successful.
*
* Since: 0.10.36
*/
gboolean
static gboolean
gst_ghost_pad_internal_activate_pull_default (GstPad * pad, GstObject * parent,
gboolean active)
{
gboolean ret;
GstPad *other;
g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
GST_LOG_OBJECT (pad, "%sactivate pull on %s:%s", (active ? "" : "de"),
GST_DEBUG_PAD_NAME (pad));
......@@ -524,12 +494,12 @@ gst_ghost_pad_internal_activate_pull_default (GstPad * pad, GstObject * parent,
* further upstream */
GST_LOG_OBJECT (pad, "pad is src, activate internal");
other = GST_PROXY_PAD_INTERNAL (pad);
ret = gst_pad_activate_pull (other, active);
ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active);
} else if (G_LIKELY ((other = gst_pad_get_peer (pad)))) {
/* We are SINK, the ghostpad is SRC, we propagate the activation upstream
* since we hold a pointer to the upstream peer. */
GST_LOG_OBJECT (pad, "activating peer");
ret = gst_pad_activate_pull (other, active);
ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active);
gst_object_unref (other);
} else {
/* this is failure, we can't activate pull if there is no peer */
......@@ -541,18 +511,41 @@ gst_ghost_pad_internal_activate_pull_default (GstPad * pad, GstObject * parent,
}
/**
* gst_ghost_pad_activate_push_default:
* gst_ghost_pad_internal_activate_mode_default:
* @pad: the #GstPad to activate or deactivate.
* @parent: the parent of @pad or NULL
* @mode: the requested activation mode
* @active: whether the pad should be active or not.
*
* Invoke the default activate push function of a ghost pad.
* Invoke the default activate mode function of a proxy pad that is
* owned by a ghost pad.
*
* Returns: %TRUE if the operation was successful.
*
* Since: 0.10.36
*/
gboolean
gst_ghost_pad_internal_activate_mode_default (GstPad * pad, GstObject * parent,
GstPadMode mode, gboolean active)
{
gboolean res;
g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
switch (mode) {
case GST_PAD_MODE_PULL:
res = gst_ghost_pad_internal_activate_pull_default (pad, parent, active);
break;
case GST_PAD_MODE_PUSH:
res = gst_ghost_pad_internal_activate_push_default (pad, parent, active);
break;
default:
GST_LOG_OBJECT (pad, "unknown activation mode %d");
res = FALSE;
break;
}
return res;
}
static gboolean
gst_ghost_pad_activate_push_default (GstPad * pad, GstObject * parent,
gboolean active)
{
......@@ -566,32 +559,18 @@ gst_ghost_pad_activate_push_default (GstPad * pad, GstObject * parent,
/* just activate the internal pad */
other = GST_PROXY_PAD_INTERNAL (pad);
ret = gst_pad_activate_push (other, active);
ret = gst_pad_activate_mode (other, GST_PAD_MODE_PUSH, active);
return ret;
}
/**
* gst_ghost_pad_activate_pull_default:
* @pad: the #GstPad to activate or deactivate.
* @parent: the parent of @pad or NULL
* @active: whether the pad should be active or not.
*
* Invoke the default activate pull function of a ghost pad.
*
* Returns: %TRUE if the operation was successful.
*
* Since: 0.10.36
*/
gboolean
static gboolean
gst_ghost_pad_activate_pull_default (GstPad * pad, GstObject * parent,
gboolean active)
{
gboolean ret;
GstPad *other;
g_return_val_if_fail (GST_IS_GHOST_PAD (pad), FALSE);
GST_LOG_OBJECT (pad, "%sactivate pull on %s:%s", (active ? "" : "de"),
GST_DEBUG_PAD_NAME (pad));
......@@ -601,12 +580,12 @@ gst_ghost_pad_activate_pull_default (GstPad * pad, GstObject * parent,
* upstream */
GST_LOG_OBJECT (pad, "pad is src, activate internal");
other = GST_PROXY_PAD_INTERNAL (pad);
ret = gst_pad_activate_pull (other, active);
ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active);
} else if (G_LIKELY ((other = gst_pad_get_peer (pad)))) {
/* We are SINK and activated by the internal pad, propagate activation
* upstream because we hold a ref to the upstream peer */
GST_LOG_OBJECT (pad, "activating peer");
ret = gst_pad_activate_pull (other, active);
ret = gst_pad_activate_mode (other, GST_PAD_MODE_PULL, active);
gst_object_unref (other);
} else {
/* no peer, we fail */
......@@ -617,6 +596,40 @@ gst_ghost_pad_activate_pull_default (GstPad * pad, GstObject * parent,
return ret;
}
/**
* gst_ghost_pad_activate_mode_default:
* @pad: the #GstPad to activate or deactivate.
* @parent: the parent of @pad or NULL
* @mode: the requested activation mode
* @active: whether the pad should be active or not.
*
* Invoke the default activate mode function of a ghost pad.
*
* Returns: %TRUE if the operation was successful.
*/
gboolean
gst_ghost_pad_activate_mode_default (GstPad * pad, GstObject * parent,
GstPadMode mode, gboolean active)
{
gboolean res;
g_return_val_if_fail (GST_IS_GHOST_PAD (pad), FALSE);
switch (mode) {
case GST_PAD_MODE_PULL:
res = gst_ghost_pad_activate_pull_default (pad, parent, active);
break;
case GST_PAD_MODE_PUSH:
res = gst_ghost_pad_activate_push_default (pad, parent, active);
break;
default:
GST_LOG_OBJECT (pad, "unknown activation mode %d");
res = FALSE;
break;
}
return res;
}
/**
* gst_ghost_pad_link_default:
* @pad: the #GstPad to link.
......@@ -687,10 +700,8 @@ gst_ghost_pad_init (GstGhostPad * pad)
GST_GHOST_PAD_PRIVATE (pad) = G_TYPE_INSTANCE_GET_PRIVATE (pad,
GST_TYPE_GHOST_PAD, GstGhostPadPrivate);
gst_pad_set_activatepull_function (GST_PAD_CAST (pad),
gst_ghost_pad_activate_pull_default);
gst_pad_set_activatepush_function (GST_PAD_CAST (pad),
gst_ghost_pad_activate_push_default);
gst_pad_set_activatemode_function (GST_PAD_CAST (pad),
gst_ghost_pad_activate_mode_default);
}
static void
......@@ -721,8 +732,7 @@ gst_ghost_pad_dispose (GObject * object)
GST_OBJECT_LOCK (pad);
internal = GST_PROXY_PAD_INTERNAL (pad);
gst_pad_set_activatepull_function (internal, NULL);
gst_pad_set_activatepush_function (internal, NULL);
gst_pad_set_activatemode_function (internal, NULL);
/* disposes of the internal pad, since the ghostpad is the only possible object
* that has a refcount on the internal pad. */
......@@ -821,10 +831,8 @@ gst_ghost_pad_construct (GstGhostPad * gpad)
GST_PROXY_PAD_INTERNAL (internal) = pad;
/* special activation functions for the internal pad */
gst_pad_set_activatepull_function (internal,
gst_ghost_pad_internal_activate_pull_default);
gst_pad_set_activatepush_function (internal,
gst_ghost_pad_internal_activate_push_default);
gst_pad_set_activatemode_function (internal,
gst_ghost_pad_internal_activate_mode_default);
GST_OBJECT_UNLOCK (pad);
......
......@@ -125,13 +125,11 @@ gboolean gst_ghost_pad_construct (GstGhostPad *gpad);
void gst_ghost_pad_unlink_default (GstPad * pad);
GstPadLinkReturn gst_ghost_pad_link_default (GstPad * pad, GstPad * peer);
gboolean gst_ghost_pad_activate_pull_default (GstPad * pad, GstObject * parent, gboolean active);
gboolean gst_ghost_pad_activate_push_default (GstPad * pad, GstObject * parent, gboolean active);
gboolean gst_ghost_pad_activate_mode_default (GstPad * pad, GstObject * parent,
GstPadMode mode, gboolean active);
gboolean gst_ghost_pad_internal_activate_push_default (GstPad * pad, GstObject * parent,
gboolean active);
gboolean gst_ghost_pad_internal_activate_pull_default (GstPad * pad, GstObject * parent,
gboolean active);
gboolean gst_ghost_pad_internal_activate_mode_default (GstPad * pad, GstObject * parent,
GstPadMode mode, gboolean active);
G_END_DECLS
......
......@@ -632,31 +632,30 @@ gst_pad_get_direction (GstPad * pad)
static gboolean
gst_pad_activate_default (GstPad * pad, GstObject * parent)
{
return gst_pad_activate_push (pad, TRUE);
return gst_pad_activate_mode (pad, GST_PAD_MODE_PUSH, TRUE);
}
static void
pre_activate (GstPad * pad, GstPadMode new_mode)
{
switch (new_mode) {
case GST_PAD_MODE_PUSH:
case GST_PAD_MODE_PULL:
GST_OBJECT_LOCK (pad);
GST_DEBUG_OBJECT (pad, "setting ACTIVATE_MODE %d, unset flushing",
new_mode);
GST_PAD_UNSET_FLUSHING (pad);
GST_PAD_MODE (pad) = new_mode;
GST_OBJECT_UNLOCK (pad);
break;
case GST_PAD_MODE_NONE:
GST_OBJECT_LOCK (pad);
GST_DEBUG_OBJECT (pad, "setting ACTIVATE_MODE NONE, set flushing");
GST_DEBUG_OBJECT (pad, "setting PAD_MODE NONE, set flushing");
GST_PAD_SET_FLUSHING (pad);
GST_PAD_MODE (pad) = new_mode;
/* unlock blocked pads so element can resume and stop */
GST_PAD_BLOCK_BROADCAST (pad);
GST_OBJECT_UNLOCK (pad);
break;
case GST_PAD_MODE_PUSH:
case GST_PAD_MODE_PULL:
GST_OBJECT_LOCK (pad);
GST_DEBUG_OBJECT (pad, "setting PAD_MODE %d, unset flushing", new_mode);
GST_PAD_UNSET_FLUSHING (pad);
GST_PAD_MODE (pad) = new_mode;
GST_OBJECT_UNLOCK (pad);
break;
}
}
......@@ -664,10 +663,6 @@ static void
post_activate (GstPad * pad, GstPadMode new_mode)
{
switch (new_mode) {
case GST_PAD_MODE_PUSH:
case GST_PAD_MODE_PULL:
/* nop */
break;
case GST_PAD_MODE_NONE:
/* ensures that streaming stops */
GST_PAD_STREAM_LOCK (pad);
......@@ -677,6 +672,10 @@ post_activate (GstPad * pad, GstPadMode new_mode)
GST_OBJECT_UNLOCK (pad);
GST_PAD_STREAM_UNLOCK (pad);
break;
case GST_PAD_MODE_PUSH:
case GST_PAD_MODE_PULL:
/* NOP */
break;
}
}
......@@ -715,46 +714,26 @@ gst_pad_set_active (GstPad * pad, gboolean active)
GST_OBJECT_UNLOCK (pad);
if (active) {
switch (old) {
case GST_PAD_MODE_PUSH:
GST_DEBUG_OBJECT (pad, "activating pad from push");
ret = TRUE;
break;
case GST_PAD_MODE_PULL:
GST_DEBUG_OBJECT (pad, "activating pad from pull");
ret = TRUE;
break;
case GST_PAD_MODE_NONE:
GST_DEBUG_OBJECT (pad, "activating pad from none");
ret = (GST_PAD_ACTIVATEFUNC (pad)) (pad, parent);
break;
default:
GST_DEBUG_OBJECT (pad, "unknown activation mode!");
break;
if (old == GST_PAD_MODE_NONE) {
GST_DEBUG_OBJECT (pad, "activating pad from none");
ret = (GST_PAD_ACTIVATEFUNC (pad)) (pad, parent);
} else {
GST_DEBUG_OBJECT (pad, "pad was active in mode %d", old);
ret = TRUE;
}
} else {
switch (old) {
case GST_PAD_MODE_PUSH:
GST_DEBUG_OBJECT (pad, "deactivating pad from push");
ret = gst_pad_activate_push (pad, FALSE);
break;
case GST_PAD_MODE_PULL:
GST_DEBUG_OBJECT (pad, "deactivating pad from pull");
ret = gst_pad_activate_pull (pad, FALSE);
break;
case GST_PAD_MODE_NONE:
GST_DEBUG_OBJECT (pad, "deactivating pad from none");
ret = TRUE;
break;
default:
GST_DEBUG_OBJECT (pad, "unknown activation mode!");
break;
if (old == GST_PAD_MODE_NONE) {
GST_DEBUG_OBJECT (pad, "pad was inactive");
ret = TRUE;
} else {
GST_DEBUG_OBJECT (pad, "deactivating pad from mode %d", old);
ret = gst_pad_activate_mode (pad, old, FALSE);
}
}
RELEASE_PARENT (parent);
if (!ret)
if (G_UNLIKELY (!ret))
goto failed;
if (!active) {
......@@ -786,15 +765,13 @@ failed:
}
/**
* gst_pad_activate_pull:
* gst_pad_activate_mode:
* @pad: the #GstPad to activate or deactivate.
* @mode: the requested activation mode
* @active: whether or not the pad should be active.
*
* Activates or deactivates the given pad in pull mode via dispatching to the
* pad's activatepullfunc. For use from within pad activation functions only.
* When called on sink pads, will first proxy the call to the peer pad, which
* is expected to activate its internally linked pads from within its
* activate_pull function.
* Activates or deactivates the given pad in @mode via dispatching to the
* pad's activatemodefunc. For use from within pad activation functions only.
*
* If you don't know what this is, you probably don't want to call it.
*
......@@ -803,82 +780,69 @@ failed:
* MT safe.
*/
gboolean
gst_pad_activate_pull (GstPad * pad, gboolean active)
gst_pad_activate_mode (GstPad * pad, GstPadMode mode, gboolean active)
{
gboolean res = FALSE;
GstObject *parent;
GstPadMode old, new;
GstPadDirection dir;
GstPad *peer;
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
GST_OBJECT_LOCK (pad);
old = GST_PAD_MODE (pad);
dir = GST_PAD_DIRECTION (pad);
ACQUIRE_PARENT (pad, parent, no_parent);
GST_OBJECT_UNLOCK (pad);
if (active) {
switch (old) {
case GST_PAD_MODE_PULL:
GST_DEBUG_OBJECT (pad, "activating pad from pull, was ok");
goto was_ok;
case GST_PAD_MODE_PUSH:
GST_DEBUG_OBJECT (pad,
"activating pad from push, deactivate push first");
/* pad was activate in the wrong direction, deactivate it
* and reactivate it in pull mode */
if (G_UNLIKELY (!gst_pad_activate_push (pad, FALSE)))
goto deactivate_failed;
/* fallthrough, pad is deactivated now. */
case GST_PAD_MODE_NONE:
GST_DEBUG_OBJECT (pad, "activating pad from none");
break;
}
} else {
switch (old) {
case GST_PAD_MODE_NONE:
GST_DEBUG_OBJECT (pad, "deactivating pad from none, was ok");
goto was_ok;
case GST_PAD_MODE_PUSH:
GST_DEBUG_OBJECT (pad, "deactivating pad from push, weird");
/* pad was activated in the other direction, deactivate it
* in push mode, this should not happen... */
if (G_UNLIKELY (!gst_pad_activate_push (pad, FALSE)))
goto deactivate_failed;
/* everything is fine now */
goto was_ok;
case GST_PAD_MODE_PULL:
GST_DEBUG_OBJECT (pad, "deactivating pad from pull");
break;
}
new = active ? mode : GST_PAD_MODE_NONE;
if (old == new)
goto was_ok;
if (active && old != mode) {
/* pad was activate in the wrong direction, deactivate it
* and reactivate it in the requested mode */
GST_DEBUG_OBJECT (pad, "deactivating pad from mode %d", old);
if (G_UNLIKELY (!gst_pad_activate_mode (pad, old, FALSE)))
goto deactivate_failed;
}
if (gst_pad_get_direction (pad) == GST_PAD_SINK) {
if ((peer = gst_pad_get_peer (pad))) {
GST_DEBUG_OBJECT (pad, "calling peer");
if (G_UNLIKELY (!gst_pad_activate_pull (peer, active)))
goto peer_failed;
gst_object_unref (peer);
} else {
/* there is no peer, this is only fatal when we activate. When we
* deactivate, we must assume the application has unlinked the peer and
* will deactivate it eventually. */
if (active)
goto not_linked;
else
GST_DEBUG_OBJECT (pad, "deactivating unlinked pad");
}
} else {
if (G_UNLIKELY (GST_PAD_GETRANGEFUNC (pad) == NULL))
goto failure; /* Can't activate pull on a src without a
switch (mode) {
case GST_PAD_MODE_PULL:
{
if (dir == GST_PAD_SINK) {
if ((peer = gst_pad_get_peer (pad))) {
GST_DEBUG_OBJECT (pad, "calling peer");
if (G_UNLIKELY (!gst_pad_activate_mode (peer, mode, active)))
goto peer_failed;
gst_object_unref (peer);
} else {
/* there is no peer, this is only fatal when we activate. When we
* deactivate, we must assume the application has unlinked the peer and
* will deactivate it eventually. */
if (active)
goto not_linked;
else
GST_DEBUG_OBJECT (pad, "deactivating unlinked pad");
}
} else {
if (G_UNLIKELY (GST_PAD_GETRANGEFUNC (pad) == NULL))
goto failure; /* Can't activate pull on a src without a
getrange function */
}
break;
}
default:
break;
}
new = active ? GST_PAD_MODE_PULL : GST_PAD_MODE_NONE;
pre_activate (pad, new);
if (GST_PAD_ACTIVATEPULLFUNC (pad)) {
if (G_UNLIKELY (!GST_PAD_ACTIVATEPULLFUNC (pad) (pad, parent, active)))
if (GST_PAD_ACTIVATEMODEFUNC (pad)) {
if (G_UNLIKELY (!GST_PAD_ACTIVATEMODEFUNC (pad) (pad, parent, mode,
active)))
goto failure;
} else {
/* can happen for sinks of passthrough elements */
......@@ -886,8 +850,8 @@ gst_pad_activate_pull (GstPad * pad, gboolean active)
post_activate (pad, new);
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "%s in pull mode",
active ? "activated" : "deactivated");
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "%s in mode %d",
active ? "activated" : "deactivated", mode);
exit_success:
res = TRUE;
......@@ -904,22 +868,22 @@ no_parent:
}
was_ok:
{
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "already %s in pull mode",
active ? "activated" : "deactivated");
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "already %s in mode %d",
active ? "activated" : "deactivated", mode);
goto exit_success;
}
deactivate_failed:
{
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
"failed to %s in switch to pull from mode %d",
(active ? "activate" : "deactivate"), old);
"failed to %s in switch to mode %d from mode %d",
(active ? "activate" : "deactivate"), mode, old);
goto exit;
}
peer_failed:
{
GST_OBJECT_LOCK (peer);
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
"activate_pull on peer (%s:%s) failed", GST_DEBUG_PAD_NAME (peer));
"activate_mode on peer (%s:%s) failed", GST_DEBUG_PAD_NAME (peer));
GST_OBJECT_UNLOCK (peer);
gst_object_unref (peer);
goto exit;
......@@ -933,128 +897,8 @@ not_linked:
failure:
{
GST_OBJECT_LOCK (pad);
GST_CAT_INFO_OBJECT (GST_CAT_PADS, pad, "failed to %s in pull mode",
active ? "activate" : "deactivate");
GST_PAD_SET_FLUSHING (pad);
GST_PAD_MODE (pad) = old;
GST_OBJECT_UNLOCK (pad);
goto exit;
}
}
/**
* gst_pad_activate_push:
* @pad: the #GstPad to activate or deactivate.
* @active: whether the pad should be active or not.
*
* Activates or deactivates the given pad in push mode via dispatching to the
* pad's activatepushfunc. For use from within pad activation functions only.
*
* If you don't know what this is, you probably don't want to call it.
*
* Returns: %TRUE if the operation was successful.
*
* MT safe.
*/
gboolean
gst_pad_activate_push (GstPad * pad, gboolean active)
{
gboolean res = FALSE;
GstObject *parent;
GstPadMode old, new;
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "trying to set %s in push mode",
active ? "activated" : "deactivated");
GST_OBJECT_LOCK (pad);
old = GST_PAD_MODE (pad);
ACQUIRE_PARENT (pad, parent, no_parent);
GST_OBJECT_UNLOCK (pad);