mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 08:46:40 +00:00
docs/design/part-gstghostpad.txt: Update ascii art in documentation.
Original commit message from CVS: * docs/design/part-gstghostpad.txt: Update ascii art in documentation. * gst/gstghostpad.c: (gst_proxy_pad_do_internal_link), (gst_proxy_pad_set_target_unlocked), (gst_proxy_pad_init), (gst_ghost_pad_parent_set), (gst_ghost_pad_parent_unset), (gst_ghost_pad_internal_do_activate_push), (gst_ghost_pad_internal_do_activate_pull), (gst_ghost_pad_do_activate_push), (gst_ghost_pad_do_activate_pull), (gst_ghost_pad_do_link), (gst_ghost_pad_do_unlink), (gst_ghost_pad_dispose), (gst_ghost_pad_new_full), (gst_ghost_pad_set_target): Small cleanups and leak fixes. Remove some checks now that the internal pad is never NULL. Fix the case where linking pads without a target would create nasty criticals. Fixes #341029. Don't assign a GstPadLinkReturn to a gboolean and mess up the return value of _set_target(). * tests/check/gst/gstghostpad.c: (GST_START_TEST), (gst_ghost_pad_suite): Some more tests for creating and linking untargeted ghostpads.
This commit is contained in:
parent
ce6e126d47
commit
47e5ba2f15
4 changed files with 398 additions and 274 deletions
25
ChangeLog
25
ChangeLog
|
@ -1,3 +1,28 @@
|
|||
2006-08-31 Wim Taymans <wim@fluendo.com>
|
||||
|
||||
* docs/design/part-gstghostpad.txt:
|
||||
Update ascii art in documentation.
|
||||
|
||||
* gst/gstghostpad.c: (gst_proxy_pad_do_internal_link),
|
||||
(gst_proxy_pad_set_target_unlocked), (gst_proxy_pad_init),
|
||||
(gst_ghost_pad_parent_set), (gst_ghost_pad_parent_unset),
|
||||
(gst_ghost_pad_internal_do_activate_push),
|
||||
(gst_ghost_pad_internal_do_activate_pull),
|
||||
(gst_ghost_pad_do_activate_push), (gst_ghost_pad_do_activate_pull),
|
||||
(gst_ghost_pad_do_link), (gst_ghost_pad_do_unlink),
|
||||
(gst_ghost_pad_dispose), (gst_ghost_pad_new_full),
|
||||
(gst_ghost_pad_set_target):
|
||||
Small cleanups and leak fixes.
|
||||
Remove some checks now that the internal pad is never NULL.
|
||||
Fix the case where linking pads without a target would create nasty
|
||||
criticals. Fixes #341029.
|
||||
Don't assign a GstPadLinkReturn to a gboolean and mess up the return
|
||||
value of _set_target().
|
||||
|
||||
* tests/check/gst/gstghostpad.c: (GST_START_TEST),
|
||||
(gst_ghost_pad_suite):
|
||||
Some more tests for creating and linking untargeted ghostpads.
|
||||
|
||||
2006-08-31 Edward Hervey <edward@fluendo.com>
|
||||
|
||||
* docs/gst/gstreamer-sections.txt:
|
||||
|
|
|
@ -9,9 +9,9 @@ Ghostpads
|
|||
|
||||
- Must look like a real GstPad on both sides.
|
||||
- target of Ghostpad must be changeable
|
||||
- target can be initially NULL
|
||||
|
||||
|
||||
* a GhostPad is implemented using a smaller GstProxyPad class:
|
||||
* a GhostPad is implemented using a private GstProxyPad class:
|
||||
|
||||
|
||||
GstProxyPad
|
||||
|
@ -20,17 +20,57 @@ Ghostpads
|
|||
|------------------|
|
||||
| GstPad *target |
|
||||
(------------------)
|
||||
| GstPad *internal |
|
||||
(------------------)
|
||||
|
||||
|
||||
GstGhostPad
|
||||
(------------------) -\
|
||||
| GstPad | |
|
||||
|------------------| > GstProxyPad
|
||||
| GstPad *target | |
|
||||
|------------------| |
|
||||
| GstPad *target | > GstProxyPad
|
||||
|------------------| |
|
||||
| GstPad *internal | |
|
||||
|------------------| -/
|
||||
| GstPad *internal |
|
||||
| <private data> |
|
||||
(------------------)
|
||||
|
||||
A GstGhostPad (X) is _always_ created together with a GstProxyPad (Y).
|
||||
The internal pad pointers are set to point to the eachother. The
|
||||
GstProxyPad pairs have opposite directions, the GstGhostPad has the same
|
||||
direction as the (future) ghosted pad (target).
|
||||
|
||||
|
||||
(- X --------)
|
||||
| |
|
||||
| target * |
|
||||
|------------|
|
||||
| internal *----+
|
||||
(------------) |
|
||||
^ V
|
||||
| (- Y --------)
|
||||
| | |
|
||||
| | target * |
|
||||
| |------------|
|
||||
+----* internal |
|
||||
(------------)
|
||||
|
||||
Which we will abreviate to:
|
||||
|
||||
(- X --------)
|
||||
| |
|
||||
| target *--------->//
|
||||
(------------)
|
||||
|
|
||||
(- Y --------)
|
||||
| target *----->//
|
||||
(------------)
|
||||
|
||||
The GstGhostPad (X) is also set as the parent of the GstProxyPad (Y).
|
||||
|
||||
The target is a pointer to the internal pads peer. It is an optimisation to
|
||||
quickly get to the peer of a ghostpad without having to dereference the
|
||||
internal->peer.
|
||||
|
||||
Some use case follow with a description of how the datastructure
|
||||
is modified.
|
||||
|
@ -40,11 +80,11 @@ Ghostpads
|
|||
|
||||
gst_ghost_pad_new (char *name, GstPad *target)
|
||||
|
||||
1) create new GstGhostPad X
|
||||
1) create new GstGhostPad X + GstProxyPad Y
|
||||
2) X name set to @name
|
||||
3) X direction is the same as the target
|
||||
4) the target is set to @target
|
||||
5) internal is NULL
|
||||
3) X direction is the same as the target, Y is opposite.
|
||||
4) the target of X is set to @target
|
||||
5) Y is linked to @target
|
||||
6) link/unlink and activate functions are set up
|
||||
on GstGhostPad.
|
||||
|
||||
|
@ -53,9 +93,11 @@ Ghostpads
|
|||
(- X --------) |
|
||||
| | |------)
|
||||
| target *------------------> | sink |
|
||||
|------------| |------)
|
||||
| internal *---->// (--------------
|
||||
(------------)
|
||||
(------------) -------> |------)
|
||||
| / (--------------
|
||||
(- Y --------) / (pad link)
|
||||
//<-----* target |/
|
||||
(------------)
|
||||
|
||||
- Automatically takes same direction as target.
|
||||
- target is filled in automatically.
|
||||
|
@ -65,20 +107,20 @@ Ghostpads
|
|||
|
||||
gst_ghost_pad_new_no_target (char *name, GstPadDirection dir)
|
||||
|
||||
1) create new GstGhostPad X
|
||||
1) create new GstGhostPad X + GstProxyPad Y
|
||||
2) X name set to @name
|
||||
3) X direction is @dir
|
||||
4) internal is NULL
|
||||
5) link/unlink and activate functions are set up
|
||||
on GstGhostPad.
|
||||
|
||||
|
||||
(- X --------)
|
||||
| |
|
||||
| target *------>//
|
||||
|------------|
|
||||
| internal *---->//
|
||||
| target *--------->//
|
||||
(------------)
|
||||
|
|
||||
(- Y --------)
|
||||
| target *----->//
|
||||
(------------)
|
||||
|
||||
- allows for setting the target later
|
||||
|
||||
|
@ -89,57 +131,67 @@ Ghostpads
|
|||
|
||||
(- X --------)
|
||||
| |
|
||||
| target *------>//
|
||||
|------------|
|
||||
| internal *---->//
|
||||
| target *--------->//
|
||||
(------------)
|
||||
|
|
||||
(- Y --------)
|
||||
| target *----->//
|
||||
(------------)
|
||||
|
||||
1) assert direction of newtarget == X direction
|
||||
2) target is set to newtarget
|
||||
3) internal pad Y is linked to newtarget
|
||||
|
||||
(--------
|
||||
(- X --------) |
|
||||
| | |------)
|
||||
| target *------------->| sink |
|
||||
|------------| |------)
|
||||
| internal *--->// (--------
|
||||
(------------)
|
||||
(--------------
|
||||
(- X --------) |
|
||||
| | |------)
|
||||
| target *------------------> | sink |
|
||||
(------------) -------> |------)
|
||||
| / (--------------
|
||||
(- Y --------) / (pad link)
|
||||
//<-----* target |/
|
||||
(------------)
|
||||
|
||||
|
||||
* Setting target on an targetted unlinked ghostpad
|
||||
* Setting target on a targetted unlinked ghostpad
|
||||
|
||||
gst_ghost_pad_set_target (char *name, GstPad *newtarget)
|
||||
|
||||
(--------
|
||||
(- X --------) |
|
||||
| | |------)
|
||||
| target *------------->| sink |
|
||||
|------------| |------)
|
||||
| internal *--->// (--------
|
||||
(------------)
|
||||
(--------------
|
||||
(- X --------) |
|
||||
| | |-------)
|
||||
| target *------------------> | sink1 |
|
||||
(------------) -------> |-------)
|
||||
| / (--------------
|
||||
(- Y --------) / (pad link)
|
||||
//<-----* target |/
|
||||
(------------)
|
||||
|
||||
1) assert direction of newtarget == X direction
|
||||
2) target is set to newtarget
|
||||
|
||||
(--------
|
||||
(- X --------) |
|
||||
| | |------)
|
||||
| target *------------->| sink |
|
||||
|------------| |------)
|
||||
| internal *--->// (--------
|
||||
(------------)
|
||||
1) assert direction of newtarget (sink2) == X direction
|
||||
2) unlink internal pad Y and oldtarget
|
||||
3) target is set to newtarget (sink2)
|
||||
4) internal pad Y is linked to newtarget
|
||||
|
||||
(--------------
|
||||
(- X --------) |
|
||||
| | |-------)
|
||||
| target *------------------> | sink2 |
|
||||
(------------) -------> |-------)
|
||||
| / (--------------
|
||||
(- Y --------) / (pad link)
|
||||
//<-----* target |/
|
||||
(------------)
|
||||
|
||||
* Linking a pad to an untargetted ghostpad:
|
||||
|
||||
gst_pad_link (src, X)
|
||||
|
||||
|
||||
(- X --------)
|
||||
| |
|
||||
| target *------>//
|
||||
|------------|
|
||||
| internal *---->//
|
||||
(- X --------)
|
||||
| |
|
||||
| target *--------->//
|
||||
(------------)
|
||||
|
|
||||
(- Y --------)
|
||||
| target *----->//
|
||||
(------------)
|
||||
-------)
|
||||
|
|
||||
|
@ -148,28 +200,28 @@ Ghostpads
|
|||
(-----|
|
||||
-------)
|
||||
|
||||
X is a sink GstGhostPad without a target. The internal GstProxyPad Y has
|
||||
the same direction as the src pad (peer).
|
||||
|
||||
1) link function is called
|
||||
a) new GstProxyPad Y is created
|
||||
b) Y direction is same as peer
|
||||
c) Y target is set to peer
|
||||
d) X internal pad is set to Y (X is parent of Y)
|
||||
e) Y is activated in the same mode as X
|
||||
f) core makes link from src to X
|
||||
a) Y direction is same as @src
|
||||
b) Y target is set to @src
|
||||
c) Y is activated in the same mode as X
|
||||
d) core makes link from @src to X
|
||||
|
||||
|
||||
(- X --------)
|
||||
| |
|
||||
| target *----->//
|
||||
>|------------|
|
||||
(real pad link) / | internal * |
|
||||
/ (----------|-)
|
||||
/ |
|
||||
-------) / V
|
||||
| / (- Y ------)
|
||||
(-----|/ | |
|
||||
| src |<-------------* target |
|
||||
(-----| (----------)
|
||||
>(------------)
|
||||
(real pad link) / |
|
||||
/ (- Y ------)
|
||||
/ -----* target |
|
||||
-------) / / (----------)
|
||||
| / /
|
||||
(-----|/ /
|
||||
| src |<----
|
||||
(-----|
|
||||
-------)
|
||||
|
||||
|
||||
|
@ -177,39 +229,37 @@ Ghostpads
|
|||
|
||||
gst_pad_link (src, X)
|
||||
|
||||
(--------
|
||||
(- X --------) |
|
||||
| | |------)
|
||||
| target *------------->| sink |
|
||||
|------------| |------)
|
||||
| internal *--->// (--------
|
||||
(------------)
|
||||
-------)
|
||||
|
|
||||
(-----|
|
||||
| src |
|
||||
(-----|
|
||||
-------)
|
||||
(--------
|
||||
(- X --------) |
|
||||
| | |------)
|
||||
| target *------------->| sink |
|
||||
(------------) >|------)
|
||||
| / (--------
|
||||
| /
|
||||
| /
|
||||
-------) | / (real pad link)
|
||||
| (- Y ------) /
|
||||
(-----| | |/
|
||||
| src | //<----* target |
|
||||
(-----| (----------)
|
||||
-------)
|
||||
|
||||
|
||||
1) link function is called
|
||||
a) new GstProxyPad Y is created
|
||||
b) Y direction is same as peer
|
||||
c) Y target is set to peer
|
||||
d) X internal pad is set to Y (X is parent of Y)
|
||||
e) link is made from Y to X target (sink)
|
||||
f) Y is activated in the same mode as X
|
||||
g) core makes link from src to X
|
||||
a) Y direction is same as @src
|
||||
b) Y target is set to @src
|
||||
c) Y is activated in the same mode as X
|
||||
d) core makes link from @src to X
|
||||
|
||||
(--------
|
||||
(- X --------) |
|
||||
| | |------)
|
||||
| target *------------->| sink |
|
||||
>|------------| >|------)
|
||||
(real pad link) / | internal * | / (--------
|
||||
/ (----------|-) /
|
||||
>(------------) >|------)
|
||||
(real pad link) / | / (--------
|
||||
/ | /
|
||||
/ | /
|
||||
-------) / V / (real pad link)
|
||||
-------) / | / (real pad link)
|
||||
| / (- Y ------) /
|
||||
(-----|/ | |/
|
||||
| src |<-------------* target |
|
||||
|
@ -224,74 +274,70 @@ Ghostpads
|
|||
|
||||
(- X --------)
|
||||
| |
|
||||
| target *----->//
|
||||
>|------------|
|
||||
(real pad link) / | internal * |
|
||||
/ (----------|-)
|
||||
| target *------>//
|
||||
>(------------)
|
||||
(real pad link) / |
|
||||
/ |
|
||||
/ |
|
||||
-------) / V
|
||||
-------) / |
|
||||
| / (- Y ------)
|
||||
(-----|/ | |
|
||||
| src |<-------------* target |
|
||||
(-----| (----------)
|
||||
-------)
|
||||
|
||||
1) assert direction of newtarget == X direction
|
||||
2) X target is set to newtarget
|
||||
3) Y (X internal) is linked to newtarget
|
||||
|
||||
1) assert direction of @newtarget == X direction
|
||||
2) X target is set to @newtarget
|
||||
3) Y is linked to @newtarget
|
||||
|
||||
(--------
|
||||
(- X --------) |
|
||||
| | |------)
|
||||
| target *------------->| sink |
|
||||
>|------------| >|------)
|
||||
(real pad link) / | internal * | / (--------
|
||||
/ (----------|-) /
|
||||
>(------------) >|------)
|
||||
(real pad link) / | / (--------
|
||||
/ | /
|
||||
/ | /
|
||||
-------) / V / (real pad link)
|
||||
-------) / | / (real pad link)
|
||||
| / (- Y ------) /
|
||||
(-----|/ | |/
|
||||
| src |<-------------* target |
|
||||
(-----| (----------)
|
||||
-------)
|
||||
|
||||
|
||||
* Setting target on targetted linked ghostpad:
|
||||
|
||||
gst_ghost_pad_set_target (char *name, GstPad *newtarget)
|
||||
|
||||
|
||||
(--------
|
||||
(- X --------) |
|
||||
| | |------)
|
||||
| target *------------->| sink |
|
||||
>|------------| >|------)
|
||||
(real pad link) / | internal * | / (--------
|
||||
/ (----------|-) /
|
||||
| | |-------)
|
||||
| target *------------->| sink1 |
|
||||
>(------------) >|-------)
|
||||
(real pad link) / | / (--------
|
||||
/ | /
|
||||
/ | /
|
||||
-------) / V / (real pad link)
|
||||
-------) / | / (real pad link)
|
||||
| / (- Y ------) /
|
||||
(-----|/ | |/
|
||||
| src |<-------------* target |
|
||||
(-----| (----------)
|
||||
-------)
|
||||
|
||||
1) assert direction of newtarget == X direction
|
||||
1) assert direction of @newtarget == X direction
|
||||
2) Y and X target are unlinked
|
||||
2) X target is set to newtarget
|
||||
3) Y (X internal) is linked to newtarget
|
||||
|
||||
2) X target is set to @newtarget
|
||||
3) Y is linked to @newtarget
|
||||
|
||||
(--------
|
||||
(- X --------) |
|
||||
| | |------)
|
||||
| target *------------->| sink |
|
||||
>|------------| >|------)
|
||||
(real pad link) / | internal * | / (--------
|
||||
/ (----------|-) /
|
||||
| | |-------)
|
||||
| target *------------->| sink2 |
|
||||
>(------------) >|-------)
|
||||
(real pad link) / | / (--------
|
||||
/ | /
|
||||
/ | /
|
||||
-------) / V / (real pad link)
|
||||
-------) / | / (real pad link)
|
||||
| / (- Y ------) /
|
||||
(-----|/ | |/
|
||||
| src |<-------------* target |
|
||||
|
|
|
@ -58,7 +58,6 @@
|
|||
#define GST_PROXY_PAD_TARGET(pad) (GST_PROXY_PAD (pad)->target)
|
||||
#define GST_PROXY_PAD_INTERNAL(pad) (GST_PROXY_PAD (pad)->internal)
|
||||
|
||||
|
||||
typedef struct _GstProxyPad GstProxyPad;
|
||||
typedef struct _GstProxyPadClass GstProxyPadClass;
|
||||
|
||||
|
@ -136,8 +135,6 @@ gst_proxy_pad_do_event (GstPad * pad, GstEvent * event)
|
|||
gboolean res = FALSE;
|
||||
GstPad *internal = gst_proxy_pad_get_internal (pad);
|
||||
|
||||
g_return_val_if_fail (internal != NULL, FALSE);
|
||||
|
||||
res = gst_pad_push_event (internal, event);
|
||||
gst_object_unref (internal);
|
||||
|
||||
|
@ -161,8 +158,8 @@ gst_proxy_pad_do_query (GstPad * pad, GstQuery * query)
|
|||
static GList *
|
||||
gst_proxy_pad_do_internal_link (GstPad * pad)
|
||||
{
|
||||
GstPad *target = gst_proxy_pad_get_target (pad);
|
||||
GList *res = NULL;
|
||||
GstPad *target = gst_proxy_pad_get_target (pad);
|
||||
|
||||
if (target) {
|
||||
res = gst_pad_get_internal_links (target);
|
||||
|
@ -179,8 +176,6 @@ gst_proxy_pad_do_bufferalloc (GstPad * pad, guint64 offset, guint size,
|
|||
GstFlowReturn result;
|
||||
GstPad *internal = gst_proxy_pad_get_internal (pad);
|
||||
|
||||
g_return_val_if_fail (internal != NULL, GST_FLOW_NOT_LINKED);
|
||||
|
||||
result = gst_pad_alloc_buffer (internal, offset, size, caps, buf);
|
||||
gst_object_unref (internal);
|
||||
|
||||
|
@ -193,8 +188,6 @@ gst_proxy_pad_do_chain (GstPad * pad, GstBuffer * buffer)
|
|||
GstPad *internal = gst_proxy_pad_get_internal (pad);
|
||||
GstFlowReturn res;
|
||||
|
||||
g_return_val_if_fail (internal != NULL, GST_FLOW_NOT_LINKED);
|
||||
|
||||
res = gst_pad_push (internal, buffer);
|
||||
gst_object_unref (internal);
|
||||
|
||||
|
@ -208,8 +201,6 @@ gst_proxy_pad_do_getrange (GstPad * pad, guint64 offset, guint size,
|
|||
GstPad *internal = gst_proxy_pad_get_internal (pad);
|
||||
GstFlowReturn res;
|
||||
|
||||
g_return_val_if_fail (internal != NULL, GST_FLOW_NOT_LINKED);
|
||||
|
||||
res = gst_pad_pull_range (internal, offset, size, buffer);
|
||||
gst_object_unref (internal);
|
||||
|
||||
|
@ -222,8 +213,6 @@ gst_proxy_pad_do_checkgetrange (GstPad * pad)
|
|||
gboolean result;
|
||||
GstPad *internal = gst_proxy_pad_get_internal (pad);
|
||||
|
||||
g_return_val_if_fail (internal != NULL, FALSE);
|
||||
|
||||
result = gst_pad_check_pull_range (internal);
|
||||
gst_object_unref (internal);
|
||||
|
||||
|
@ -332,6 +321,7 @@ gst_proxy_pad_set_target_unlocked (GstPad * pad, GstPad * target)
|
|||
|
||||
return TRUE;
|
||||
|
||||
/* ERRORS */
|
||||
wrong_direction:
|
||||
{
|
||||
GST_ERROR_OBJECT (pad,
|
||||
|
@ -422,6 +412,7 @@ gst_proxy_pad_init (GstProxyPad * ppad)
|
|||
gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_query));
|
||||
gst_pad_set_internal_link_function (pad,
|
||||
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_internal_link));
|
||||
|
||||
gst_pad_set_getcaps_function (pad,
|
||||
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getcaps));
|
||||
gst_pad_set_acceptcaps_function (pad,
|
||||
|
@ -430,7 +421,6 @@ gst_proxy_pad_init (GstProxyPad * ppad)
|
|||
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_fixatecaps));
|
||||
gst_pad_set_setcaps_function (pad,
|
||||
GST_DEBUG_FUNCPTR (gst_proxy_pad_do_setcaps));
|
||||
|
||||
}
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
|
@ -510,33 +500,57 @@ gst_critical (const gchar * format, ...)
|
|||
* _ the internal and target are unlinked as soon as the GhostPad is removed
|
||||
* from it's parent.
|
||||
*/
|
||||
|
||||
static void
|
||||
gst_ghost_pad_parent_set (GstObject * object, GstObject * parent)
|
||||
{
|
||||
GstPad *gpad = GST_PAD (object);
|
||||
GstPad *target = gst_proxy_pad_get_target (gpad);
|
||||
GstPad *internal = gst_proxy_pad_get_internal (gpad);
|
||||
GstPad *gpad;
|
||||
GstPad *target;
|
||||
GstPad *internal;
|
||||
GstPadLinkReturn ret;
|
||||
|
||||
gpad = GST_PAD (object);
|
||||
|
||||
/* internal is never NULL */
|
||||
internal = gst_proxy_pad_get_internal (gpad);
|
||||
target = gst_proxy_pad_get_target (gpad);
|
||||
|
||||
if (target) {
|
||||
if (GST_PAD_IS_SRC (internal))
|
||||
gst_pad_link (internal, target);
|
||||
ret = gst_pad_link (internal, target);
|
||||
else
|
||||
gst_pad_link (target, internal);
|
||||
ret = gst_pad_link (target, internal);
|
||||
gst_object_unref (target);
|
||||
|
||||
if (ret != GST_PAD_LINK_OK)
|
||||
goto link_failed;
|
||||
}
|
||||
gst_object_unref (internal);
|
||||
|
||||
if (GST_OBJECT_CLASS (gst_ghost_pad_parent_class)->parent_set)
|
||||
GST_OBJECT_CLASS (gst_ghost_pad_parent_class)->parent_set (object, parent);
|
||||
|
||||
return;
|
||||
|
||||
/* ERRORS */
|
||||
link_failed:
|
||||
{
|
||||
/* a warning is all we can do */
|
||||
gst_object_unref (internal);
|
||||
g_warning ("could not link internal ghostpad");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_ghost_pad_parent_unset (GstObject * object, GstObject * parent)
|
||||
{
|
||||
GstPad *gpad = GST_PAD (object);
|
||||
GstPad *target = gst_proxy_pad_get_target (gpad);
|
||||
GstPad *internal = gst_proxy_pad_get_internal (gpad);
|
||||
GstPad *gpad;
|
||||
GstPad *target;
|
||||
GstPad *internal;
|
||||
|
||||
gpad = GST_PAD (object);
|
||||
internal = gst_proxy_pad_get_internal (gpad);
|
||||
target = gst_proxy_pad_get_target (gpad);
|
||||
|
||||
if (target) {
|
||||
if (GST_PAD_IS_SRC (internal))
|
||||
|
@ -570,29 +584,18 @@ static gboolean
|
|||
gst_ghost_pad_internal_do_activate_push (GstPad * pad, gboolean active)
|
||||
{
|
||||
gboolean ret;
|
||||
GstPad *other;
|
||||
|
||||
if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
|
||||
GstPad *parent = gst_proxy_pad_get_internal (pad);
|
||||
if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK)
|
||||
other = gst_proxy_pad_get_internal (pad);
|
||||
else
|
||||
other = gst_pad_get_peer (pad);
|
||||
|
||||
if (parent) {
|
||||
g_return_val_if_fail (GST_IS_GHOST_PAD (parent), FALSE);
|
||||
|
||||
ret = gst_pad_activate_push (parent, active);
|
||||
|
||||
gst_object_unref (parent);
|
||||
} else {
|
||||
ret = FALSE;
|
||||
}
|
||||
} else {
|
||||
GstPad *peer = gst_pad_get_peer (pad);
|
||||
|
||||
if (peer) {
|
||||
ret = gst_pad_activate_push (peer, active);
|
||||
gst_object_unref (peer);
|
||||
} else {
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
if (G_LIKELY (other)) {
|
||||
ret = gst_pad_activate_push (other, active);
|
||||
gst_object_unref (other);
|
||||
} else
|
||||
ret = FALSE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -601,29 +604,18 @@ static gboolean
|
|||
gst_ghost_pad_internal_do_activate_pull (GstPad * pad, gboolean active)
|
||||
{
|
||||
gboolean ret;
|
||||
GstPad *other;
|
||||
|
||||
if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
|
||||
GstPad *peer = gst_pad_get_peer (pad);
|
||||
if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK)
|
||||
other = gst_pad_get_peer (pad);
|
||||
else
|
||||
other = gst_proxy_pad_get_internal (pad);
|
||||
|
||||
if (peer) {
|
||||
ret = gst_pad_activate_pull (peer, active);
|
||||
gst_object_unref (peer);
|
||||
} else {
|
||||
ret = FALSE;
|
||||
}
|
||||
} else {
|
||||
GstPad *parent = gst_proxy_pad_get_internal (pad);
|
||||
|
||||
if (parent) {
|
||||
g_return_val_if_fail (GST_IS_GHOST_PAD (parent), FALSE);
|
||||
|
||||
ret = gst_pad_activate_pull (parent, active);
|
||||
|
||||
gst_object_unref (parent);
|
||||
} else {
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
if (G_LIKELY (other)) {
|
||||
ret = gst_pad_activate_pull (other, active);
|
||||
gst_object_unref (other);
|
||||
} else
|
||||
ret = FALSE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -633,19 +625,16 @@ gst_ghost_pad_do_activate_push (GstPad * pad, gboolean active)
|
|||
{
|
||||
gboolean ret;
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
|
||||
GstPad *internal = gst_proxy_pad_get_internal (pad);
|
||||
|
||||
if (internal) {
|
||||
ret = gst_pad_activate_push (internal, active);
|
||||
gst_object_unref (internal);
|
||||
} else {
|
||||
ret = TRUE;
|
||||
}
|
||||
} else {
|
||||
ret = TRUE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -653,26 +642,18 @@ static gboolean
|
|||
gst_ghost_pad_do_activate_pull (GstPad * pad, gboolean active)
|
||||
{
|
||||
gboolean ret;
|
||||
GstPad *other;
|
||||
|
||||
if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
|
||||
GstPad *peer = gst_pad_get_peer (pad);
|
||||
if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK)
|
||||
other = gst_pad_get_peer (pad);
|
||||
else
|
||||
other = gst_proxy_pad_get_internal (pad);
|
||||
|
||||
if (peer) {
|
||||
ret = gst_pad_activate_pull (peer, active);
|
||||
gst_object_unref (peer);
|
||||
} else {
|
||||
ret = FALSE;
|
||||
}
|
||||
} else {
|
||||
GstPad *internal = gst_proxy_pad_get_internal (pad);
|
||||
|
||||
if (internal) {
|
||||
ret = gst_pad_activate_pull (internal, active);
|
||||
gst_object_unref (internal);
|
||||
} else {
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
if (G_LIKELY (other)) {
|
||||
ret = gst_pad_activate_pull (other, active);
|
||||
gst_object_unref (other);
|
||||
} else
|
||||
ret = FALSE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -680,44 +661,55 @@ gst_ghost_pad_do_activate_pull (GstPad * pad, gboolean active)
|
|||
static GstPadLinkReturn
|
||||
gst_ghost_pad_do_link (GstPad * pad, GstPad * peer)
|
||||
{
|
||||
GstPad *internal, *target;
|
||||
GstPadLinkReturn ret = GST_PAD_LINK_OK;
|
||||
GstPadLinkReturn ret;
|
||||
GstPad *internal;
|
||||
|
||||
target = gst_proxy_pad_get_target (pad);
|
||||
g_return_val_if_fail (target != NULL, GST_PAD_LINK_NOSCHED);
|
||||
ret = GST_PAD_LINK_OK;
|
||||
|
||||
internal = gst_proxy_pad_get_internal (pad);
|
||||
gst_proxy_pad_set_target (internal, peer);
|
||||
if (!gst_proxy_pad_set_target (internal, peer))
|
||||
goto failed;
|
||||
|
||||
/* if we are a source pad, we should call the peer link function
|
||||
* if the peer has one */
|
||||
if (GST_PAD_IS_SRC (pad)) {
|
||||
if (GST_PAD_LINKFUNC (peer) && ret == GST_PAD_LINK_OK)
|
||||
if (GST_PAD_LINKFUNC (peer))
|
||||
ret = GST_PAD_LINKFUNC (peer) (peer, pad);
|
||||
}
|
||||
|
||||
gst_object_unref (target);
|
||||
done:
|
||||
gst_object_unref (internal);
|
||||
|
||||
return ret;
|
||||
|
||||
/* ERRORS */
|
||||
failed:
|
||||
{
|
||||
ret = GST_PAD_LINK_REFUSED;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_ghost_pad_do_unlink (GstPad * pad)
|
||||
{
|
||||
GstPad *target = gst_proxy_pad_get_target (pad);
|
||||
GstPad *internal = gst_proxy_pad_get_internal (pad);
|
||||
GstPad *target;
|
||||
GstPad *internal;
|
||||
|
||||
target = gst_proxy_pad_get_target (pad);
|
||||
internal = gst_proxy_pad_get_internal (pad);
|
||||
|
||||
GST_DEBUG_OBJECT (pad, "unlinking ghostpad");
|
||||
|
||||
/* The target of the internal pad is no longer valid */
|
||||
gst_proxy_pad_set_target (internal, NULL);
|
||||
|
||||
if (target && target->unlinkfunc)
|
||||
target->unlinkfunc (target);
|
||||
if (target) {
|
||||
if (GST_PAD_UNLINKFUNC (target))
|
||||
GST_PAD_UNLINKFUNC (target) (target);
|
||||
|
||||
if (target)
|
||||
gst_object_unref (target);
|
||||
}
|
||||
|
||||
gst_object_unref (internal);
|
||||
}
|
||||
|
||||
|
@ -771,9 +763,9 @@ gst_ghost_pad_dispose (GObject * object)
|
|||
}
|
||||
|
||||
GST_PROXY_PAD_INTERNAL (internal) = NULL;
|
||||
/*
|
||||
disposes of the internal pad, since the ghostpad is the only possible object
|
||||
that has a refcount on the internal pad.
|
||||
|
||||
/* disposes of the internal pad, since the ghostpad is the only possible object
|
||||
* that has a refcount on the internal pad.
|
||||
*/
|
||||
gst_object_unparent (GST_OBJECT_CAST (internal));
|
||||
|
||||
|
@ -819,7 +811,6 @@ gst_ghost_pad_new_full (const gchar * name, GstPadDirection dir,
|
|||
|
||||
|
||||
/* INTERNAL PAD */
|
||||
|
||||
internal =
|
||||
g_object_new (GST_TYPE_PROXY_PAD, "name", NULL,
|
||||
"direction", (dir == GST_PAD_SRC) ? GST_PAD_SINK : GST_PAD_SRC, NULL);
|
||||
|
@ -840,37 +831,45 @@ gst_ghost_pad_new_full (const gchar * name, GstPadDirection dir,
|
|||
GST_PROXY_LOCK (ret);
|
||||
|
||||
if (!gst_object_set_parent (GST_OBJECT_CAST (internal),
|
||||
GST_OBJECT_CAST (ret))) {
|
||||
gst_critical ("Could not set internal pad%" GST_PTR_FORMAT, internal);
|
||||
goto beach;
|
||||
}
|
||||
GST_OBJECT_CAST (ret)))
|
||||
goto parent_failed;
|
||||
|
||||
/*
|
||||
The ghostpad is the parent of the internal pad and is the only object that
|
||||
can have a refcount on the internal pad.
|
||||
At this point, the GstGhostPad has a refcount of 1, and the internal pad has
|
||||
a refcount of 1.
|
||||
When the refcount of the GstGhostPad drops to 0, the ghostpad will dispose
|
||||
it's refcount on the internal pad in the dispose method by un-parenting it.
|
||||
This is why we don't take extra refcounts in the assignments below
|
||||
/* The ghostpad is the parent of the internal pad and is the only object that
|
||||
* can have a refcount on the internal pad.
|
||||
* At this point, the GstGhostPad has a refcount of 1, and the internal pad has
|
||||
* a refcount of 1.
|
||||
* When the refcount of the GstGhostPad drops to 0, the ghostpad will dispose
|
||||
* it's refcount on the internal pad in the dispose method by un-parenting it.
|
||||
* This is why we don't take extra refcounts in the assignments below
|
||||
*/
|
||||
GST_PROXY_PAD_INTERNAL (ret) = internal;
|
||||
GST_PROXY_PAD_INTERNAL (internal) = GST_PAD (ret);
|
||||
GST_PROXY_PAD_INTERNAL (internal) = ret;
|
||||
|
||||
/* could be more general here, iterating over all writable properties...
|
||||
* taking the short road for now tho */
|
||||
GST_GHOST_PAD (ret)->notify_id = g_signal_connect (internal, "notify::caps",
|
||||
G_CALLBACK (on_int_notify), ret);
|
||||
on_int_notify (internal, NULL, GST_GHOST_PAD (ret));
|
||||
GST_GHOST_PAD_CAST (ret)->notify_id =
|
||||
g_signal_connect (internal, "notify::caps", G_CALLBACK (on_int_notify),
|
||||
ret);
|
||||
/* call function to init values */
|
||||
on_int_notify (internal, NULL, GST_GHOST_PAD_CAST (ret));
|
||||
|
||||
gst_pad_set_activatepull_function (GST_PAD (internal),
|
||||
GST_DEBUG_FUNCPTR (gst_ghost_pad_internal_do_activate_pull));
|
||||
gst_pad_set_activatepush_function (GST_PAD (internal),
|
||||
GST_DEBUG_FUNCPTR (gst_ghost_pad_internal_do_activate_push));
|
||||
|
||||
beach:
|
||||
GST_PROXY_UNLOCK (ret);
|
||||
|
||||
return ret;
|
||||
|
||||
/* ERRORS */
|
||||
parent_failed:
|
||||
{
|
||||
gst_critical ("Could not set internal pad %" GST_PTR_FORMAT, internal);
|
||||
GST_PROXY_UNLOCK (ret);
|
||||
gst_object_unref (ret);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -979,13 +978,12 @@ set_target_failed:
|
|||
* @templ: the #GstPadTemplate to create the ghostpad from.
|
||||
*
|
||||
* Create a new ghostpad based on @templ, without setting a target. The
|
||||
* direction will be taken from @templ.
|
||||
* direction will be taken from the @templ.
|
||||
*
|
||||
* Returns: a new #GstPad, or NULL in case of an error.
|
||||
*
|
||||
* Since: 0.10.10
|
||||
*/
|
||||
|
||||
GstPad *
|
||||
gst_ghost_pad_new_no_target_from_template (const gchar * name,
|
||||
GstPadTemplate * templ)
|
||||
|
@ -1034,11 +1032,12 @@ gst_ghost_pad_set_target (GstGhostPad * gpad, GstPad * newtarget)
|
|||
GstPad *oldtarget;
|
||||
GstObject *parent;
|
||||
gboolean result;
|
||||
GstPadLinkReturn lret;
|
||||
|
||||
g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE);
|
||||
|
||||
GST_PROXY_LOCK (gpad);
|
||||
internal = GST_PROXY_PAD_INTERNAL (GST_PAD (gpad));
|
||||
internal = GST_PROXY_PAD_INTERNAL (GST_PAD_CAST (gpad));
|
||||
|
||||
GST_DEBUG_OBJECT (gpad, "set target %s:%s", GST_DEBUG_PAD_NAME (newtarget));
|
||||
|
||||
|
@ -1059,9 +1058,13 @@ gst_ghost_pad_set_target (GstGhostPad * gpad, GstPad * newtarget)
|
|||
/* and link to internal pad if we are not unparent-ed */
|
||||
if ((parent = gst_object_get_parent (GST_OBJECT (gpad)))) {
|
||||
if (GST_PAD_IS_SRC (internal))
|
||||
result = gst_pad_link (internal, newtarget);
|
||||
lret = gst_pad_link (internal, newtarget);
|
||||
else
|
||||
result = gst_pad_link (newtarget, internal);
|
||||
lret = gst_pad_link (newtarget, internal);
|
||||
|
||||
/* FIXME, do something with lret, possibly checking the return value and
|
||||
* undoing the set_target operation if it failed */
|
||||
|
||||
gst_object_unref (parent);
|
||||
} else {
|
||||
/* we need to connect the internal pad once we have a parent */
|
||||
|
|
|
@ -148,17 +148,26 @@ GST_START_TEST (test_remove2)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
#if 0
|
||||
/* test if a ghost pad without a target can be linked
|
||||
* It can't because it has incompatible caps...
|
||||
/* test if a ghost pad without a target can be linked and
|
||||
* unlinked. An untargeted ghostpad has a default ANY caps unless there
|
||||
* is a padtemplate that says something else.
|
||||
*/
|
||||
GST_START_TEST (test_ghost_pad_notarget)
|
||||
GST_START_TEST (test_ghost_pads_notarget)
|
||||
{
|
||||
GstElement *b1, *b2, *sink;
|
||||
GstPad *srcpad, *sinkpad;
|
||||
GstPad *srcpad, *sinkpad, *peer;
|
||||
GstPadLinkReturn ret;
|
||||
gboolean bret;
|
||||
GstBus *bus;
|
||||
GstCaps *caps;
|
||||
|
||||
b1 = gst_element_factory_make ("pipeline", NULL);
|
||||
|
||||
/* make sure all messages are discarded */
|
||||
bus = gst_pipeline_get_bus (GST_PIPELINE (b1));
|
||||
gst_bus_set_flushing (bus, TRUE);
|
||||
gst_object_unref (bus);
|
||||
|
||||
b2 = gst_element_factory_make ("bin", NULL);
|
||||
sink = gst_element_factory_make ("fakesink", NULL);
|
||||
|
||||
|
@ -172,10 +181,33 @@ GST_START_TEST (test_ghost_pad_notarget)
|
|||
|
||||
ret = gst_pad_link (srcpad, sinkpad);
|
||||
fail_unless (ret == GST_PAD_LINK_OK);
|
||||
|
||||
/* check if the peers are ok */
|
||||
peer = gst_pad_get_peer (srcpad);
|
||||
fail_unless (peer == sinkpad);
|
||||
gst_object_unref (peer);
|
||||
|
||||
peer = gst_pad_get_peer (sinkpad);
|
||||
fail_unless (peer == srcpad);
|
||||
gst_object_unref (peer);
|
||||
|
||||
/* check caps, untargetted pad should return ANY or the padtemplate caps
|
||||
* when it was created from a template */
|
||||
caps = gst_pad_get_caps (srcpad);
|
||||
fail_unless (gst_caps_is_any (caps));
|
||||
gst_caps_unref (caps);
|
||||
|
||||
/* unlink */
|
||||
bret = gst_pad_unlink (srcpad, sinkpad);
|
||||
fail_unless (bret == TRUE);
|
||||
|
||||
/* cleanup */
|
||||
gst_object_unref (srcpad);
|
||||
gst_object_unref (sinkpad);
|
||||
gst_object_unref (b1);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
#endif
|
||||
|
||||
/* test if linking fails over different bins using a pipeline
|
||||
* like this:
|
||||
|
@ -225,6 +257,10 @@ GST_START_TEST (test_link)
|
|||
gst_element_set_state (b1, GST_STATE_READY);
|
||||
gst_element_set_state (b1, GST_STATE_NULL);
|
||||
ASSERT_OBJECT_REFCOUNT (b1, "pipeline", 1);
|
||||
|
||||
gst_object_unref (srcpad);
|
||||
gst_object_unref (sinkpad);
|
||||
gst_object_unref (b1);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
@ -345,8 +381,8 @@ GST_START_TEST (test_ghost_pads_bin)
|
|||
GstBin *sinkbin;
|
||||
GstElement *src;
|
||||
GstElement *sink;
|
||||
GstPad *srcghost;
|
||||
GstPad *sinkghost;
|
||||
GstPad *srcpad, *srcghost, *target;
|
||||
GstPad *sinkpad, *sinkghost;
|
||||
|
||||
pipeline = GST_BIN (gst_pipeline_new ("pipe"));
|
||||
ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
|
||||
|
@ -361,27 +397,35 @@ GST_START_TEST (test_ghost_pads_bin)
|
|||
|
||||
src = gst_element_factory_make ("fakesrc", "src");
|
||||
gst_bin_add (srcbin, src);
|
||||
srcghost = gst_ghost_pad_new ("src", gst_element_get_pad (src, "src"));
|
||||
srcpad = gst_element_get_pad (src, "src");
|
||||
srcghost = gst_ghost_pad_new ("src", srcpad);
|
||||
gst_object_unref (srcpad);
|
||||
gst_element_add_pad (GST_ELEMENT (srcbin), srcghost);
|
||||
|
||||
sink = gst_element_factory_make ("fakesink", "sink");
|
||||
gst_bin_add (sinkbin, sink);
|
||||
sinkghost = gst_ghost_pad_new ("sink", gst_element_get_pad (sink, "sink"));
|
||||
sinkpad = gst_element_get_pad (sink, "sink");
|
||||
sinkghost = gst_ghost_pad_new ("sink", sinkpad);
|
||||
gst_object_unref (sinkpad);
|
||||
gst_element_add_pad (GST_ELEMENT (sinkbin), sinkghost);
|
||||
|
||||
gst_element_link (GST_ELEMENT (srcbin), GST_ELEMENT (sinkbin));
|
||||
|
||||
fail_unless (GST_PAD_PEER (srcghost) != NULL);
|
||||
fail_unless (GST_PAD_PEER (sinkghost) != NULL);
|
||||
fail_unless (GST_PAD_PEER (gst_ghost_pad_get_target (GST_GHOST_PAD
|
||||
(srcghost))) != NULL);
|
||||
fail_unless (GST_PAD_PEER (gst_ghost_pad_get_target (GST_GHOST_PAD
|
||||
(sinkghost))) != NULL);
|
||||
target = gst_ghost_pad_get_target (GST_GHOST_PAD (srcghost));
|
||||
fail_unless (GST_PAD_PEER (target) != NULL);
|
||||
gst_object_unref (target);
|
||||
target = gst_ghost_pad_get_target (GST_GHOST_PAD (sinkghost));
|
||||
fail_unless (GST_PAD_PEER (target) != NULL);
|
||||
gst_object_unref (target);
|
||||
|
||||
/* flush the message, dropping the b1 refcount to 1 */
|
||||
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY);
|
||||
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
|
||||
ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
|
||||
|
||||
gst_object_unref (pipeline);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
@ -437,6 +481,9 @@ GST_START_TEST (test_ghost_pads_block)
|
|||
|
||||
g_mutex_free (block_data.mutex);
|
||||
g_cond_free (block_data.cond);
|
||||
|
||||
ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
|
||||
gst_object_unref (pipeline);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
@ -475,6 +522,9 @@ GST_START_TEST (test_ghost_pads_probes)
|
|||
|
||||
g_mutex_free (block_data.mutex);
|
||||
g_cond_free (block_data.cond);
|
||||
|
||||
ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
|
||||
gst_object_unref (pipeline);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
@ -569,7 +619,7 @@ gst_ghost_pad_suite (void)
|
|||
tcase_add_test (tc_chain, test_link);
|
||||
tcase_add_test (tc_chain, test_ghost_pads);
|
||||
tcase_add_test (tc_chain, test_ghost_pads_bin);
|
||||
/* tcase_add_test (tc_chain, test_ghost_pad_notarget); */
|
||||
tcase_add_test (tc_chain, test_ghost_pads_notarget);
|
||||
tcase_add_test (tc_chain, test_ghost_pads_block);
|
||||
tcase_add_test (tc_chain, test_ghost_pads_probes);
|
||||
tcase_add_test (tc_chain, test_ghost_pads_new_from_template);
|
||||
|
|
Loading…
Reference in a new issue