mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 11:41:09 +00:00
gst/gstelement.c (gst_element_dispose): Protect against multiple invocations.
Original commit message from CVS: 2004-02-24 Andy Wingo <wingo@pobox.com> * gst/gstelement.c (gst_element_dispose): Protect against multiple invocations. * gst/schedulers/gstoptimalscheduler.c I added a mess of prototypes at the top of the file by way of documentation. Some of the operations on chains and groups were re-organized. (create_group): Added a type argument so if the group is enabled, the setup_group_scheduler knows what to do. (group_elements): Added a type argument here, too, to be passed on to create_group. (group_element_set_enabled): If an unlinked PLAYING element is added to a bin, we have to create a new group to hold the element, and this function will be called before the group is added to the chain. Thus we have a valid case for group->chain==NULL. Instead of calling chain_group_set_enabled, just set the flag on the group (the chain's status will be set when the group is added to it). (gst_opt_scheduler_state_transition, chain_group_set_enabled): Setup the group scheduler when the group is enabled, not specifically when an element goes PAUSED->PLAYING. This means PLAYING elements can be added, linked, and scheduled into a PLAYING pipeline, as was intended. (add_to_group): Don't ref the group twice. I don't know when this double-ref got in here. Removing it has the potential to cause segfaults if other parts of the scheduler are buggy. If you find that the scheduler is segfaulting for you, put in an extra ref here and see if that hacks over the underlying issue. Of course, then find out what code is unreffing a group it doesn't own... (create_group): Make the extra refcount floating, and remove it after adding the element. This means that... (unref_group): Destroy when the refcount reaches 0, not 1, like every other refcounted object in the known universe. (remove_from_group): When a group becomes empty, set it to be not active, and remove it from its chain. Don't unref it again, there's no floating reference any more. (destroy_group): We have to remove the group from the chain in remove_from_group (rather than here) to break refcounting cycles (the chain always has a ref on the group). So assert that group->chain==NULL. (ref_group_by_count): Removed, it was commented out anyway. (merge_chains): Use the remove_from_chain and add_to_chain primitives to do the reparenting, instead of rolling our own implementation. (add_to_chain): The first non-disabled group in the chain's group list will be the entry point for the chain. Because buffers can accumulate in loop elements' peer bufpens, we preferentially schedule loop groups before get groups to avoid unnecessary execution of get-based groups when the bufpens are already full. (gst_opt_scheduler_schedule_run_queue): Debug fixes. (get_group_schedule_function): Ditto. (loop_group_schedule_function): Ditto. (gst_opt_scheduler_loop_wrapper): Ditto. (gst_opt_scheduler_iterate): Ditto. I understand the opt scheduler now, yippee! * gst/gstpad.c: All throughout, added FIXMEs to look at for 0.9. (gst_pad_get_name, gst_pad_set_chain_function) (gst_pad_set_get_function, gst_pad_set_event_function) (gst_pad_set_event_mask_function, gst_pad_get_event_masks) (gst_pad_get_event_masks_default, gst_pad_set_convert_function) (gst_pad_set_query_function, gst_pad_get_query_types) (gst_pad_get_query_types_default) (gst_pad_set_internal_link_function) (gst_pad_set_formats_function, gst_pad_set_link_function) (gst_pad_set_fixate_function, gst_pad_set_getcaps_function) (gst_pad_set_bufferalloc_function, gst_pad_unlink) (gst_pad_renegotiate, gst_pad_set_parent, gst_pad_get_parent) (gst_pad_add_ghost_pad, gst_pad_proxy_getcaps) (gst_pad_proxy_pad_link, gst_pad_proxy_fixate) (gst_pad_get_pad_template_caps, gst_pad_check_compatibility) (gst_pad_get_peer, gst_pad_get_allowed_caps) (gst_pad_alloc_buffer, gst_pad_push, gst_pad_pull) (gst_pad_selectv, gst_pad_select, gst_pad_template_get_caps) (gst_pad_event_default_dispatch, gst_pad_event_default) (gst_pad_dispatcher, gst_pad_send_event, gst_pad_convert_default) (gst_pad_convert, gst_pad_query_default, gst_pad_query) (gst_pad_get_formats_default, gst_pad_get_formats): Better argument checks, and some doc fixes. (gst_pad_custom_new_from_template): Um, does anyone use these functions? Actually make a custom pad instead of a normal one. (gst_pad_try_set_caps): Transpose some checks. (gst_pad_try_set_caps_nonfixed): Same, and use a macro to check if the pad is in negotiation. (gst_pad_try_relink_filtered): Use pad_link_prepare. * gst/gstelement.c: Remove prototypes also defined in gstclock.h. * gst/gstelement.h: * gst/gstclock.h: Un-deprecate the old clocking API, as discussed on the list.
This commit is contained in:
parent
79f5d87041
commit
3f5a8814d5
8 changed files with 615 additions and 388 deletions
97
ChangeLog
97
ChangeLog
|
@ -1,3 +1,100 @@
|
|||
2004-02-24 Andy Wingo <wingo@pobox.com>
|
||||
|
||||
* gst/gstelement.c (gst_element_dispose): Protect against multiple
|
||||
invocations.
|
||||
|
||||
* gst/schedulers/gstoptimalscheduler.c
|
||||
I added a mess of prototypes at the top of the file by way of
|
||||
documentation. Some of the operations on chains and groups were
|
||||
re-organized.
|
||||
|
||||
(create_group): Added a type argument so if the group is enabled,
|
||||
the setup_group_scheduler knows what to do.
|
||||
(group_elements): Added a type argument here, too, to be passed on
|
||||
to create_group.
|
||||
(group_element_set_enabled): If an unlinked PLAYING element is
|
||||
added to a bin, we have to create a new group to hold the element,
|
||||
and this function will be called before the group is added to the
|
||||
chain. Thus we have a valid case for group->chain==NULL. Instead
|
||||
of calling chain_group_set_enabled, just set the flag on the group
|
||||
(the chain's status will be set when the group is added to it).
|
||||
(gst_opt_scheduler_state_transition, chain_group_set_enabled):
|
||||
Setup the group scheduler when the group is enabled, not
|
||||
specifically when an element goes PAUSED->PLAYING. This means
|
||||
PLAYING elements can be added, linked, and scheduled into a
|
||||
PLAYING pipeline, as was intended.
|
||||
(add_to_group): Don't ref the group twice. I don't know when this
|
||||
double-ref got in here. Removing it has the potential to cause
|
||||
segfaults if other parts of the scheduler are buggy. If you find
|
||||
that the scheduler is segfaulting for you, put in an extra ref
|
||||
here and see if that hacks over the underlying issue. Of course,
|
||||
then find out what code is unreffing a group it doesn't own...
|
||||
(create_group): Make the extra refcount floating, and remove it
|
||||
after adding the element. This means that...
|
||||
(unref_group): Destroy when the refcount reaches 0, not 1, like
|
||||
every other refcounted object in the known universe.
|
||||
(remove_from_group): When a group becomes empty, set it to be not
|
||||
active, and remove it from its chain. Don't unref it again,
|
||||
there's no floating reference any more.
|
||||
(destroy_group): We have to remove the group from the chain in
|
||||
remove_from_group (rather than here) to break refcounting cycles
|
||||
(the chain always has a ref on the group). So assert that
|
||||
group->chain==NULL.
|
||||
(ref_group_by_count): Removed, it was commented out anyway.
|
||||
(merge_chains): Use the remove_from_chain and add_to_chain
|
||||
primitives to do the reparenting, instead of rolling our own
|
||||
implementation.
|
||||
(add_to_chain): The first non-disabled group in the chain's group
|
||||
list will be the entry point for the chain. Because buffers can
|
||||
accumulate in loop elements' peer bufpens, we preferentially
|
||||
schedule loop groups before get groups to avoid unnecessary
|
||||
execution of get-based groups when the bufpens are already full.
|
||||
(gst_opt_scheduler_schedule_run_queue): Debug fixes.
|
||||
(get_group_schedule_function): Ditto.
|
||||
(loop_group_schedule_function): Ditto.
|
||||
(gst_opt_scheduler_loop_wrapper): Ditto.
|
||||
(gst_opt_scheduler_iterate): Ditto.
|
||||
|
||||
I understand the opt scheduler now, yippee!
|
||||
|
||||
* gst/gstpad.c: All throughout, added FIXMEs to look at for 0.9.
|
||||
(gst_pad_get_name, gst_pad_set_chain_function)
|
||||
(gst_pad_set_get_function, gst_pad_set_event_function)
|
||||
(gst_pad_set_event_mask_function, gst_pad_get_event_masks)
|
||||
(gst_pad_get_event_masks_default, gst_pad_set_convert_function)
|
||||
(gst_pad_set_query_function, gst_pad_get_query_types)
|
||||
(gst_pad_get_query_types_default)
|
||||
(gst_pad_set_internal_link_function)
|
||||
(gst_pad_set_formats_function, gst_pad_set_link_function)
|
||||
(gst_pad_set_fixate_function, gst_pad_set_getcaps_function)
|
||||
(gst_pad_set_bufferalloc_function, gst_pad_unlink)
|
||||
(gst_pad_renegotiate, gst_pad_set_parent, gst_pad_get_parent)
|
||||
(gst_pad_add_ghost_pad, gst_pad_proxy_getcaps)
|
||||
(gst_pad_proxy_pad_link, gst_pad_proxy_fixate)
|
||||
(gst_pad_get_pad_template_caps, gst_pad_check_compatibility)
|
||||
(gst_pad_get_peer, gst_pad_get_allowed_caps)
|
||||
(gst_pad_alloc_buffer, gst_pad_push, gst_pad_pull)
|
||||
(gst_pad_selectv, gst_pad_select, gst_pad_template_get_caps)
|
||||
(gst_pad_event_default_dispatch, gst_pad_event_default)
|
||||
(gst_pad_dispatcher, gst_pad_send_event, gst_pad_convert_default)
|
||||
(gst_pad_convert, gst_pad_query_default, gst_pad_query)
|
||||
(gst_pad_get_formats_default, gst_pad_get_formats): Better
|
||||
argument checks, and some doc fixes.
|
||||
|
||||
(gst_pad_custom_new_from_template): Um, does anyone
|
||||
use these functions? Actually make a custom pad instead of a
|
||||
normal one.
|
||||
(gst_pad_try_set_caps): Transpose some checks.
|
||||
(gst_pad_try_set_caps_nonfixed): Same, and use a macro to check if
|
||||
the pad is in negotiation.
|
||||
(gst_pad_try_relink_filtered): Use pad_link_prepare.
|
||||
|
||||
* gst/gstelement.c: Remove prototypes also defined in gstclock.h.
|
||||
|
||||
* gst/gstelement.h:
|
||||
* gst/gstclock.h: Un-deprecate the old clocking API, as discussed
|
||||
on the list.
|
||||
|
||||
2004-02-24 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
|
||||
* gst/gstbin.c: (gst_bin_add):
|
||||
|
|
|
@ -116,7 +116,7 @@ U gst-template/gst-app/src/Makefile.am
|
|||
<para>
|
||||
First we will examine the code you would be likely to place in a header
|
||||
file (although since the interface to the code is entirely defined by the
|
||||
pluging system, and doesn't depend on reading a header file, this is not
|
||||
plugin system, and doesn't depend on reading a header file, this is not
|
||||
crucial.)
|
||||
|
||||
The code here can be found in
|
||||
|
|
62
docs/random/wingo/without-factories
Normal file
62
docs/random/wingo/without-factories
Normal file
|
@ -0,0 +1,62 @@
|
|||
-*- outline -*-
|
||||
|
||||
* Creating Elements Without Factories
|
||||
|
||||
** The purpose of factories
|
||||
|
||||
On a typical GStreamer system, there are approximately 6.022*10^23
|
||||
plugins. GStreamer knows about all of them because of the registry. The
|
||||
goal is to avoid initializing each one of them, when maybe for your
|
||||
application you only need one or two.
|
||||
|
||||
The problem becomes, how do you create an instance of the plugin? The
|
||||
normal way to instantiate a class is via g_object_new (TYPE, ARGS...).
|
||||
In the case that the plugin isn't loaded, you don't know its type, and
|
||||
can't even get it from the type name.
|
||||
|
||||
Element factories exist to solve this problem by associating names (like
|
||||
"sinesrc" or "identity") with certain types that are provided by the
|
||||
plugin. Then when the user asks for "sinesrc", the appropriate plugin is
|
||||
loaded, its types are initialized, and then gst_element_factory_create
|
||||
creates the object for you.
|
||||
|
||||
** Why not factories?
|
||||
|
||||
To review, factories (1) allow plugins to remain unloaded if not
|
||||
necessary, and (2) make it easy to create elements.
|
||||
|
||||
If you are writing an application that has custom elements (as is the
|
||||
case with most serious applications), you will probably have the plugin
|
||||
loaded up already, and you will have access to the type of the element.
|
||||
To muck about creating a plugin for the app, registering the element
|
||||
with the plugin, and then creating it with the element factory API
|
||||
actually takes more work than the normal way.
|
||||
|
||||
** g_object_new
|
||||
|
||||
So you want to avoid factories. To create objects with a simple
|
||||
g_object_new call is our strategy. However, to preserve the same
|
||||
semantics as gst_element_factory_create, we need to know what else is
|
||||
needed to initialize a GStreamer element.
|
||||
|
||||
The other things that gst_element_factory_create does are as follows:
|
||||
|
||||
*** Sets the ->elementfactory member on the element class
|
||||
|
||||
Note that anything trying to get the factory won't work (e.g.
|
||||
gst_element_get_factory). Thankfully this is less of a problem after the
|
||||
0.7 plugin system changes.
|
||||
|
||||
*** Initializes the name of the element
|
||||
|
||||
To do this ourselves, we either call gst_object_set_name, or when we
|
||||
set the "name" property when creating the object.
|
||||
|
||||
** Summary
|
||||
|
||||
To create a GStreamer element when you know the type, you can just use
|
||||
|
||||
g_object_new (get_type_of_my_element (),
|
||||
"name", the_name_you_want_possibly_null,
|
||||
... any other properties ...
|
||||
NULL);
|
|
@ -163,27 +163,21 @@ struct _GstClockClass {
|
|||
|
||||
GType gst_clock_get_type (void);
|
||||
|
||||
#ifndef GST_DISABLE_DEPRECATED
|
||||
gdouble gst_clock_set_speed (GstClock *clock, gdouble speed);
|
||||
gdouble gst_clock_get_speed (GstClock *clock);
|
||||
#endif
|
||||
|
||||
guint64 gst_clock_set_resolution (GstClock *clock, guint64 resolution);
|
||||
guint64 gst_clock_get_resolution (GstClock *clock);
|
||||
|
||||
#ifndef GST_DISABLE_DEPRECATED
|
||||
void gst_clock_set_active (GstClock *clock, gboolean active);
|
||||
gboolean gst_clock_is_active (GstClock *clock);
|
||||
void gst_clock_reset (GstClock *clock);
|
||||
gboolean gst_clock_handle_discont (GstClock *clock, guint64 time);
|
||||
#endif
|
||||
|
||||
GstClockTime gst_clock_get_time (GstClock *clock);
|
||||
GstClockTime gst_clock_get_event_time (GstClock *clock);
|
||||
|
||||
|
||||
/* FIXME: deprecate? */
|
||||
#ifndef GST_DISABLE_DEPRECATED
|
||||
GstClockID gst_clock_get_next_id (GstClock *clock);
|
||||
|
||||
/* creating IDs that can be used to get notifications */
|
||||
|
@ -203,7 +197,6 @@ GstClockReturn gst_clock_id_wait_async (GstClockID id,
|
|||
void gst_clock_id_unschedule (GstClockID id);
|
||||
void gst_clock_id_unlock (GstClockID id);
|
||||
void gst_clock_id_free (GstClockID id);
|
||||
#endif
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -835,9 +835,6 @@ gst_element_get_time (GstElement *element)
|
|||
}
|
||||
}
|
||||
|
||||
GstClockID gst_clock_new_single_shot_id (GstClock *clock,
|
||||
GstClockTime time);
|
||||
void gst_clock_id_free (GstClockID id);
|
||||
/**
|
||||
* gst_element_wait:
|
||||
* @element: element that should wait
|
||||
|
@ -2961,7 +2958,9 @@ gst_element_dispose (GObject *object)
|
|||
element->numsrcpads = 0;
|
||||
element->numsinkpads = 0;
|
||||
element->numpads = 0;
|
||||
if (element->state_mutex)
|
||||
g_mutex_free (element->state_mutex);
|
||||
if (element->state_cond)
|
||||
g_cond_free (element->state_cond);
|
||||
|
||||
if (element->prop_value_queue)
|
||||
|
|
|
@ -287,10 +287,8 @@ gboolean gst_element_requires_clock (GstElement *element);
|
|||
gboolean gst_element_provides_clock (GstElement *element);
|
||||
GstClock* gst_element_get_clock (GstElement *element);
|
||||
void gst_element_set_clock (GstElement *element, GstClock *clock);
|
||||
#ifndef GST_DISABLE_DEPRECATED
|
||||
GstClockReturn gst_element_clock_wait (GstElement *element,
|
||||
GstClockID id, GstClockTimeDiff *jitter);
|
||||
#endif
|
||||
GstClockTime gst_element_get_time (GstElement *element);
|
||||
gboolean gst_element_wait (GstElement *element, GstClockTime timestamp);
|
||||
void gst_element_set_time (GstElement *element, GstClockTime time);
|
||||
|
|
269
gst/gstpad.c
269
gst/gstpad.c
|
@ -353,9 +353,9 @@ gst_pad_custom_new_from_template (GType type, GstPadTemplate *templ,
|
|||
{
|
||||
GstPad *pad;
|
||||
|
||||
g_return_val_if_fail (templ != NULL, NULL);
|
||||
g_return_val_if_fail (GST_IS_PAD_TEMPLATE (templ), NULL);
|
||||
|
||||
pad = gst_pad_new (name, templ->direction);
|
||||
pad = gst_pad_custom_new (type, name, templ->direction);
|
||||
gst_pad_set_pad_template (pad, templ);
|
||||
|
||||
return pad;
|
||||
|
@ -379,6 +379,7 @@ gst_pad_new_from_template (GstPadTemplate *templ, const gchar *name)
|
|||
templ, name);
|
||||
}
|
||||
|
||||
/* FIXME 0.9: GST_PAD_UNKNOWN needs to die! */
|
||||
/**
|
||||
* gst_pad_get_direction:
|
||||
* @pad: a #GstPad to get the direction of.
|
||||
|
@ -465,6 +466,7 @@ gst_pad_set_name (GstPad *pad, const gchar *name)
|
|||
gst_object_set_name (GST_OBJECT (pad), name);
|
||||
}
|
||||
|
||||
/* FIXME 0.9: This function must die */
|
||||
/**
|
||||
* gst_pad_get_name:
|
||||
* @pad: a #GstPad to get the name of.
|
||||
|
@ -477,7 +479,6 @@ gst_pad_set_name (GstPad *pad, const gchar *name)
|
|||
const gchar*
|
||||
gst_pad_get_name (GstPad *pad)
|
||||
{
|
||||
g_return_val_if_fail (pad != NULL, NULL);
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
|
||||
|
||||
return GST_OBJECT_NAME (pad);
|
||||
|
@ -485,15 +486,15 @@ gst_pad_get_name (GstPad *pad)
|
|||
|
||||
/**
|
||||
* gst_pad_set_chain_function:
|
||||
* @pad: a #GstPad to set the chain function for.
|
||||
* @pad: a real sink #GstPad.
|
||||
* @chain: the #GstPadChainFunction to set.
|
||||
*
|
||||
* Sets the given chain function for the pad.
|
||||
* Sets the given chain function for the pad. The chain function is called to
|
||||
* process a #GstData input buffer.
|
||||
*/
|
||||
void
|
||||
gst_pad_set_chain_function (GstPad *pad, GstPadChainFunction chain)
|
||||
{
|
||||
g_return_if_fail (pad != NULL);
|
||||
g_return_if_fail (GST_IS_REAL_PAD (pad));
|
||||
g_return_if_fail (GST_RPAD_DIRECTION (pad) == GST_PAD_SINK);
|
||||
|
||||
|
@ -504,16 +505,17 @@ gst_pad_set_chain_function (GstPad *pad, GstPadChainFunction chain)
|
|||
|
||||
/**
|
||||
* gst_pad_set_get_function:
|
||||
* @pad: a #GstPad to set the get function for.
|
||||
* @pad: a real source #GstPad.
|
||||
* @get: the #GstPadGetFunction to set.
|
||||
*
|
||||
* Sets the given get function for the pad.
|
||||
* Sets the given get function for the pad. The get function is called to
|
||||
* produce a new #GstData to start the processing pipeline. Get functions cannot
|
||||
* return %NULL.
|
||||
*/
|
||||
void
|
||||
gst_pad_set_get_function (GstPad *pad,
|
||||
GstPadGetFunction get)
|
||||
{
|
||||
g_return_if_fail (pad != NULL);
|
||||
g_return_if_fail (GST_IS_REAL_PAD (pad));
|
||||
g_return_if_fail (GST_RPAD_DIRECTION (pad) == GST_PAD_SRC);
|
||||
|
||||
|
@ -525,7 +527,7 @@ gst_pad_set_get_function (GstPad *pad,
|
|||
|
||||
/**
|
||||
* gst_pad_set_event_function:
|
||||
* @pad: a #GstPad to set the event handler for.
|
||||
* @pad: a real source #GstPad.
|
||||
* @event: the #GstPadEventFunction to set.
|
||||
*
|
||||
* Sets the given event handler for the pad.
|
||||
|
@ -545,7 +547,7 @@ gst_pad_set_event_function (GstPad *pad,
|
|||
|
||||
/**
|
||||
* gst_pad_set_event_mask_function:
|
||||
* @pad: a #GstPad to set the event mask function for.
|
||||
* @pad: a real #GstPad of either direction.
|
||||
* @mask_func: the #GstPadEventMaskFunction to set.
|
||||
*
|
||||
* Sets the given event mask function for the pad.
|
||||
|
@ -564,7 +566,7 @@ gst_pad_set_event_mask_function (GstPad *pad,
|
|||
|
||||
/**
|
||||
* gst_pad_get_event_masks:
|
||||
* @pad: a #GstPad to get the event mask for.
|
||||
* @pad: a #GstPad.
|
||||
*
|
||||
* Gets the array of eventmasks from the given pad.
|
||||
*
|
||||
|
@ -576,8 +578,7 @@ gst_pad_get_event_masks (GstPad *pad)
|
|||
{
|
||||
GstRealPad *rpad;
|
||||
|
||||
if (pad == NULL)
|
||||
return FALSE;
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
|
||||
|
||||
rpad = GST_PAD_REALIZE (pad);
|
||||
|
||||
|
@ -599,7 +600,7 @@ gst_pad_get_event_masks_dispatcher (GstPad *pad, const GstEventMask **data)
|
|||
|
||||
/**
|
||||
* gst_pad_get_event_masks_default:
|
||||
* @pad: a #GstPad to get the event mask for.
|
||||
* @pad: a #GstPad.
|
||||
*
|
||||
* Invokes the default event masks dispatcher on the pad.
|
||||
*
|
||||
|
@ -611,6 +612,8 @@ gst_pad_get_event_masks_default (GstPad *pad)
|
|||
{
|
||||
GstEventMask *result = NULL;
|
||||
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
|
||||
|
||||
gst_pad_dispatcher (pad, (GstPadDispatcherFunction)
|
||||
gst_pad_get_event_masks_dispatcher, &result);
|
||||
|
||||
|
@ -619,7 +622,7 @@ gst_pad_get_event_masks_default (GstPad *pad)
|
|||
|
||||
/**
|
||||
* gst_pad_set_convert_function:
|
||||
* @pad: a #GstPad to set the convert function for.
|
||||
* @pad: a real #GstPad of either direction.
|
||||
* @convert: the #GstPadConvertFunction to set.
|
||||
*
|
||||
* Sets the given convert function for the pad.
|
||||
|
@ -628,7 +631,6 @@ void
|
|||
gst_pad_set_convert_function (GstPad *pad,
|
||||
GstPadConvertFunction convert)
|
||||
{
|
||||
g_return_if_fail (pad != NULL);
|
||||
g_return_if_fail (GST_IS_REAL_PAD (pad));
|
||||
|
||||
GST_RPAD_CONVERTFUNC (pad) = convert;
|
||||
|
@ -639,7 +641,7 @@ gst_pad_set_convert_function (GstPad *pad,
|
|||
|
||||
/**
|
||||
* gst_pad_set_query_function:
|
||||
* @pad: the #GstPad to set the query function for.
|
||||
* @pad: a real #GstPad of either direction.
|
||||
* @query: the #GstPadQueryFunction to set.
|
||||
*
|
||||
* Set the given query function for the pad.
|
||||
|
@ -647,7 +649,6 @@ gst_pad_set_convert_function (GstPad *pad,
|
|||
void
|
||||
gst_pad_set_query_function (GstPad *pad, GstPadQueryFunction query)
|
||||
{
|
||||
g_return_if_fail (pad != NULL);
|
||||
g_return_if_fail (GST_IS_REAL_PAD (pad));
|
||||
|
||||
GST_RPAD_QUERYFUNC (pad) = query;
|
||||
|
@ -658,7 +659,7 @@ gst_pad_set_query_function (GstPad *pad, GstPadQueryFunction query)
|
|||
|
||||
/**
|
||||
* gst_pad_set_query_type_function:
|
||||
* @pad: the #GstPad to set the query type function for.
|
||||
* @pad: a real #GstPad of either direction.
|
||||
* @type_func: the #GstPadQueryTypeFunction to set.
|
||||
*
|
||||
* Set the given query type function for the pad.
|
||||
|
@ -666,7 +667,6 @@ gst_pad_set_query_function (GstPad *pad, GstPadQueryFunction query)
|
|||
void
|
||||
gst_pad_set_query_type_function (GstPad *pad, GstPadQueryTypeFunction type_func)
|
||||
{
|
||||
g_return_if_fail (pad != NULL);
|
||||
g_return_if_fail (GST_IS_REAL_PAD (pad));
|
||||
|
||||
GST_RPAD_QUERYTYPEFUNC (pad) = type_func;
|
||||
|
@ -677,7 +677,7 @@ gst_pad_set_query_type_function (GstPad *pad, GstPadQueryTypeFunction type_func)
|
|||
|
||||
/**
|
||||
* gst_pad_get_query_types:
|
||||
* @pad: the #GstPad to query
|
||||
* @pad: a #GstPad.
|
||||
*
|
||||
* Get an array of supported queries that can be performed
|
||||
* on this pad.
|
||||
|
@ -689,12 +689,11 @@ gst_pad_get_query_types (GstPad *pad)
|
|||
{
|
||||
GstRealPad *rpad;
|
||||
|
||||
if (pad == NULL)
|
||||
return FALSE;
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
|
||||
|
||||
rpad = GST_PAD_REALIZE (pad);
|
||||
|
||||
g_return_val_if_fail (rpad, FALSE);
|
||||
g_return_val_if_fail (rpad, NULL);
|
||||
|
||||
if (GST_RPAD_QUERYTYPEFUNC (rpad))
|
||||
return GST_RPAD_QUERYTYPEFUNC (rpad) (GST_PAD (pad));
|
||||
|
@ -712,7 +711,7 @@ gst_pad_get_query_types_dispatcher (GstPad *pad, const GstQueryType **data)
|
|||
|
||||
/**
|
||||
* gst_pad_get_query_types_default:
|
||||
* @pad: the #GstPad to query
|
||||
* @pad: a #GstPad.
|
||||
*
|
||||
* Invoke the default dispatcher for the query types on
|
||||
* the pad.
|
||||
|
@ -725,6 +724,8 @@ gst_pad_get_query_types_default (GstPad *pad)
|
|||
{
|
||||
GstQueryType *result = NULL;
|
||||
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
|
||||
|
||||
gst_pad_dispatcher (pad, (GstPadDispatcherFunction)
|
||||
gst_pad_get_query_types_dispatcher, &result);
|
||||
|
||||
|
@ -733,7 +734,7 @@ gst_pad_get_query_types_default (GstPad *pad)
|
|||
|
||||
/**
|
||||
* gst_pad_set_internal_link_function:
|
||||
* @pad: a #GstPad to set the internal link function for.
|
||||
* @pad: a real #GstPad of either direction.
|
||||
* @intlink: the #GstPadIntLinkFunction to set.
|
||||
*
|
||||
* Sets the given internal link function for the pad.
|
||||
|
@ -742,7 +743,6 @@ void
|
|||
gst_pad_set_internal_link_function (GstPad *pad,
|
||||
GstPadIntLinkFunction intlink)
|
||||
{
|
||||
g_return_if_fail (pad != NULL);
|
||||
g_return_if_fail (GST_IS_REAL_PAD (pad));
|
||||
|
||||
GST_RPAD_INTLINKFUNC (pad) = intlink;
|
||||
|
@ -752,7 +752,7 @@ gst_pad_set_internal_link_function (GstPad *pad,
|
|||
|
||||
/**
|
||||
* gst_pad_set_formats_function:
|
||||
* @pad: the #GstPad to set the formats function for.
|
||||
* @pad: a real #GstPad of either direction.
|
||||
* @formats: the #GstPadFormatsFunction to set.
|
||||
*
|
||||
* Sets the given formats function for the pad.
|
||||
|
@ -760,7 +760,6 @@ gst_pad_set_internal_link_function (GstPad *pad,
|
|||
void
|
||||
gst_pad_set_formats_function (GstPad *pad, GstPadFormatsFunction formats)
|
||||
{
|
||||
g_return_if_fail (pad != NULL);
|
||||
g_return_if_fail (GST_IS_REAL_PAD (pad));
|
||||
|
||||
GST_RPAD_FORMATSFUNC (pad) = formats;
|
||||
|
@ -770,7 +769,7 @@ gst_pad_set_formats_function (GstPad *pad, GstPadFormatsFunction formats)
|
|||
|
||||
/**
|
||||
* gst_pad_set_link_function:
|
||||
* @pad: a #GstPad to set the link function for.
|
||||
* @pad: a real #GstPad.
|
||||
* @link: the #GstPadLinkFunction to set.
|
||||
*
|
||||
* Sets the given link function for the pad. It will be called when the pad is
|
||||
|
@ -799,7 +798,6 @@ void
|
|||
gst_pad_set_link_function (GstPad *pad,
|
||||
GstPadLinkFunction link)
|
||||
{
|
||||
g_return_if_fail (pad != NULL);
|
||||
g_return_if_fail (GST_IS_REAL_PAD (pad));
|
||||
|
||||
GST_RPAD_LINKFUNC (pad) = link;
|
||||
|
@ -809,7 +807,7 @@ gst_pad_set_link_function (GstPad *pad,
|
|||
|
||||
/**
|
||||
* gst_pad_set_unlink_function:
|
||||
* @pad: a #GstPad to set the unlink function for.
|
||||
* @pad: a real #GstPad.
|
||||
* @unlink: the #GstPadUnlinkFunction to set.
|
||||
*
|
||||
* Sets the given unlink function for the pad. It will be called
|
||||
|
@ -819,7 +817,6 @@ void
|
|||
gst_pad_set_unlink_function (GstPad *pad,
|
||||
GstPadUnlinkFunction unlink)
|
||||
{
|
||||
g_return_if_fail (pad != NULL);
|
||||
g_return_if_fail (GST_IS_REAL_PAD (pad));
|
||||
|
||||
GST_RPAD_UNLINKFUNC (pad) = unlink;
|
||||
|
@ -829,7 +826,7 @@ gst_pad_set_unlink_function (GstPad *pad,
|
|||
|
||||
/**
|
||||
* gst_pad_set_fixate_function:
|
||||
* @pad: a #GstPad to set the fixate function for.
|
||||
* @pad: a real #GstPad.
|
||||
* @fixate: the #GstPadFixateFunction to set.
|
||||
*
|
||||
* Sets the given fixate function for the pad. Its job is to narrow down the
|
||||
|
@ -845,7 +842,6 @@ gst_pad_set_unlink_function (GstPad *pad,
|
|||
void
|
||||
gst_pad_set_fixate_function (GstPad *pad, GstPadFixateFunction fixate)
|
||||
{
|
||||
g_return_if_fail (pad != NULL);
|
||||
g_return_if_fail (GST_IS_REAL_PAD (pad));
|
||||
|
||||
GST_RPAD_FIXATEFUNC (pad) = fixate;
|
||||
|
@ -855,7 +851,7 @@ gst_pad_set_fixate_function (GstPad *pad, GstPadFixateFunction fixate)
|
|||
|
||||
/**
|
||||
* gst_pad_set_getcaps_function:
|
||||
* @pad: a #GstPad to set the getcaps function for.
|
||||
* @pad: a real #GstPad.
|
||||
* @getcaps: the #GstPadGetCapsFunction to set.
|
||||
*
|
||||
* Sets the given getcaps function for the pad. @getcaps should return the
|
||||
|
@ -882,7 +878,6 @@ void
|
|||
gst_pad_set_getcaps_function (GstPad *pad,
|
||||
GstPadGetCapsFunction getcaps)
|
||||
{
|
||||
g_return_if_fail (pad != NULL);
|
||||
g_return_if_fail (GST_IS_REAL_PAD (pad));
|
||||
|
||||
GST_RPAD_GETCAPSFUNC (pad) = getcaps;
|
||||
|
@ -892,7 +887,7 @@ gst_pad_set_getcaps_function (GstPad *pad,
|
|||
|
||||
/**
|
||||
* gst_pad_set_bufferalloc_function:
|
||||
* @pad: a #GstPad to set the bufferalloc function for.
|
||||
* @pad: a real sink #GstPad.
|
||||
* @bufalloc: the #GstPadBufferAllocFunction to set.
|
||||
*
|
||||
* Sets the given bufferalloc function for the pad. Note that the
|
||||
|
@ -902,7 +897,6 @@ void
|
|||
gst_pad_set_bufferalloc_function (GstPad *pad,
|
||||
GstPadBufferAllocFunction bufalloc)
|
||||
{
|
||||
g_return_if_fail (pad != NULL);
|
||||
g_return_if_fail (GST_IS_REAL_PAD (pad));
|
||||
g_return_if_fail (GST_PAD_IS_SINK (pad));
|
||||
|
||||
|
@ -911,6 +905,8 @@ gst_pad_set_bufferalloc_function (GstPad *pad,
|
|||
GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (bufalloc));
|
||||
}
|
||||
|
||||
/* FIXME 0.9: Do we actually want to allow the case where src and sink are
|
||||
switched? */
|
||||
/**
|
||||
* gst_pad_unlink:
|
||||
* @srcpad: the source #GstPad to unlink.
|
||||
|
@ -926,17 +922,13 @@ gst_pad_unlink (GstPad *srcpad,
|
|||
GstRealPad *realsrc, *realsink;
|
||||
GstScheduler *src_sched, *sink_sched;
|
||||
|
||||
/* generic checks */
|
||||
g_return_if_fail (srcpad != NULL);
|
||||
g_return_if_fail (GST_IS_PAD (srcpad));
|
||||
g_return_if_fail (sinkpad != NULL);
|
||||
g_return_if_fail (GST_IS_PAD (sinkpad));
|
||||
|
||||
GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "unlinking %s:%s(%p) and %s:%s(%p)",
|
||||
GST_DEBUG_PAD_NAME (srcpad), srcpad,
|
||||
GST_DEBUG_PAD_NAME (sinkpad), sinkpad);
|
||||
|
||||
/* now we need to deal with the real/ghost stuff */
|
||||
realsrc = GST_PAD_REALIZE (srcpad);
|
||||
realsink = GST_PAD_REALIZE (sinkpad);
|
||||
|
||||
|
@ -1352,9 +1344,7 @@ gst_pad_renegotiate (GstPad *pad)
|
|||
{
|
||||
GstPadLink *link;
|
||||
|
||||
g_return_val_if_fail (pad != NULL, GST_PAD_LINK_REFUSED);
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), GST_PAD_LINK_REFUSED);
|
||||
|
||||
g_return_val_if_fail (GST_PAD_LINK_SRC (pad), GST_PAD_LINK_REFUSED);
|
||||
g_return_val_if_fail (GST_PAD_LINK_SINK (pad), GST_PAD_LINK_REFUSED);
|
||||
|
||||
|
@ -1400,7 +1390,6 @@ gst_pad_try_set_caps (GstPad *pad, const GstCaps *caps)
|
|||
GstPadLink *oldlink;
|
||||
GstPadLinkReturn ret;
|
||||
|
||||
g_return_val_if_fail (pad != NULL, GST_PAD_LINK_REFUSED);
|
||||
g_return_val_if_fail (GST_IS_REAL_PAD (pad), GST_PAD_LINK_REFUSED);
|
||||
g_return_val_if_fail (!GST_PAD_IS_NEGOTIATING (pad), GST_PAD_LINK_REFUSED);
|
||||
|
||||
|
@ -1421,15 +1410,15 @@ gst_pad_try_set_caps (GstPad *pad, const GstCaps *caps)
|
|||
return GST_PAD_LINK_OK;
|
||||
}
|
||||
|
||||
g_return_val_if_fail (GST_PAD_LINK_SRC (pad), GST_PAD_LINK_REFUSED);
|
||||
g_return_val_if_fail (GST_PAD_LINK_SINK (pad), GST_PAD_LINK_REFUSED);
|
||||
|
||||
/* if the desired caps are already there, it's trivially ok */
|
||||
if (GST_PAD_CAPS (pad) && gst_caps_is_equal_fixed (caps,
|
||||
GST_PAD_CAPS (pad))) {
|
||||
return GST_PAD_LINK_OK;
|
||||
}
|
||||
|
||||
g_return_val_if_fail (GST_PAD_LINK_SRC (pad), GST_PAD_LINK_REFUSED);
|
||||
g_return_val_if_fail (GST_PAD_LINK_SINK (pad), GST_PAD_LINK_REFUSED);
|
||||
|
||||
link = gst_pad_link_new ();
|
||||
|
||||
link->srcpad = GST_PAD_LINK_SRC (pad);
|
||||
|
@ -1461,7 +1450,7 @@ gst_pad_try_set_caps (GstPad *pad, const GstCaps *caps)
|
|||
|
||||
/**
|
||||
* gst_pad_try_set_caps_nonfixed:
|
||||
* @pad: a #GstPad
|
||||
* @pad: a real #GstPad
|
||||
* @caps: #GstCaps to set on @pad
|
||||
*
|
||||
* Like gst_pad_try_set_caps(), but allows non-fixed caps.
|
||||
|
@ -1475,16 +1464,17 @@ gst_pad_try_set_caps_nonfixed (GstPad *pad, const GstCaps *caps)
|
|||
GstPadLink *oldlink;
|
||||
GstPadLinkReturn ret;
|
||||
|
||||
g_return_val_if_fail (pad != NULL, GST_PAD_LINK_REFUSED);
|
||||
g_return_val_if_fail (GST_IS_REAL_PAD (pad), GST_PAD_LINK_REFUSED);
|
||||
g_return_val_if_fail (!GST_FLAG_IS_SET (pad, GST_PAD_NEGOTIATING),
|
||||
GST_PAD_LINK_REFUSED);
|
||||
g_return_val_if_fail (!GST_PAD_IS_NEGOTIATING (pad), GST_PAD_LINK_REFUSED);
|
||||
|
||||
/* we allow setting caps on non-linked pads. It's ignored */
|
||||
if (!GST_PAD_PEER (pad)) {
|
||||
return GST_PAD_LINK_OK;
|
||||
}
|
||||
|
||||
g_return_val_if_fail (GST_PAD_LINK_SRC (pad), GST_PAD_LINK_REFUSED);
|
||||
g_return_val_if_fail (GST_PAD_LINK_SINK (pad), GST_PAD_LINK_REFUSED);
|
||||
|
||||
/* if the link is already negotiated and the caps are compatible
|
||||
* with what we're setting, it's trivially OK. */
|
||||
if (GST_PAD_CAPS (pad)) {
|
||||
|
@ -1497,9 +1487,6 @@ gst_pad_try_set_caps_nonfixed (GstPad *pad, const GstCaps *caps)
|
|||
gst_caps_free (intersection);
|
||||
}
|
||||
|
||||
g_return_val_if_fail (GST_PAD_LINK_SRC (pad), GST_PAD_LINK_REFUSED);
|
||||
g_return_val_if_fail (GST_PAD_LINK_SINK (pad), GST_PAD_LINK_REFUSED);
|
||||
|
||||
link = gst_pad_link_new ();
|
||||
|
||||
link->srcpad = GST_PAD_LINK_SRC (pad);
|
||||
|
@ -1565,6 +1552,11 @@ gst_pad_can_link_filtered (GstPad *srcpad, GstPad *sinkpad,
|
|||
realsrc = GST_PAD_REALIZE (srcpad);
|
||||
realsink = GST_PAD_REALIZE (sinkpad);
|
||||
|
||||
g_return_val_if_fail (GST_RPAD_PEER (realsrc) == NULL, NULL);
|
||||
g_return_val_if_fail (GST_RPAD_PEER (realsink) == NULL, NULL);
|
||||
g_return_val_if_fail (GST_PAD_PARENT (realsrc) != NULL, NULL);
|
||||
g_return_val_if_fail (GST_PAD_PARENT (realsink) != NULL, NULL);
|
||||
|
||||
if ((GST_PAD (realsrc) != srcpad) || (GST_PAD (realsink) != sinkpad)) {
|
||||
GST_CAT_INFO (GST_CAT_PADS, "*actually* linking %s:%s and %s:%s",
|
||||
GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
|
||||
|
@ -1792,6 +1784,7 @@ gst_pad_link (GstPad *srcpad, GstPad *sinkpad)
|
|||
return gst_pad_link_filtered (srcpad, sinkpad, NULL);
|
||||
}
|
||||
|
||||
/* FIXME 0.9: Remove this */
|
||||
/**
|
||||
* gst_pad_set_parent:
|
||||
* @pad: a #GstPad to set the parent of.
|
||||
|
@ -1803,16 +1796,14 @@ gst_pad_link (GstPad *srcpad, GstPad *sinkpad)
|
|||
void
|
||||
gst_pad_set_parent (GstPad *pad, GstElement *parent)
|
||||
{
|
||||
g_return_if_fail (pad != NULL);
|
||||
g_return_if_fail (GST_IS_PAD (pad));
|
||||
g_return_if_fail (GST_PAD_PARENT (pad) == NULL);
|
||||
g_return_if_fail (parent != NULL);
|
||||
g_return_if_fail (GST_IS_OBJECT (parent));
|
||||
g_return_if_fail ((gpointer) pad != (gpointer) parent);
|
||||
g_return_if_fail (GST_IS_ELEMENT (parent));
|
||||
|
||||
gst_object_set_parent (GST_OBJECT (pad), GST_OBJECT (parent));
|
||||
}
|
||||
|
||||
/* FIXME 0.9: Remove this */
|
||||
/**
|
||||
* gst_pad_get_parent:
|
||||
* @pad: the #GstPad to get the parent of.
|
||||
|
@ -1841,13 +1832,15 @@ gst_pad_set_pad_template (GstPad *pad, GstPadTemplate *templ)
|
|||
if (templ)
|
||||
g_signal_emit (G_OBJECT (templ), gst_pad_template_signals[TEMPL_PAD_CREATED], 0, pad);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_pad_get_pad_template:
|
||||
* @pad: a #GstPad to get the pad template of.
|
||||
* @pad: a #GstPad.
|
||||
*
|
||||
* Gets the pad template object of this pad.
|
||||
* Gets the template for @pad.
|
||||
*
|
||||
* Returns: the #GstPadTemplate from which this pad was instantiated.
|
||||
* Returns: the #GstPadTemplate from which this pad was instantiated, or %NULL
|
||||
* if this pad has no template.
|
||||
*/
|
||||
GstPadTemplate*
|
||||
gst_pad_get_pad_template (GstPad *pad)
|
||||
|
@ -1867,7 +1860,8 @@ gst_pad_get_pad_template (GstPad *pad)
|
|||
* is taken. For decoupled pads, the scheduler of the peer
|
||||
* parent is taken.
|
||||
*
|
||||
* Returns: the #GstScheduler of the pad.
|
||||
* Returns: the #GstScheduler of the pad, or %NULL if there is no parent or the
|
||||
* parent is not yet in a managing bin.
|
||||
*/
|
||||
GstScheduler*
|
||||
gst_pad_get_scheduler (GstPad *pad)
|
||||
|
@ -1907,12 +1901,12 @@ gst_pad_get_scheduler (GstPad *pad)
|
|||
GstElement*
|
||||
gst_pad_get_real_parent (GstPad *pad)
|
||||
{
|
||||
g_return_val_if_fail (pad != NULL, NULL);
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
|
||||
|
||||
return GST_PAD_PARENT (GST_PAD (GST_PAD_REALIZE (pad)));
|
||||
}
|
||||
|
||||
/* FIXME 0.9: Make static. */
|
||||
/**
|
||||
* gst_pad_add_ghost_pad:
|
||||
* @pad: a #GstPad to attach the ghost pad to.
|
||||
|
@ -1927,9 +1921,7 @@ gst_pad_add_ghost_pad (GstPad *pad,
|
|||
{
|
||||
GstRealPad *realpad;
|
||||
|
||||
g_return_if_fail (pad != NULL);
|
||||
g_return_if_fail (GST_IS_PAD (pad));
|
||||
g_return_if_fail (ghostpad != NULL);
|
||||
g_return_if_fail (GST_IS_GHOST_PAD (ghostpad));
|
||||
|
||||
/* if we're ghosting a ghost pad, drill down to find the real pad */
|
||||
|
@ -1944,6 +1936,7 @@ gst_pad_add_ghost_pad (GstPad *pad,
|
|||
gst_pad_set_pad_template (GST_PAD (ghostpad), GST_PAD_PAD_TEMPLATE (pad));
|
||||
}
|
||||
|
||||
/* FIXME 0.9: Make static. */
|
||||
/**
|
||||
* gst_pad_remove_ghost_pad:
|
||||
* @pad: a #GstPad to remove the ghost pad from.
|
||||
|
@ -1978,7 +1971,6 @@ gst_pad_remove_ghost_pad (GstPad *pad,
|
|||
GList*
|
||||
gst_pad_get_ghost_pad_list (GstPad *pad)
|
||||
{
|
||||
g_return_val_if_fail (pad != NULL, NULL);
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
|
||||
|
||||
return GST_PAD_REALIZE(pad)->ghostpads;
|
||||
|
@ -2112,55 +2104,21 @@ gboolean
|
|||
gst_pad_try_relink_filtered (GstPad *srcpad, GstPad *sinkpad,
|
||||
const GstCaps *filtercaps)
|
||||
{
|
||||
GstRealPad *realsrc, *realsink;
|
||||
GstPadLink *link;
|
||||
|
||||
/* generic checks */
|
||||
g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
|
||||
g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
|
||||
GST_INFO ("trying to relink %" GST_PTR_FORMAT " and %" GST_PTR_FORMAT
|
||||
" with filtercaps %" GST_PTR_FORMAT, srcpad, sinkpad);
|
||||
|
||||
GST_CAT_INFO (GST_CAT_PADS, "trying to relink %s:%s and %s:%s with filtercaps %" GST_PTR_FORMAT,
|
||||
GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad), filtercaps);
|
||||
link = gst_pad_link_prepare (srcpad, sinkpad, filtercaps);
|
||||
if (!link) return FALSE;
|
||||
|
||||
/* now we need to deal with the real/ghost stuff */
|
||||
realsrc = GST_PAD_REALIZE (srcpad);
|
||||
realsink = GST_PAD_REALIZE (sinkpad);
|
||||
|
||||
g_return_val_if_fail (realsrc != NULL, FALSE);
|
||||
g_return_val_if_fail (realsink != NULL, FALSE);
|
||||
g_return_val_if_fail (GST_RPAD_PEER (realsrc) == realsink, FALSE);
|
||||
g_assert (realsrc == GST_RPAD_PEER (realsink));
|
||||
if ((GST_PAD (realsrc) != srcpad) || (GST_PAD (realsink) != sinkpad)) {
|
||||
GST_CAT_INFO (GST_CAT_PADS, "*actually* linking %s:%s and %s:%s",
|
||||
GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
|
||||
}
|
||||
|
||||
link = gst_pad_link_new ();
|
||||
|
||||
if (GST_RPAD_DIRECTION (realsrc) == GST_PAD_SRC) {
|
||||
link->srcpad = GST_PAD (realsrc);
|
||||
link->sinkpad = GST_PAD (realsink);
|
||||
} else {
|
||||
link->srcpad = GST_PAD (realsink);
|
||||
link->sinkpad = GST_PAD (realsrc);
|
||||
}
|
||||
|
||||
if (GST_RPAD_DIRECTION (link->srcpad) != GST_PAD_SRC) {
|
||||
GST_CAT_INFO (GST_CAT_PADS, "Real src pad %s:%s is not a source pad, failed",
|
||||
GST_DEBUG_PAD_NAME (link->srcpad));
|
||||
gst_pad_link_free (link);
|
||||
return FALSE;
|
||||
}
|
||||
if (GST_RPAD_DIRECTION (link->sinkpad) != GST_PAD_SINK) {
|
||||
GST_CAT_INFO (GST_CAT_PADS, "Real sink pad %s:%s is not a sink pad, failed",
|
||||
GST_DEBUG_PAD_NAME (link->sinkpad));
|
||||
if (GST_RPAD_PEER (link->srcpad) != (GstRealPad*)link->sinkpad) {
|
||||
g_warning ("Pads %s:%s and %s:%s were never linked",
|
||||
GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
|
||||
gst_pad_link_free (link);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
link->srccaps = gst_pad_get_caps (link->srcpad);
|
||||
link->sinkcaps = gst_pad_get_caps (link->sinkpad);
|
||||
if (filtercaps) link->filtercaps = gst_caps_copy (filtercaps);
|
||||
if (GST_PAD_LINK_FAILED (gst_pad_link_try (link)))
|
||||
return FALSE;
|
||||
|
||||
|
@ -2210,6 +2168,8 @@ gst_pad_proxy_getcaps (GstPad *pad)
|
|||
const GList *pads;
|
||||
GstCaps *caps;
|
||||
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
|
||||
|
||||
GST_DEBUG ("proxying getcaps for %s:%s\n", GST_DEBUG_PAD_NAME (pad));
|
||||
|
||||
element = gst_pad_get_parent (pad);
|
||||
|
@ -2241,7 +2201,7 @@ gst_pad_proxy_getcaps (GstPad *pad)
|
|||
*
|
||||
* Calls gst_pad_try_set_caps() for every other pad belonging to the
|
||||
* same element as @pad. If gst_pad_try_set_caps() fails on any pad,
|
||||
* the proxy link fails.
|
||||
* the proxy link fails. May be used only during negotiation.
|
||||
*
|
||||
* Returns: GST_PAD_LINK_OK if sucessful
|
||||
*/
|
||||
|
@ -2252,6 +2212,9 @@ gst_pad_proxy_pad_link (GstPad *pad, const GstCaps *caps)
|
|||
const GList *pads;
|
||||
GstPadLinkReturn ret;
|
||||
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), GST_PAD_LINK_REFUSED);
|
||||
g_return_val_if_fail (caps != NULL, GST_PAD_LINK_REFUSED);
|
||||
|
||||
GST_DEBUG ("proxying pad link for %s:%s\n", GST_DEBUG_PAD_NAME (pad));
|
||||
|
||||
element = gst_pad_get_parent (pad);
|
||||
|
@ -2290,6 +2253,9 @@ gst_pad_proxy_fixate (GstPad *pad, const GstCaps *caps)
|
|||
const GList *pads;
|
||||
const GstCaps *othercaps;
|
||||
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
|
||||
g_return_val_if_fail (caps != NULL, NULL);
|
||||
|
||||
GST_DEBUG ("proxying fixate for %s:%s\n", GST_DEBUG_PAD_NAME (pad));
|
||||
|
||||
element = gst_pad_get_parent (pad);
|
||||
|
@ -2550,7 +2516,6 @@ const GstCaps*
|
|||
gst_pad_get_pad_template_caps (GstPad *pad)
|
||||
{
|
||||
static GstStaticCaps anycaps = GST_STATIC_CAPS ("ANY");
|
||||
g_return_val_if_fail (pad != NULL, NULL);
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
|
||||
|
||||
if (GST_PAD_PAD_TEMPLATE (pad))
|
||||
|
@ -2558,6 +2523,7 @@ gst_pad_get_pad_template_caps (GstPad *pad)
|
|||
|
||||
#if 0
|
||||
/* FIXME this should be enabled some day */
|
||||
/* wingo: why? mail the list during 0.9 when you find this :) */
|
||||
g_warning("pad %s:%s (%p) has no pad template\n",
|
||||
GST_DEBUG_PAD_NAME (realpad), realpad);
|
||||
#endif
|
||||
|
@ -2565,6 +2531,8 @@ gst_pad_get_pad_template_caps (GstPad *pad)
|
|||
return gst_static_caps_get(&anycaps);
|
||||
}
|
||||
|
||||
/* FIXME 0.9: This function should probably die, or at least be renamed to
|
||||
* get_caps_by_format. */
|
||||
/**
|
||||
* gst_pad_template_get_caps_by_name:
|
||||
* @templ: a #GstPadTemplate to get the capabilities of.
|
||||
|
@ -2591,12 +2559,14 @@ gst_pad_template_get_caps_by_name (GstPadTemplate *templ, const gchar *name)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* FIXME 0.9: What good is this if it only works for already-negotiated pads? */
|
||||
/**
|
||||
* gst_pad_check_compatibility:
|
||||
* @srcpad: the source #GstPad to check.
|
||||
* @sinkpad: the sink #GstPad to check against.
|
||||
*
|
||||
* Checks if two pads have compatible capabilities.
|
||||
* Checks if two pads have compatible capabilities. If neither one has yet been
|
||||
* negotiated, returns TRUE for no good reason.
|
||||
*
|
||||
* Returns: TRUE if they are compatible or if the capabilities could not be
|
||||
* checked, FALSE if the capabilities are not compatible.
|
||||
|
@ -2604,9 +2574,7 @@ gst_pad_template_get_caps_by_name (GstPadTemplate *templ, const gchar *name)
|
|||
gboolean
|
||||
gst_pad_check_compatibility (GstPad *srcpad, GstPad *sinkpad)
|
||||
{
|
||||
g_return_val_if_fail (srcpad != NULL, FALSE);
|
||||
g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
|
||||
g_return_val_if_fail (sinkpad != NULL, FALSE);
|
||||
g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
|
||||
|
||||
if (GST_PAD_CAPS (srcpad) && GST_PAD_CAPS (sinkpad)) {
|
||||
|
@ -2631,14 +2599,13 @@ gst_pad_check_compatibility (GstPad *srcpad, GstPad *sinkpad)
|
|||
* gst_pad_get_peer:
|
||||
* @pad: a #GstPad to get the peer of.
|
||||
*
|
||||
* Gets the peer pad of @pad.
|
||||
* Gets the peer of @pad.
|
||||
*
|
||||
* Returns: the peer #GstPad.
|
||||
*/
|
||||
GstPad*
|
||||
gst_pad_get_peer (GstPad *pad)
|
||||
{
|
||||
g_return_val_if_fail (pad != NULL, NULL);
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
|
||||
|
||||
return GST_PAD (GST_PAD_PEER (pad));
|
||||
|
@ -2646,10 +2613,10 @@ gst_pad_get_peer (GstPad *pad)
|
|||
|
||||
/**
|
||||
* gst_pad_get_allowed_caps:
|
||||
* @pad: a #GstPad to get the allowed caps of.
|
||||
* @pad: a real #GstPad.
|
||||
*
|
||||
* Gets the capabilities of the allowed media types that can
|
||||
* flow through this pad. The caller must free the resulting caps.
|
||||
* Gets the capabilities of the allowed media types that can flow through @pad.
|
||||
* The caller must free the resulting caps.
|
||||
*
|
||||
* Returns: the allowed #GstCaps of the pad link. Free the caps when
|
||||
* you no longer need it.
|
||||
|
@ -2663,7 +2630,6 @@ gst_pad_get_allowed_caps (GstPad *pad)
|
|||
GstCaps *icaps;
|
||||
GstPadLink *link;
|
||||
|
||||
g_return_val_if_fail (pad != NULL, NULL);
|
||||
g_return_val_if_fail (GST_IS_REAL_PAD (pad), NULL);
|
||||
|
||||
GST_CAT_DEBUG (GST_CAT_PROPERTIES, "get allowed caps of %s:%s",
|
||||
|
@ -2717,12 +2683,14 @@ gst_pad_caps_change_notify (GstPad *pad)
|
|||
gboolean
|
||||
gst_pad_recover_caps_error (GstPad *pad, const GstCaps *allowed)
|
||||
{
|
||||
/* FIXME */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* FIXME 0.9: Is it so difficult to write SOURCE? */
|
||||
/**
|
||||
* gst_pad_alloc_buffer:
|
||||
* @pad: a #GstPad to get the buffer from.
|
||||
* @pad: a source #GstPad.
|
||||
*
|
||||
* Allocates a new, empty buffer optimized to push to pad @pad. This
|
||||
* function only works if @pad is a src pad.
|
||||
|
@ -2734,7 +2702,6 @@ gst_pad_alloc_buffer (GstPad *pad, guint64 offset, gint size)
|
|||
{
|
||||
GstRealPad *peer;
|
||||
|
||||
g_return_val_if_fail (pad != NULL, NULL);
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
|
||||
g_return_val_if_fail (GST_PAD_IS_SRC (pad), NULL);
|
||||
|
||||
|
@ -2950,10 +2917,11 @@ gst_ghost_pad_save_thyself (GstPad *pad, xmlNodePtr parent)
|
|||
|
||||
/**
|
||||
* gst_pad_push:
|
||||
* @pad: a #GstPad to push the buffer out of.
|
||||
* @pad: a source #GstPad.
|
||||
* @data: the #GstData to push.
|
||||
*
|
||||
* Pushes a buffer or an event to the peer of @pad. @pad must be linked.
|
||||
* Pushes a buffer or an event to the peer of @pad. @pad must be linked. May
|
||||
* only be called by @pad's parent.
|
||||
*/
|
||||
void
|
||||
gst_pad_push (GstPad *pad, GstData *data)
|
||||
|
@ -3016,9 +2984,10 @@ gst_pad_push (GstPad *pad, GstData *data)
|
|||
|
||||
/**
|
||||
* gst_pad_pull:
|
||||
* @pad: a #GstPad to pull a buffer from.
|
||||
* @pad: a sink #GstPad.
|
||||
*
|
||||
* Pulls an event or a buffer from the peer pad.
|
||||
* Pulls an event or a buffer from the peer pad. May only be called by @pad's
|
||||
* parent.
|
||||
*
|
||||
* Returns: a new #GstData from the peer pad.
|
||||
*/
|
||||
|
@ -3070,9 +3039,10 @@ restart:
|
|||
|
||||
/**
|
||||
* gst_pad_selectv:
|
||||
* @padlist: a #GList of pads.
|
||||
* @padlist: a #GList of sink pads.
|
||||
*
|
||||
* Waits for a buffer on any of the list of pads.
|
||||
* Waits for a buffer on any of the list of pads. Each #GstPad in @padlist must
|
||||
* be owned by the calling code.
|
||||
*
|
||||
* Returns: the #GstPad that has a buffer available.
|
||||
* Use #gst_pad_pull() to get the buffer.
|
||||
|
@ -3087,9 +3057,10 @@ gst_pad_selectv (GList *padlist)
|
|||
return pad;
|
||||
}
|
||||
|
||||
/* FIXME 0.9: Don't allow the first pad to be NULL */
|
||||
/**
|
||||
* gst_pad_select:
|
||||
* @pad: a first #GstPad to perform the select on.
|
||||
* @pad: a first sink #GstPad to perform the select on.
|
||||
* @...: A NULL-terminated list of more pads to select on.
|
||||
*
|
||||
* Waits for a buffer on the given set of pads.
|
||||
|
@ -3342,7 +3313,7 @@ gst_pad_template_new (const gchar *name_template,
|
|||
const GstCaps*
|
||||
gst_pad_template_get_caps (GstPadTemplate *templ)
|
||||
{
|
||||
g_return_val_if_fail (templ != NULL, NULL);
|
||||
g_return_val_if_fail (GST_IS_PAD_TEMPLATE (templ), NULL);
|
||||
|
||||
return GST_PAD_TEMPLATE_CAPS (templ);
|
||||
}
|
||||
|
@ -3595,13 +3566,15 @@ gst_pad_event_default_dispatch (GstPad *pad, GstElement *element,
|
|||
{
|
||||
GList *orig, *pads;
|
||||
|
||||
GST_INFO_OBJECT (pad, "Sending event %p to all internally linked pads", event);
|
||||
|
||||
orig = pads = gst_pad_get_internal_links (pad);
|
||||
|
||||
while (pads) {
|
||||
GstPad *eventpad = GST_PAD (pads->data);
|
||||
pads = g_list_next (pads);
|
||||
|
||||
/* for all pads in the opposite direction that are linked */
|
||||
/* for all of the internally-linked pads that are actually linked */
|
||||
if (GST_PAD_IS_LINKED (eventpad)) {
|
||||
if (GST_PAD_DIRECTION (eventpad) == GST_PAD_SRC) {
|
||||
/* increase the refcount */
|
||||
|
@ -3628,7 +3601,11 @@ gst_pad_event_default_dispatch (GstPad *pad, GstElement *element,
|
|||
* @pad: a #GstPad to call the default event handler on.
|
||||
* @event: the #GstEvent to handle.
|
||||
*
|
||||
* Invokes the default event handler for the given pad.
|
||||
* Invokes the default event handler for the given pad. End-of-stream and
|
||||
* discontinuity events are handled specially, and then the event is sent to all
|
||||
* pads internally linked to @pad. Note that if there are many possible sink
|
||||
* pads that are internally linked to @pad, only one will be sent an event.
|
||||
* Multi-sinkpad elements should implement custom event handlers.
|
||||
*
|
||||
* Returns: TRUE if the event was sent succesfully.
|
||||
*/
|
||||
|
@ -3638,7 +3615,7 @@ gst_pad_event_default (GstPad *pad, GstEvent *event)
|
|||
GstElement *element;
|
||||
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
|
||||
g_return_val_if_fail (event, FALSE);
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
|
||||
element = GST_PAD_PARENT (pad);
|
||||
|
||||
|
@ -3695,7 +3672,7 @@ gst_pad_dispatcher (GstPad *pad, GstPadDispatcherFunction dispatch,
|
|||
GList *int_pads, *orig;
|
||||
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
|
||||
g_return_val_if_fail (data, FALSE);
|
||||
g_return_val_if_fail (dispatch != NULL, FALSE);
|
||||
|
||||
orig = int_pads = gst_pad_get_internal_links (pad);
|
||||
|
||||
|
@ -3732,7 +3709,7 @@ gst_pad_send_event (GstPad *pad, GstEvent *event)
|
|||
GstRealPad *rpad;
|
||||
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
|
||||
g_return_val_if_fail (event, FALSE);
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
|
||||
rpad = GST_PAD_REALIZE (pad);
|
||||
|
||||
|
@ -3790,8 +3767,8 @@ gst_pad_convert_default (GstPad *pad,
|
|||
GstPadConvertData data;
|
||||
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
|
||||
g_return_val_if_fail (dest_format, FALSE);
|
||||
g_return_val_if_fail (dest_value, FALSE);
|
||||
g_return_val_if_fail (dest_format != NULL, FALSE);
|
||||
g_return_val_if_fail (dest_value != NULL, FALSE);
|
||||
|
||||
data.src_format = src_format;
|
||||
data.src_value = src_value;
|
||||
|
@ -3822,8 +3799,8 @@ gst_pad_convert (GstPad *pad,
|
|||
GstRealPad *rpad;
|
||||
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
|
||||
g_return_val_if_fail (dest_format, FALSE);
|
||||
g_return_val_if_fail (dest_value, FALSE);
|
||||
g_return_val_if_fail (dest_format != NULL, FALSE);
|
||||
g_return_val_if_fail (dest_value != NULL, FALSE);
|
||||
|
||||
if (src_format == *dest_format) {
|
||||
*dest_value = src_value;
|
||||
|
@ -3871,8 +3848,8 @@ gst_pad_query_default (GstPad *pad, GstQueryType type,
|
|||
GstPadQueryData data;
|
||||
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
|
||||
g_return_val_if_fail (format, FALSE);
|
||||
g_return_val_if_fail (value, FALSE);
|
||||
g_return_val_if_fail (format != NULL, FALSE);
|
||||
g_return_val_if_fail (value != NULL, FALSE);
|
||||
|
||||
data.type = type;
|
||||
data.format = format;
|
||||
|
@ -3904,8 +3881,8 @@ gst_pad_query (GstPad *pad, GstQueryType type,
|
|||
GstRealPad *rpad;
|
||||
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
|
||||
g_return_val_if_fail (format, FALSE);
|
||||
g_return_val_if_fail (value, FALSE);
|
||||
g_return_val_if_fail (format != NULL, FALSE);
|
||||
g_return_val_if_fail (value != NULL, FALSE);
|
||||
|
||||
rpad = GST_PAD_REALIZE (pad);
|
||||
|
||||
|
@ -3938,6 +3915,8 @@ gst_pad_get_formats_default (GstPad *pad)
|
|||
{
|
||||
GstFormat *result = NULL;
|
||||
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
|
||||
|
||||
gst_pad_dispatcher (pad, (GstPadDispatcherFunction)
|
||||
gst_pad_get_formats_dispatcher, &result);
|
||||
|
||||
|
@ -3957,7 +3936,7 @@ gst_pad_get_formats (GstPad *pad)
|
|||
{
|
||||
GstRealPad *rpad;
|
||||
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
|
||||
|
||||
rpad = GST_PAD_REALIZE (pad);
|
||||
|
||||
|
|
|
@ -183,20 +183,81 @@ struct _GstOptSchedulerGroup {
|
|||
};
|
||||
|
||||
|
||||
/* some group operations */
|
||||
static GstOptSchedulerGroup* ref_group (GstOptSchedulerGroup *group);
|
||||
#ifndef USE_COTHREADS
|
||||
/*
|
||||
static GstOptSchedulerGroup* ref_group_by_count (GstOptSchedulerGroup *group, gint count);
|
||||
* A group is a set of elements through which data can flow without switching
|
||||
* cothreads or without invoking the scheduler's run queue.
|
||||
*/
|
||||
#endif
|
||||
static GstOptSchedulerGroup* ref_group (GstOptSchedulerGroup *group);
|
||||
static GstOptSchedulerGroup* unref_group (GstOptSchedulerGroup *group);
|
||||
static GstOptSchedulerGroup* create_group (GstOptSchedulerChain *chain,
|
||||
GstElement *element,
|
||||
GstOptSchedulerGroupType type);
|
||||
static void destroy_group (GstOptSchedulerGroup *group);
|
||||
static GstOptSchedulerGroup* add_to_group (GstOptSchedulerGroup *group,
|
||||
GstElement *element);
|
||||
static GstOptSchedulerGroup* remove_from_group (GstOptSchedulerGroup *group,
|
||||
GstElement *element);
|
||||
static GstOptSchedulerGroup* merge_groups (GstOptSchedulerGroup *group1,
|
||||
GstOptSchedulerGroup *group2);
|
||||
static void setup_group_scheduler (GstOptScheduler *osched,
|
||||
GstOptSchedulerGroup *group);
|
||||
static void destroy_group_scheduler (GstOptSchedulerGroup *group);
|
||||
static void group_error_handler (GstOptSchedulerGroup *group);
|
||||
static void group_element_set_enabled (GstOptSchedulerGroup *group,
|
||||
GstElement *element, gboolean enabled);
|
||||
GstElement *element,
|
||||
gboolean enabled);
|
||||
static gboolean schedule_group (GstOptSchedulerGroup *group);
|
||||
|
||||
|
||||
/*
|
||||
* A chain is a set of groups that are linked to each other.
|
||||
*/
|
||||
static void destroy_chain (GstOptSchedulerChain *chain);
|
||||
static GstOptSchedulerChain* create_chain (GstOptScheduler *osched);
|
||||
static GstOptSchedulerChain* ref_chain (GstOptSchedulerChain *chain);
|
||||
static GstOptSchedulerChain* unref_chain (GstOptSchedulerChain *chain);
|
||||
static GstOptSchedulerChain* add_to_chain (GstOptSchedulerChain *chain,
|
||||
GstOptSchedulerGroup *group);
|
||||
static GstOptSchedulerChain* remove_from_chain (GstOptSchedulerChain *chain,
|
||||
GstOptSchedulerGroup *group);
|
||||
static GstOptSchedulerChain* merge_chains (GstOptSchedulerChain *chain1,
|
||||
GstOptSchedulerChain *chain2);
|
||||
static void chain_recursively_migrate_group (GstOptSchedulerChain *chain,
|
||||
GstOptSchedulerGroup *group);
|
||||
static void chain_group_set_enabled (GstOptSchedulerChain *chain,
|
||||
GstOptSchedulerGroup *group, gboolean enabled);
|
||||
GstOptSchedulerGroup *group,
|
||||
gboolean enabled);
|
||||
static void schedule_chain (GstOptSchedulerChain *chain);
|
||||
|
||||
|
||||
/*
|
||||
* The schedule functions are the entry points for cothreads, or called directly
|
||||
* by gst_opt_scheduler_schedule_run_queue
|
||||
*/
|
||||
static int get_group_schedule_function (int argc, char *argv[]);
|
||||
static int loop_group_schedule_function (int argc, char *argv[]);
|
||||
static int unknown_group_schedule_function (int argc, char *argv[]);
|
||||
|
||||
|
||||
/*
|
||||
* These wrappers are set on the pads as the chain handler (what happens when
|
||||
* gst_pad_push is called) or get handler (for gst_pad_pull).
|
||||
*/
|
||||
static void gst_opt_scheduler_loop_wrapper (GstPad *sinkpad, GstData *data);
|
||||
static GstData* gst_opt_scheduler_get_wrapper (GstPad *srcpad);
|
||||
static void gst_opt_scheduler_chain_wrapper (GstPad *sinkpad, GstData *data);
|
||||
|
||||
|
||||
/*
|
||||
* Without cothreads, gst_pad_push or gst_pad_pull on a loop-based group will
|
||||
* just queue the peer element on a list. We need to actually run the queue
|
||||
* instead of relying on cothreads to do the switch for us.
|
||||
*/
|
||||
#ifndef USE_COTHREADS
|
||||
static void gst_opt_scheduler_schedule_run_queue (GstOptScheduler *osched);
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Scheduler private data for an element
|
||||
*/
|
||||
|
@ -212,6 +273,10 @@ struct _GstOptSchedulerCtx {
|
|||
GstOptSchedulerCtxFlags flags; /* flags for this element */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Implementation of GstScheduler
|
||||
*/
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
|
@ -219,7 +284,6 @@ enum
|
|||
ARG_MAX_RECURSION,
|
||||
};
|
||||
|
||||
|
||||
static void gst_opt_scheduler_class_init (GstOptSchedulerClass *klass);
|
||||
static void gst_opt_scheduler_init (GstOptScheduler *scheduler);
|
||||
|
||||
|
@ -379,42 +443,6 @@ GST_PLUGIN_DEFINE (
|
|||
);
|
||||
|
||||
|
||||
static void
|
||||
destroy_chain (GstOptSchedulerChain *chain)
|
||||
{
|
||||
GstOptScheduler *osched;
|
||||
|
||||
GST_LOG ( "destroy chain %p", chain);
|
||||
|
||||
g_assert (chain->num_groups == 0);
|
||||
g_assert (chain->groups == NULL);
|
||||
|
||||
osched = chain->sched;
|
||||
osched->chains = g_slist_remove (osched->chains, chain);
|
||||
|
||||
gst_object_unref (GST_OBJECT (osched));
|
||||
|
||||
g_free (chain);
|
||||
}
|
||||
|
||||
static GstOptSchedulerChain*
|
||||
create_chain (GstOptScheduler *osched)
|
||||
{
|
||||
GstOptSchedulerChain *chain;
|
||||
|
||||
chain = g_new0 (GstOptSchedulerChain, 1);
|
||||
chain->sched = osched;
|
||||
chain->refcount = 1;
|
||||
chain->flags = GST_OPT_SCHEDULER_CHAIN_DISABLED;
|
||||
|
||||
gst_object_ref (GST_OBJECT (osched));
|
||||
osched->chains = g_slist_prepend (osched->chains, chain);
|
||||
|
||||
GST_LOG ( "new chain %p", chain);
|
||||
|
||||
return chain;
|
||||
}
|
||||
|
||||
static GstOptSchedulerChain*
|
||||
ref_chain (GstOptSchedulerChain *chain)
|
||||
{
|
||||
|
@ -439,6 +467,42 @@ unref_chain (GstOptSchedulerChain *chain)
|
|||
return chain;
|
||||
}
|
||||
|
||||
static GstOptSchedulerChain*
|
||||
create_chain (GstOptScheduler *osched)
|
||||
{
|
||||
GstOptSchedulerChain *chain;
|
||||
|
||||
chain = g_new0 (GstOptSchedulerChain, 1);
|
||||
chain->sched = osched;
|
||||
chain->refcount = 1;
|
||||
chain->flags = GST_OPT_SCHEDULER_CHAIN_DISABLED;
|
||||
|
||||
gst_object_ref (GST_OBJECT (osched));
|
||||
osched->chains = g_slist_prepend (osched->chains, chain);
|
||||
|
||||
GST_LOG ( "new chain %p", chain);
|
||||
|
||||
return chain;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_chain (GstOptSchedulerChain *chain)
|
||||
{
|
||||
GstOptScheduler *osched;
|
||||
|
||||
GST_LOG ( "destroy chain %p", chain);
|
||||
|
||||
g_assert (chain->num_groups == 0);
|
||||
g_assert (chain->groups == NULL);
|
||||
|
||||
osched = chain->sched;
|
||||
osched->chains = g_slist_remove (osched->chains, chain);
|
||||
|
||||
gst_object_unref (GST_OBJECT (osched));
|
||||
|
||||
g_free (chain);
|
||||
}
|
||||
|
||||
static GstOptSchedulerChain*
|
||||
add_to_chain (GstOptSchedulerChain *chain, GstOptSchedulerGroup *group)
|
||||
{
|
||||
|
@ -449,7 +513,17 @@ add_to_chain (GstOptSchedulerChain *chain, GstOptSchedulerGroup *group)
|
|||
group = ref_group (group);
|
||||
|
||||
group->chain = ref_chain (chain);
|
||||
|
||||
/* The first non-disabled group in the chain's group list will be the entry
|
||||
point for the chain. Because buffers can accumulate in loop elements' peer
|
||||
bufpens, we preferentially schedule loop groups before get groups to avoid
|
||||
unnecessary execution of get-based groups when the bufpens are already
|
||||
full. */
|
||||
if (group->type == GST_OPT_SCHEDULER_GROUP_LOOP)
|
||||
chain->groups = g_slist_prepend (chain->groups, group);
|
||||
else
|
||||
chain->groups = g_slist_append (chain->groups, group);
|
||||
|
||||
chain->num_groups++;
|
||||
|
||||
if (GST_OPT_SCHEDULER_GROUP_IS_ENABLED (group)) {
|
||||
|
@ -491,10 +565,17 @@ merge_chains (GstOptSchedulerChain *chain1, GstOptSchedulerChain *chain2)
|
|||
|
||||
GST_LOG ("merging chain %p and %p", chain1, chain2);
|
||||
|
||||
/* FIXME: document how chain2 can be NULL */
|
||||
if (chain1 == chain2 || chain2 == NULL)
|
||||
return chain1;
|
||||
|
||||
ref_chain (chain2);
|
||||
/* switch if it's more efficient */
|
||||
if (chain1->num_groups < chain2->num_groups) {
|
||||
GstOptSchedulerChain *tmp = chain2;
|
||||
chain2 = chain1;
|
||||
chain1 = tmp;
|
||||
}
|
||||
|
||||
walk = chain2->groups;
|
||||
while (walk) {
|
||||
GstOptSchedulerGroup *group = (GstOptSchedulerGroup *) walk->data;
|
||||
|
@ -503,17 +584,15 @@ merge_chains (GstOptSchedulerChain *chain1, GstOptSchedulerChain *chain2)
|
|||
GST_LOG ("reparenting group %p from chain %p to %p",
|
||||
group, chain2, chain1);
|
||||
|
||||
group->chain = NULL;
|
||||
chain2->num_groups--;
|
||||
chain2 = unref_chain (chain2);
|
||||
ref_group (group);
|
||||
|
||||
group->chain = ref_chain (chain1);
|
||||
chain1->groups = g_slist_prepend (chain1->groups, group);
|
||||
chain1->num_groups++;
|
||||
remove_from_chain (chain2, group);
|
||||
add_to_chain (chain1, group);
|
||||
|
||||
unref_group (group);
|
||||
}
|
||||
g_slist_free (chain2->groups);
|
||||
chain2->groups = NULL;
|
||||
unref_chain (chain2);
|
||||
|
||||
/* chain2 is now freed, if nothing else was referencing it before */
|
||||
|
||||
return chain1;
|
||||
}
|
||||
|
@ -521,8 +600,8 @@ merge_chains (GstOptSchedulerChain *chain1, GstOptSchedulerChain *chain2)
|
|||
static void
|
||||
chain_group_set_enabled (GstOptSchedulerChain *chain, GstOptSchedulerGroup *group, gboolean enabled)
|
||||
{
|
||||
g_assert (chain != NULL);
|
||||
g_assert (group != NULL);
|
||||
g_assert (chain != NULL);
|
||||
|
||||
GST_LOG ("request to %d group %p in chain %p, have %d groups enabled out of %d",
|
||||
enabled, group, chain, chain->num_enabled, chain->num_groups);
|
||||
|
@ -539,6 +618,10 @@ chain_group_set_enabled (GstOptSchedulerChain *chain, GstOptSchedulerGroup *grou
|
|||
GST_DEBUG ("enable group %p in chain %p, now %d groups enabled out of %d", group, chain,
|
||||
chain->num_enabled, chain->num_groups);
|
||||
|
||||
/* OK to call even if the scheduler (cothread context / schedulerfunc) was
|
||||
setup already -- will get destroyed when the group is destroyed */
|
||||
setup_group_scheduler (chain->sched, group);
|
||||
|
||||
if (chain->num_enabled == chain->num_groups) {
|
||||
GST_DEBUG ("enable chain %p", chain);
|
||||
GST_OPT_SCHEDULER_CHAIN_ENABLE (chain);
|
||||
|
@ -594,28 +677,13 @@ ref_group (GstOptSchedulerGroup *group)
|
|||
return group;
|
||||
}
|
||||
|
||||
#ifndef USE_COTHREADS
|
||||
/* remove me
|
||||
static GstOptSchedulerGroup*
|
||||
ref_group_by_count (GstOptSchedulerGroup *group, gint count)
|
||||
{
|
||||
GST_LOG ("ref group %p %d->%d", group,
|
||||
group->refcount, group->refcount+count);
|
||||
|
||||
group->refcount += count;
|
||||
|
||||
return group;
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
|
||||
static GstOptSchedulerGroup*
|
||||
unref_group (GstOptSchedulerGroup *group)
|
||||
{
|
||||
GST_LOG ("unref group %p %d->%d", group,
|
||||
group->refcount, group->refcount-1);
|
||||
|
||||
if (--group->refcount == 1) {
|
||||
if (--group->refcount == 0) {
|
||||
destroy_group (group);
|
||||
group = NULL;
|
||||
}
|
||||
|
@ -623,6 +691,42 @@ unref_group (GstOptSchedulerGroup *group)
|
|||
return group;
|
||||
}
|
||||
|
||||
static GstOptSchedulerGroup*
|
||||
create_group (GstOptSchedulerChain *chain, GstElement *element,
|
||||
GstOptSchedulerGroupType type)
|
||||
{
|
||||
GstOptSchedulerGroup *group;
|
||||
|
||||
group = g_new0 (GstOptSchedulerGroup, 1);
|
||||
GST_LOG ("new group %p", group);
|
||||
group->refcount = 1; /* float... */
|
||||
group->flags = GST_OPT_SCHEDULER_GROUP_DISABLED;
|
||||
group->type = type;
|
||||
|
||||
add_to_group (group, element);
|
||||
add_to_chain (chain, group);
|
||||
group = unref_group (group); /* ...and sink. */
|
||||
|
||||
/* group's refcount is now 2 (one for the element, one for the chain) */
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_group (GstOptSchedulerGroup *group)
|
||||
{
|
||||
GST_LOG ("destroy group %p", group);
|
||||
|
||||
g_assert (group != NULL);
|
||||
g_assert (group->elements == NULL);
|
||||
g_assert (group->chain == NULL);
|
||||
|
||||
if (group->flags & GST_OPT_SCHEDULER_GROUP_SCHEDULABLE)
|
||||
destroy_group_scheduler (group);
|
||||
|
||||
g_free (group);
|
||||
}
|
||||
|
||||
static GstOptSchedulerGroup*
|
||||
add_to_group (GstOptSchedulerGroup *group, GstElement *element)
|
||||
{
|
||||
|
@ -639,6 +743,7 @@ add_to_group (GstOptSchedulerGroup *group, GstElement *element)
|
|||
|
||||
g_assert (GST_ELEMENT_SCHED_GROUP (element) == NULL);
|
||||
|
||||
/* Ref the group... */
|
||||
GST_ELEMENT_SCHED_GROUP (element) = ref_group (group);
|
||||
|
||||
gst_object_ref (GST_OBJECT (element));
|
||||
|
@ -649,28 +754,100 @@ add_to_group (GstOptSchedulerGroup *group, GstElement *element)
|
|||
group_element_set_enabled (group, element, TRUE);
|
||||
}
|
||||
|
||||
/* Ref the group... */
|
||||
ref_group (group);
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
static GstOptSchedulerGroup*
|
||||
create_group (GstOptSchedulerChain *chain, GstElement *element)
|
||||
remove_from_group (GstOptSchedulerGroup *group, GstElement *element)
|
||||
{
|
||||
GstOptSchedulerGroup *group;
|
||||
GST_DEBUG ("removing element \"%s\" from group %p", GST_ELEMENT_NAME (element), group);
|
||||
|
||||
group = g_new0 (GstOptSchedulerGroup, 1);
|
||||
GST_LOG ("new group %p", group);
|
||||
group->refcount = 1;
|
||||
group->flags = GST_OPT_SCHEDULER_GROUP_DISABLED;
|
||||
g_assert (group != NULL);
|
||||
g_assert (element != NULL);
|
||||
g_assert (GST_ELEMENT_SCHED_GROUP (element) == group);
|
||||
|
||||
add_to_group (group, element);
|
||||
add_to_chain (chain, group);
|
||||
group->elements = g_slist_remove (group->elements, element);
|
||||
group->num_elements--;
|
||||
|
||||
/* if the element was an entry point in the group, clear the group's
|
||||
* entry point */
|
||||
if (group->entry == element) {
|
||||
group->entry = NULL;
|
||||
}
|
||||
|
||||
GST_ELEMENT_SCHED_GROUP (element) = NULL;
|
||||
gst_object_unref (GST_OBJECT (element));
|
||||
|
||||
if (group->num_elements == 0) {
|
||||
GST_LOG ("group %p is now empty", group);
|
||||
/* don't know in what case group->chain would be NULL, but putting this here
|
||||
in deference to 0.8 -- remove me in 0.9 */
|
||||
if (group->chain) {
|
||||
GST_LOG ("removing group %p from its chain", group);
|
||||
chain_group_set_enabled (group->chain, group, FALSE);
|
||||
remove_from_chain (group->chain, group);
|
||||
}
|
||||
}
|
||||
group = unref_group (group);
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
/* FIXME need to check if the groups are of the same type -- otherwise need to
|
||||
setup the scheduler again, if it is setup */
|
||||
static GstOptSchedulerGroup*
|
||||
merge_groups (GstOptSchedulerGroup *group1, GstOptSchedulerGroup *group2)
|
||||
{
|
||||
g_assert (group1 != NULL);
|
||||
|
||||
GST_DEBUG ("merging groups %p and %p", group1, group2);
|
||||
|
||||
if (group1 == group2 || group2 == NULL)
|
||||
return group1;
|
||||
|
||||
while (group2 && group2->elements) {
|
||||
GstElement *element = (GstElement *)group2->elements->data;
|
||||
|
||||
group2 = remove_from_group (group2, element);
|
||||
add_to_group (group1, element);
|
||||
}
|
||||
|
||||
return group1;
|
||||
}
|
||||
|
||||
/* setup the scheduler context for a group. The right schedule function
|
||||
* is selected based on the group type and cothreads are created if
|
||||
* needed */
|
||||
static void
|
||||
setup_group_scheduler (GstOptScheduler *osched, GstOptSchedulerGroup *group)
|
||||
{
|
||||
GroupScheduleFunction wrapper;
|
||||
|
||||
wrapper = unknown_group_schedule_function;
|
||||
|
||||
/* figure out the wrapper function for this group */
|
||||
if (group->type == GST_OPT_SCHEDULER_GROUP_GET)
|
||||
wrapper = get_group_schedule_function;
|
||||
else if (group->type == GST_OPT_SCHEDULER_GROUP_LOOP)
|
||||
wrapper = loop_group_schedule_function;
|
||||
|
||||
#ifdef USE_COTHREADS
|
||||
if (!(group->flags & GST_OPT_SCHEDULER_GROUP_SCHEDULABLE)) {
|
||||
do_cothread_create (group->cothread, osched->context,
|
||||
(cothread_func) wrapper, 0, (char **) group);
|
||||
}
|
||||
else {
|
||||
do_cothread_setfunc (group->cothread, osched->context,
|
||||
(cothread_func) wrapper, 0, (char **) group);
|
||||
}
|
||||
#else
|
||||
group->schedulefunc = wrapper;
|
||||
group->argc = 0;
|
||||
group->argv = (char **) group;
|
||||
#endif
|
||||
group->flags |= GST_OPT_SCHEDULER_GROUP_SCHEDULABLE;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_group_scheduler (GstOptSchedulerGroup *group)
|
||||
{
|
||||
|
@ -693,71 +870,6 @@ destroy_group_scheduler (GstOptSchedulerGroup *group)
|
|||
group->flags &= ~GST_OPT_SCHEDULER_GROUP_SCHEDULABLE;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_group (GstOptSchedulerGroup *group)
|
||||
{
|
||||
GST_LOG ("destroy group %p", group);
|
||||
|
||||
g_assert (group != NULL);
|
||||
g_assert (group->elements == NULL);
|
||||
|
||||
remove_from_chain (group->chain, group);
|
||||
|
||||
if (group->flags & GST_OPT_SCHEDULER_GROUP_SCHEDULABLE)
|
||||
destroy_group_scheduler (group);
|
||||
|
||||
g_free (group);
|
||||
}
|
||||
|
||||
static GstOptSchedulerGroup*
|
||||
remove_from_group (GstOptSchedulerGroup *group, GstElement *element)
|
||||
{
|
||||
GST_DEBUG ("removing element \"%s\" from group %p", GST_ELEMENT_NAME (element), group);
|
||||
|
||||
g_assert (group != NULL);
|
||||
g_assert (element != NULL);
|
||||
g_assert (GST_ELEMENT_SCHED_GROUP (element) == group);
|
||||
|
||||
group->elements = g_slist_remove (group->elements, element);
|
||||
group->num_elements--;
|
||||
|
||||
/* if the element was an entry point in the group, clear the group's
|
||||
* entry point */
|
||||
if (group->entry == element) {
|
||||
group->entry = NULL;
|
||||
}
|
||||
|
||||
GST_ELEMENT_SCHED_GROUP (element) = NULL;
|
||||
gst_object_unref (GST_OBJECT (element));
|
||||
|
||||
if (group->num_elements == 0) {
|
||||
group = unref_group (group);
|
||||
}
|
||||
group = unref_group (group);
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
static GstOptSchedulerGroup*
|
||||
merge_groups (GstOptSchedulerGroup *group1, GstOptSchedulerGroup *group2)
|
||||
{
|
||||
g_assert (group1 != NULL);
|
||||
|
||||
GST_DEBUG ("merging groups %p and %p", group1, group2);
|
||||
|
||||
if (group1 == group2 || group2 == NULL)
|
||||
return group1;
|
||||
|
||||
while (group2 && group2->elements) {
|
||||
GstElement *element = (GstElement *)group2->elements->data;
|
||||
|
||||
group2 = remove_from_group (group2, element);
|
||||
add_to_group (group1, element);
|
||||
}
|
||||
|
||||
return group1;
|
||||
}
|
||||
|
||||
static void
|
||||
group_error_handler (GstOptSchedulerGroup *group)
|
||||
{
|
||||
|
@ -779,6 +891,11 @@ group_element_set_enabled (GstOptSchedulerGroup *group, GstElement *element, gbo
|
|||
GST_LOG ("request to %d element %s in group %p, have %d elements enabled out of %d",
|
||||
enabled, GST_ELEMENT_NAME (element), group, group->num_enabled, group->num_elements);
|
||||
|
||||
/* Note that if an unlinked PLAYING element is added to a bin, we have to
|
||||
create a new group to hold the element, and this function will be called
|
||||
before the group is added to the chain. Thus we have a valid case for
|
||||
group->chain==NULL. */
|
||||
|
||||
if (enabled) {
|
||||
if (group->num_enabled < group->num_elements)
|
||||
group->num_enabled++;
|
||||
|
@ -787,10 +904,15 @@ group_element_set_enabled (GstOptSchedulerGroup *group, GstElement *element, gbo
|
|||
GST_ELEMENT_NAME (element), group, group->num_enabled, group->num_elements);
|
||||
|
||||
if (group->num_enabled == group->num_elements) {
|
||||
if (!group->chain) {
|
||||
GST_DEBUG ("enable chainless group %p", group);
|
||||
GST_OPT_SCHEDULER_GROUP_ENABLE (group);
|
||||
} else {
|
||||
GST_LOG ("enable group %p", group);
|
||||
chain_group_set_enabled (group->chain, group, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (group->num_enabled > 0)
|
||||
group->num_enabled--;
|
||||
|
@ -799,11 +921,16 @@ group_element_set_enabled (GstOptSchedulerGroup *group, GstElement *element, gbo
|
|||
GST_ELEMENT_NAME (element), group, group->num_enabled, group->num_elements);
|
||||
|
||||
if (group->num_enabled == 0) {
|
||||
if (!group->chain) {
|
||||
GST_DEBUG ("disable chainless group %p", group);
|
||||
GST_OPT_SCHEDULER_GROUP_DISABLE (group);
|
||||
} else {
|
||||
GST_LOG ("disable group %p", group);
|
||||
chain_group_set_enabled (group->chain, group, FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* a group is scheduled by doing a cothread switch to it or
|
||||
* by calling the schedule function. In the non-cothread case
|
||||
|
@ -855,9 +982,12 @@ schedule_group (GstOptSchedulerGroup *group)
|
|||
static void
|
||||
gst_opt_scheduler_schedule_run_queue (GstOptScheduler *osched)
|
||||
{
|
||||
GST_LOG_OBJECT (osched, "entering scheduler run queue recursion %d %d",
|
||||
GST_LOG_OBJECT (osched, "running queue: %d groups, recursed %d times",
|
||||
g_list_length (osched->runqueue),
|
||||
osched->recursion, g_list_length (osched->runqueue));
|
||||
|
||||
/* note that we have a ref on each group on the queue (unref after running) */
|
||||
|
||||
/* make sure we don't exceed max_recursion */
|
||||
if (osched->recursion > osched->max_recursion) {
|
||||
osched->state = GST_OPT_SCHEDULER_STATE_ERROR;
|
||||
|
@ -872,7 +1002,7 @@ gst_opt_scheduler_schedule_run_queue (GstOptScheduler *osched)
|
|||
|
||||
group = (GstOptSchedulerGroup *) osched->runqueue->data;
|
||||
|
||||
/* runqueue hols refcount to group */
|
||||
/* runqueue holds refcount to group */
|
||||
osched->runqueue = g_list_remove (osched->runqueue, group);
|
||||
|
||||
GST_LOG_OBJECT (osched, "scheduling group %p", group);
|
||||
|
@ -945,7 +1075,7 @@ get_group_schedule_function (int argc, char *argv[])
|
|||
GstElement *entry = group->entry;
|
||||
const GList *pads = gst_element_get_pad_list (entry);
|
||||
|
||||
GST_LOG ("get wrapper of group %p", group);
|
||||
GST_LOG ("executing get-based group %p", group);
|
||||
|
||||
group->flags |= GST_OPT_SCHEDULER_GROUP_RUNNING;
|
||||
|
||||
|
@ -986,7 +1116,7 @@ loop_group_schedule_function (int argc, char *argv[])
|
|||
GstOptSchedulerGroup *group = (GstOptSchedulerGroup *) argv;
|
||||
GstElement *entry = group->entry;
|
||||
|
||||
GST_LOG ("loop wrapper of group %p", group);
|
||||
GST_LOG ("executing loop-based group %p", group);
|
||||
|
||||
group->flags |= GST_OPT_SCHEDULER_GROUP_RUNNING;
|
||||
|
||||
|
@ -1024,26 +1154,31 @@ gst_opt_scheduler_loop_wrapper (GstPad *sinkpad, GstData *data)
|
|||
{
|
||||
GstOptSchedulerGroup *group;
|
||||
GstOptScheduler *osched;
|
||||
|
||||
GST_LOG ("loop wrapper, putting buffer in bufpen");
|
||||
GstRealPad *peer;
|
||||
|
||||
group = GST_ELEMENT_SCHED_GROUP (GST_PAD_PARENT (sinkpad));
|
||||
osched = group->chain->sched;
|
||||
peer = GST_RPAD_PEER (sinkpad);
|
||||
|
||||
GST_LOG ("chain handler for loop-based pad %" GST_PTR_FORMAT, sinkpad);
|
||||
|
||||
#ifdef USE_COTHREADS
|
||||
if (GST_PAD_BUFLIST (GST_RPAD_PEER (sinkpad))) {
|
||||
if (GST_PAD_BUFLIST (peer)) {
|
||||
g_warning ("deadlock detected, disabling group %p", group);
|
||||
group_error_handler (group);
|
||||
}
|
||||
else {
|
||||
GST_PAD_BUFLIST (GST_RPAD_PEER (sinkpad)) = g_list_append (GST_PAD_BUFLIST (GST_RPAD_PEER (sinkpad)), data);
|
||||
GST_LOG ("queueing data %p on %s:%s's bufpen", data,
|
||||
GST_DEBUG_PAD_NAME (peer));
|
||||
GST_PAD_BUFLIST (peer) = g_list_append (GST_PAD_BUFLIST (peer), data);
|
||||
schedule_group (group);
|
||||
}
|
||||
#else
|
||||
GST_PAD_BUFLIST (GST_RPAD_PEER (sinkpad)) = g_list_append (GST_PAD_BUFLIST (GST_RPAD_PEER (sinkpad)), data);
|
||||
GST_LOG ("queueing data %p on %s:%s's bufpen", data,
|
||||
GST_DEBUG_PAD_NAME (peer));
|
||||
GST_PAD_BUFLIST (peer) = g_list_append (GST_PAD_BUFLIST (peer), data);
|
||||
if (!(group->flags & GST_OPT_SCHEDULER_GROUP_RUNNING)) {
|
||||
GST_LOG ("adding %p to runqueue", group);
|
||||
GST_LOG ("adding group %p to runqueue", group);
|
||||
if (!g_list_find (osched->runqueue, group))
|
||||
{
|
||||
ref_group (group);
|
||||
|
@ -1052,8 +1187,8 @@ gst_opt_scheduler_loop_wrapper (GstPad *sinkpad, GstData *data)
|
|||
}
|
||||
#endif
|
||||
|
||||
GST_LOG ("after loop wrapper buflist %d",
|
||||
g_list_length (GST_PAD_BUFLIST (GST_RPAD_PEER (sinkpad))));
|
||||
GST_LOG ("%d buffers left on %s:%s's bufpen after chain handler",
|
||||
g_list_length (GST_PAD_BUFLIST (peer)));
|
||||
}
|
||||
|
||||
/* this function is called by a loop based element that performs a
|
||||
|
@ -1067,15 +1202,14 @@ gst_opt_scheduler_get_wrapper (GstPad *srcpad)
|
|||
GstOptScheduler *osched;
|
||||
gboolean disabled;
|
||||
|
||||
GST_LOG ("get wrapper, removing buffer from bufpen");
|
||||
GST_LOG ("get handler for %" GST_PTR_FORMAT, srcpad);
|
||||
|
||||
/* first try to grab a queued buffer */
|
||||
if (GST_PAD_BUFLIST (srcpad)) {
|
||||
data = GST_PAD_BUFLIST (srcpad)->data;
|
||||
GST_PAD_BUFLIST (srcpad) = g_list_remove (GST_PAD_BUFLIST (srcpad), data);
|
||||
|
||||
GST_LOG ("get wrapper, returning queued data %d",
|
||||
g_list_length (GST_PAD_BUFLIST (srcpad)));
|
||||
GST_LOG ("returning popped queued data %p", data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
@ -1087,6 +1221,7 @@ gst_opt_scheduler_get_wrapper (GstPad *srcpad)
|
|||
disabled = FALSE;
|
||||
|
||||
do {
|
||||
GST_LOG ("scheduling upstream group %p to fill bufpen", group);
|
||||
#ifdef USE_COTHREADS
|
||||
schedule_group (group);
|
||||
#else
|
||||
|
@ -1099,9 +1234,9 @@ gst_opt_scheduler_get_wrapper (GstPad *srcpad)
|
|||
osched->runqueue = g_list_append (osched->runqueue, group);
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (osched, "recursing into scheduler group %p", group);
|
||||
GST_LOG ("recursing into scheduler group %p", group);
|
||||
gst_opt_scheduler_schedule_run_queue (osched);
|
||||
GST_LOG_OBJECT (osched, "return from recurse group %p", group);
|
||||
GST_LOG ("return from recurse group %p", group);
|
||||
|
||||
/* if the other group was disabled we might have to break out of the loop */
|
||||
disabled = GST_OPT_SCHEDULER_GROUP_IS_DISABLED (group);
|
||||
|
@ -1139,7 +1274,7 @@ gst_opt_scheduler_get_wrapper (GstPad *srcpad)
|
|||
}
|
||||
while (data == NULL);
|
||||
|
||||
GST_LOG ("get wrapper, returning data %p, queue length %d",
|
||||
GST_LOG ("get handler, returning data %p, queue length %d",
|
||||
data, g_list_length (GST_PAD_BUFLIST (srcpad)));
|
||||
|
||||
return data;
|
||||
|
@ -1207,44 +1342,9 @@ gst_opt_scheduler_event_wrapper (GstPad *srcpad, GstEvent *event)
|
|||
return GST_RPAD_EVENTFUNC (srcpad) (srcpad, event);
|
||||
}
|
||||
|
||||
|
||||
/* setup the scheduler context for a group. The right schedule function
|
||||
* is selected based on the group type and cothreads are created if
|
||||
* needed */
|
||||
static void
|
||||
setup_group_scheduler (GstOptScheduler *osched, GstOptSchedulerGroup *group)
|
||||
{
|
||||
GroupScheduleFunction wrapper;
|
||||
|
||||
wrapper = unknown_group_schedule_function;
|
||||
|
||||
/* figure out the wrapper function for this group */
|
||||
if (group->type == GST_OPT_SCHEDULER_GROUP_GET)
|
||||
wrapper = get_group_schedule_function;
|
||||
else if (group->type == GST_OPT_SCHEDULER_GROUP_LOOP)
|
||||
wrapper = loop_group_schedule_function;
|
||||
|
||||
#ifdef USE_COTHREADS
|
||||
if (!(group->flags & GST_OPT_SCHEDULER_GROUP_SCHEDULABLE)) {
|
||||
do_cothread_create (group->cothread, osched->context,
|
||||
(cothread_func) wrapper, 0, (char **) group);
|
||||
}
|
||||
else {
|
||||
do_cothread_setfunc (group->cothread, osched->context,
|
||||
(cothread_func) wrapper, 0, (char **) group);
|
||||
}
|
||||
#else
|
||||
group->schedulefunc = wrapper;
|
||||
group->argc = 0;
|
||||
group->argv = (char **) group;
|
||||
#endif
|
||||
group->flags |= GST_OPT_SCHEDULER_GROUP_SCHEDULABLE;
|
||||
}
|
||||
|
||||
static GstElementStateReturn
|
||||
gst_opt_scheduler_state_transition (GstScheduler *sched, GstElement *element, gint transition)
|
||||
{
|
||||
GstOptScheduler *osched = GST_OPT_SCHEDULER (sched);
|
||||
GstOptSchedulerGroup *group;
|
||||
GstElementStateReturn res = GST_STATE_SUCCESS;
|
||||
|
||||
|
@ -1288,7 +1388,6 @@ gst_opt_scheduler_state_transition (GstScheduler *sched, GstElement *element, gi
|
|||
}
|
||||
/* else construct the scheduling context of this group and enable it */
|
||||
else {
|
||||
setup_group_scheduler (osched, group);
|
||||
group_element_set_enabled (group, element, TRUE);
|
||||
}
|
||||
break;
|
||||
|
@ -1340,7 +1439,8 @@ get_group (GstElement *element, GstOptSchedulerGroup **group)
|
|||
* will also merge the chains.
|
||||
*/
|
||||
static GstOptSchedulerGroup*
|
||||
group_elements (GstOptScheduler *osched, GstElement *element1, GstElement *element2)
|
||||
group_elements (GstOptScheduler *osched, GstElement *element1, GstElement *element2,
|
||||
GstOptSchedulerGroupType type)
|
||||
{
|
||||
GstOptSchedulerGroup *group1, *group2, *group = NULL;
|
||||
|
||||
|
@ -1356,7 +1456,7 @@ group_elements (GstOptScheduler *osched, GstElement *element1, GstElement *eleme
|
|||
GST_ELEMENT_NAME (element1), GST_ELEMENT_NAME (element2));
|
||||
|
||||
chain = create_chain (osched);
|
||||
group = create_group (chain, element1);
|
||||
group = create_group (chain, element1, type);
|
||||
add_to_group (group, element2);
|
||||
}
|
||||
/* the first element has a group */
|
||||
|
@ -1548,9 +1648,8 @@ gst_opt_scheduler_add_element (GstScheduler *sched, GstElement *element)
|
|||
|
||||
chain = create_chain (osched);
|
||||
|
||||
group = create_group (chain, element);
|
||||
group = create_group (chain, element, GST_OPT_SCHEDULER_GROUP_LOOP);
|
||||
group->entry = element;
|
||||
group->type = GST_OPT_SCHEDULER_GROUP_LOOP;
|
||||
|
||||
GST_LOG ("added element \"%s\" as loop based entry", GST_ELEMENT_NAME (element));
|
||||
}
|
||||
|
@ -1733,13 +1832,13 @@ gst_opt_scheduler_pad_link (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad
|
|||
|
||||
/* the two elements should be put into the same group,
|
||||
* this also means that they are in the same chain automatically */
|
||||
group = group_elements (osched, element1, element2);
|
||||
group = group_elements (osched, element1, element2,
|
||||
GST_OPT_SCHEDULER_GROUP_GET);
|
||||
|
||||
/* if there is not yet an entry in the group, select the source
|
||||
* element as the entry point */
|
||||
if (!group->entry) {
|
||||
group->entry = element1;
|
||||
group->type = GST_OPT_SCHEDULER_GROUP_GET;
|
||||
|
||||
GST_DEBUG ("setting \"%s\" as entry point of _get-based group %p",
|
||||
GST_ELEMENT_NAME (element1), group);
|
||||
|
@ -1759,7 +1858,7 @@ gst_opt_scheduler_pad_link (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad
|
|||
* this also means that they are in the same chain automatically,
|
||||
* in case of a loop-based element1, there will be a group for element1 and
|
||||
* element2 will be added to it. */
|
||||
group_elements (osched, element1, element2);
|
||||
group_elements (osched, element1, element2, GST_OPT_SCHEDULER_GROUP_LOOP);
|
||||
break;
|
||||
case GST_OPT_GET_TO_LOOP:
|
||||
GST_LOG ("get to loop based link");
|
||||
|
@ -1770,7 +1869,7 @@ gst_opt_scheduler_pad_link (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad
|
|||
* this also means that they are in the same chain automatically,
|
||||
* element2 is loop-based so it already has a group where element1
|
||||
* will be added to */
|
||||
group_elements (osched, element1, element2);
|
||||
group_elements (osched, element1, element2, GST_OPT_SCHEDULER_GROUP_LOOP);
|
||||
break;
|
||||
case GST_OPT_CHAIN_TO_LOOP:
|
||||
case GST_OPT_LOOP_TO_LOOP:
|
||||
|
@ -1796,7 +1895,8 @@ gst_opt_scheduler_pad_link (GstScheduler *sched, GstPad *srcpad, GstPad *sinkpad
|
|||
/* create a new group for element1 as it cannot be merged into another group
|
||||
* here. we create the group in the same chain as the loop-based element. */
|
||||
GST_DEBUG ("creating new group for element %s", GST_ELEMENT_NAME (element1));
|
||||
group1 = create_group (group2->chain, element1);
|
||||
group1 = create_group (group2->chain, element1,
|
||||
GST_OPT_SCHEDULER_GROUP_LOOP);
|
||||
}
|
||||
else {
|
||||
/* both elements are already in a group, make sure they are added to
|
||||
|
@ -2052,7 +2152,7 @@ gst_opt_scheduler_iterate (GstScheduler *sched)
|
|||
|
||||
osched->state = GST_OPT_SCHEDULER_STATE_RUNNING;
|
||||
|
||||
GST_DEBUG ("iterating scheduler %p", sched);
|
||||
GST_DEBUG_OBJECT (sched, "iterating");
|
||||
|
||||
while (iterations) {
|
||||
gboolean scheduled = FALSE;
|
||||
|
@ -2066,6 +2166,7 @@ gst_opt_scheduler_iterate (GstScheduler *sched)
|
|||
ref_chain (chain);
|
||||
/* if the chain is not disabled, schedule it */
|
||||
if (!GST_OPT_SCHEDULER_CHAIN_IS_DISABLED (chain)) {
|
||||
GST_LOG ("scheduling chain %p", chain);
|
||||
schedule_chain (chain);
|
||||
scheduled = TRUE;
|
||||
}
|
||||
|
@ -2080,8 +2181,6 @@ gst_opt_scheduler_iterate (GstScheduler *sched)
|
|||
osched->state = GST_OPT_SCHEDULER_STATE_RUNNING;
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (sched, "iterate scheduled %p", chain);
|
||||
|
||||
chains = g_slist_next (chains);
|
||||
unref_chain (chain);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue