Correctly distribute clock/scheduler to elements

Original commit message from CVS:
* gst/elements/gstfakesink.c: (gst_fakesink_event):
* gst/elements/gstfakesrc.c: (gst_fakesrc_update_functions),
(gst_fakesrc_loop), (gst_fakesrc_activate):
* gst/elements/gstfilesrc.c: (gst_filesrc_init),
(gst_filesrc_getrange), (gst_filesrc_get), (gst_filesrc_loop):
* gst/gstbin.c: (gst_bin_class_init), (gst_bin_set_index),
(gst_bin_set_clock), (gst_bin_set_bus), (gst_bin_set_scheduler),
(gst_bin_add_func), (gst_bin_iterate_elements),
(gst_bin_change_state), (gst_bin_get_by_name_recurse_up):
* gst/gstcaps.c: (gst_caps_intersect):
* gst/gstelement.c: (gst_element_pads_activate),
(gst_element_change_state), (gst_element_create_task):
* gst/gstobject.c: (gst_object_class_init), (gst_object_ref),
(gst_object_unref), (gst_object_sink), (gst_object_dispose),
(gst_object_dispatch_properties_changed), (gst_object_set_name),
(gst_object_set_parent), (gst_object_unparent),
(gst_object_check_uniqueness), (gst_object_get_path_string):
* gst/gstpad.c: (gst_real_pad_init), (gst_real_pad_get_property),
(gst_pad_set_active), (gst_pad_is_active),
(gst_pad_set_blocked_async), (gst_pad_set_loop_function),
(gst_pad_set_getrange_function), (gst_pad_set_acceptcaps_function),
(gst_pad_set_fixatecaps_function), (gst_pad_set_setcaps_function),
(gst_pad_unlink), (gst_pad_link_prepare_filtered),
(gst_pad_link_filtered), (gst_pad_relink_filtered),
(gst_pad_get_caps), (gst_pad_set_caps), (gst_pad_configure_sink),
(gst_pad_configure_src), (gst_pad_realize),
(gst_pad_get_allowed_caps), (gst_pad_get_negotiated_caps),
(gst_pad_get_filter_caps), (gst_pad_alloc_buffer), (gst_pad_push),
(gst_pad_push_event):
* gst/gstpad.h:
* gst/gstpipeline.c: (gst_pipeline_init), (gst_pipeline_dispose),
(is_eos), (pipeline_bus_handler), (gst_pipeline_change_state),
(gst_pipeline_get_scheduler), (gst_pipeline_get_bus):
* gst/gstpipeline.h:
* gst/gstqueue.c: (gst_queue_init), (gst_queue_locked_flush),
(gst_queue_handle_sink_event), (gst_queue_chain), (gst_queue_loop),
(gst_queue_src_activate), (gst_queue_change_state):
* gst/gsttask.h:
* gst/gstutils.c: (gst_element_get_compatible_pad_filtered),
(gst_element_link_pads_filtered), (gst_element_unlink),
(gst_pad_can_link_filtered):
* gst/schedulers/threadscheduler.c: (gst_thread_scheduler_func):
* libs/gst/Makefile.am:
* tools/gst-inspect.c: (print_pad_info):
* tools/gst-launch.c: (main):
* tools/gst-xmlinspect.c: (print_element_info):
Correctly distribute clock/scheduler to elements
Caps intersection improvement.
MT fixes.
Work on scheduling simplifications, get rid of _pull and prepare
for scheduling setup.
More work on capsnego.
This commit is contained in:
Wim Taymans 2004-12-20 16:07:05 +00:00
parent ccb77fc69f
commit 457e99ab07
24 changed files with 850 additions and 462 deletions

View file

@ -1,3 +1,58 @@
2004-12-20 Wim Taymans <wim@fluendo.com>
* gst/elements/gstfakesink.c: (gst_fakesink_event):
* gst/elements/gstfakesrc.c: (gst_fakesrc_update_functions),
(gst_fakesrc_loop), (gst_fakesrc_activate):
* gst/elements/gstfilesrc.c: (gst_filesrc_init),
(gst_filesrc_getrange), (gst_filesrc_get), (gst_filesrc_loop):
* gst/gstbin.c: (gst_bin_class_init), (gst_bin_set_index),
(gst_bin_set_clock), (gst_bin_set_bus), (gst_bin_set_scheduler),
(gst_bin_add_func), (gst_bin_iterate_elements),
(gst_bin_change_state), (gst_bin_get_by_name_recurse_up):
* gst/gstcaps.c: (gst_caps_intersect):
* gst/gstelement.c: (gst_element_pads_activate),
(gst_element_change_state), (gst_element_create_task):
* gst/gstobject.c: (gst_object_class_init), (gst_object_ref),
(gst_object_unref), (gst_object_sink), (gst_object_dispose),
(gst_object_dispatch_properties_changed), (gst_object_set_name),
(gst_object_set_parent), (gst_object_unparent),
(gst_object_check_uniqueness), (gst_object_get_path_string):
* gst/gstpad.c: (gst_real_pad_init), (gst_real_pad_get_property),
(gst_pad_set_active), (gst_pad_is_active),
(gst_pad_set_blocked_async), (gst_pad_set_loop_function),
(gst_pad_set_getrange_function), (gst_pad_set_acceptcaps_function),
(gst_pad_set_fixatecaps_function), (gst_pad_set_setcaps_function),
(gst_pad_unlink), (gst_pad_link_prepare_filtered),
(gst_pad_link_filtered), (gst_pad_relink_filtered),
(gst_pad_get_caps), (gst_pad_set_caps), (gst_pad_configure_sink),
(gst_pad_configure_src), (gst_pad_realize),
(gst_pad_get_allowed_caps), (gst_pad_get_negotiated_caps),
(gst_pad_get_filter_caps), (gst_pad_alloc_buffer), (gst_pad_push),
(gst_pad_push_event):
* gst/gstpad.h:
* gst/gstpipeline.c: (gst_pipeline_init), (gst_pipeline_dispose),
(is_eos), (pipeline_bus_handler), (gst_pipeline_change_state),
(gst_pipeline_get_scheduler), (gst_pipeline_get_bus):
* gst/gstpipeline.h:
* gst/gstqueue.c: (gst_queue_init), (gst_queue_locked_flush),
(gst_queue_handle_sink_event), (gst_queue_chain), (gst_queue_loop),
(gst_queue_src_activate), (gst_queue_change_state):
* gst/gsttask.h:
* gst/gstutils.c: (gst_element_get_compatible_pad_filtered),
(gst_element_link_pads_filtered), (gst_element_unlink),
(gst_pad_can_link_filtered):
* gst/schedulers/threadscheduler.c: (gst_thread_scheduler_func):
* libs/gst/Makefile.am:
* tools/gst-inspect.c: (print_pad_info):
* tools/gst-launch.c: (main):
* tools/gst-xmlinspect.c: (print_element_info):
Correctly distribute clock/scheduler to elements
Caps intersection improvement.
MT fixes.
Work on scheduling simplifications, get rid of _pull and prepare
for scheduling setup.
More work on capsnego.
2004-12-14 Thomas Vander Stichele <thomas at apestaart dot org>
* check/gst/gstobject.c:

View file

@ -332,7 +332,7 @@ gst_fakesink_event (GstPad * pad, GstEvent * event)
{
gst_element_finish_preroll (GST_ELEMENT (fakesink),
GST_STREAM_GET_LOCK (pad));
gst_pipeline_post_message (GST_ELEMENT_MANAGER (fakesink),
gst_element_post_message (GST_ELEMENT (fakesink),
gst_message_new_eos (GST_OBJECT (fakesink)));
break;
}

View file

@ -189,8 +189,7 @@ static void gst_fakesrc_set_clock (GstElement * element, GstClock * clock);
static GstElementStateReturn gst_fakesrc_change_state (GstElement * element);
static GstFlowReturn gst_fakesrc_get (GstPad * pad, GstBuffer ** buffer);
static void gst_fakesrc_loop (GstElement * element);
static gboolean gst_fakesrc_loop (GstPad * pad);
static guint gst_fakesrc_signals[LAST_SIGNAL] = { 0 };
@ -471,13 +470,8 @@ gst_fakesrc_update_functions (GstFakeSrc * src)
while (pads) {
GstPad *pad = GST_PAD (pads->data);
if (src->loop_based) {
gst_pad_set_get_function (pad, NULL);
} else {
gst_pad_set_get_function (pad, GST_DEBUG_FUNCPTR (gst_fakesrc_get));
}
gst_pad_set_activate_function (pad, gst_fakesrc_activate);
gst_pad_set_loop_function (pad, gst_fakesrc_loop);
gst_pad_set_event_function (pad, gst_fakesrc_event_handler);
gst_pad_set_event_mask_function (pad, gst_fakesrc_get_event_mask);
gst_pad_set_query_function (pad, gst_fakesrc_query);
@ -784,20 +778,16 @@ gst_fakesrc_create_buffer (GstFakeSrc * src)
return buf;
}
static GstFlowReturn
gst_fakesrc_get (GstPad * pad, GstBuffer ** buffer)
static gboolean
gst_fakesrc_loop (GstPad * pad)
{
GstFakeSrc *src;
GstBuffer *buf;
GstClockTime time;
GstFlowReturn result = GST_FLOW_OK;
g_return_val_if_fail (pad != NULL, GST_FLOW_ERROR);
gboolean result = TRUE;
src = GST_FAKESRC (GST_OBJECT_PARENT (pad));
g_return_val_if_fail (GST_IS_FAKESRC (src), GST_FLOW_ERROR);
GST_STREAM_LOCK (pad);
if (src->need_flush) {
src->need_flush = FALSE;
@ -809,14 +799,14 @@ gst_fakesrc_get (GstPad * pad, GstBuffer ** buffer)
gst_pad_push_event (pad, gst_event_new (GST_EVENT_SEGMENT_DONE));
} else {
gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
result = GST_FLOW_UNEXPECTED;
result = FALSE;
goto done;
}
}
if (src->rt_num_buffers == 0) {
gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
result = GST_FLOW_UNEXPECTED;
result = FALSE;
goto done;
} else {
if (src->rt_num_buffers > 0)
@ -826,7 +816,7 @@ gst_fakesrc_get (GstPad * pad, GstBuffer ** buffer)
if (src->eos) {
GST_INFO ("fakesrc is setting eos on pad");
gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
result = GST_FLOW_UNEXPECTED;
result = FALSE;
goto done;
}
@ -866,7 +856,7 @@ gst_fakesrc_get (GstPad * pad, GstBuffer ** buffer)
src->bytes_sent += GST_BUFFER_SIZE (buf);
*buffer = buf;
gst_pad_push (pad, buf);
done:
GST_STREAM_UNLOCK (pad);
@ -874,26 +864,24 @@ done:
return result;
}
#if 0
/**
* gst_fakesrc_loop:
* @element: the faksesrc to loop
*
* generate an empty buffer and push it to the next element.
*/
static void
gst_fakesrc_loop (GstElement * element)
static gboolean
gst_fakesrc_loop (GstPad * pad)
{
GstFakeSrc *src;
const GList *pads;
GstTask *task;
g_return_if_fail (element != NULL);
g_return_if_fail (GST_IS_FAKESRC (element));
src = GST_FAKESRC (element);
src = GST_FAKESRC (GST_PAD_PARENT (pad));
task = src->task;
pads = element->pads;
pads = GST_ELEMENT (src)->pads;
while (pads) {
GstPad *pad = GST_PAD (pads->data);
@ -902,22 +890,21 @@ gst_fakesrc_loop (GstElement * element)
ret = gst_fakesrc_get (pad, &buffer);
if (ret != GST_FLOW_OK) {
gst_task_stop (task);
return;
return FALSE;
}
ret = gst_pad_push (pad, buffer);
if (ret != GST_FLOW_OK) {
gst_task_stop (task);
return;
return FALSE;
}
if (src->eos) {
gst_task_stop (task);
return;
return FALSE;
}
pads = g_list_next (pads);
}
return TRUE;
}
#endif
static gboolean
gst_fakesrc_activate (GstPad * pad, gboolean active)
@ -929,11 +916,11 @@ gst_fakesrc_activate (GstPad * pad, gboolean active)
if (active) {
/* if we have a scheduler we can start the task */
if (GST_ELEMENT_MANAGER (fakesrc)) {
if (GST_ELEMENT_SCHEDULER (fakesrc)) {
GST_STREAM_LOCK (pad);
fakesrc->task =
gst_scheduler_create_task (GST_ELEMENT_MANAGER (fakesrc)->scheduler,
(GstTaskFunction) gst_fakesrc_loop, fakesrc);
gst_scheduler_create_task (GST_ELEMENT_SCHEDULER (fakesrc),
(GstTaskFunction) gst_fakesrc_loop, pad);
gst_task_start (fakesrc->task);
GST_STREAM_UNLOCK (pad);

View file

@ -171,6 +171,8 @@ static void gst_filesrc_get_property (GObject * object, guint prop_id,
static gboolean gst_filesrc_check_filesize (GstFileSrc * src);
static GstFlowReturn gst_filesrc_get (GstPad * pad, GstBuffer ** buffer);
static GstFlowReturn gst_filesrc_getrange (GstPad * pad, guint64 offset,
guint length, GstBuffer ** buffer);
static gboolean gst_filesrc_srcpad_event (GstPad * pad, GstEvent * event);
static gboolean gst_filesrc_srcpad_query (GstPad * pad, GstQueryType type,
GstFormat * format, gint64 * value);
@ -248,7 +250,7 @@ gst_filesrc_init (GstFileSrc * src)
src->srcpad =
gst_pad_new_from_template (gst_static_pad_template_get (&srctemplate),
"src");
gst_pad_set_get_function (src->srcpad, gst_filesrc_get);
gst_pad_set_getrange_function (src->srcpad, gst_filesrc_getrange);
gst_pad_set_activate_function (src->srcpad, gst_filesrc_activate);
gst_pad_set_event_function (src->srcpad, gst_filesrc_srcpad_event);
gst_pad_set_event_mask_function (src->srcpad, gst_filesrc_get_event_mask);
@ -688,13 +690,27 @@ gst_filesrc_get_read (GstFileSrc * src)
return GST_DATA (buf);
}
static GstFlowReturn
gst_filesrc_getrange (GstPad * pad, guint64 offset, guint length,
GstBuffer ** buffer)
{
GstFileSrc *src;
src = GST_FILESRC (GST_PAD_PARENT (pad));
src->curoffset = offset;
src->block_size = length;
return gst_filesrc_get (pad, buffer);
}
static GstFlowReturn
gst_filesrc_get (GstPad * pad, GstBuffer ** buffer)
{
GstFileSrc *src;
GstData *data;
src = GST_FILESRC (gst_pad_get_parent (pad));
src = GST_FILESRC (GST_PAD_PARENT (pad));
g_return_val_if_fail (GST_FLAG_IS_SET (src, GST_FILESRC_OPEN),
GST_FLOW_WRONG_STATE);
@ -863,24 +879,25 @@ gst_filesrc_close_file (GstFileSrc * src)
GST_FLAG_UNSET (src, GST_FILESRC_OPEN);
}
static void
static gboolean
gst_filesrc_loop (GstElement * element)
{
GstFileSrc *filesrc;
GstFlowReturn result;
gboolean result;
GstBuffer *buffer;
filesrc = GST_FILESRC (element);
result = gst_filesrc_get (filesrc->srcpad, &buffer);
if (result != GST_FLOW_OK) {
gst_task_stop (filesrc->task);
return;
return FALSE;
}
result = gst_pad_push (filesrc->srcpad, buffer);
if (result != GST_FLOW_OK) {
gst_task_stop (filesrc->task);
return FALSE;
}
return TRUE;
}

View file

@ -61,6 +61,8 @@ static void gst_bin_set_index (GstElement * element, GstIndex * index);
#endif
static void gst_bin_set_clock (GstElement * element, GstClock * clock);
static GstClock *gst_bin_get_clock (GstElement * element);
static void gst_bin_set_bus (GstElement * element, GstBus * bus);
static void gst_bin_set_scheduler (GstElement * element, GstScheduler * sched);
static gboolean gst_bin_add_func (GstBin * bin, GstElement * element);
static gboolean gst_bin_remove_func (GstBin * bin, GstElement * element);
@ -167,6 +169,8 @@ gst_bin_class_init (GstBinClass * klass)
#endif
gstelement_class->get_clock = GST_DEBUG_FUNCPTR (gst_bin_get_clock);
gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_bin_set_clock);
gstelement_class->set_bus = GST_DEBUG_FUNCPTR (gst_bin_set_bus);
gstelement_class->set_scheduler = GST_DEBUG_FUNCPTR (gst_bin_set_scheduler);
klass->add_element = GST_DEBUG_FUNCPTR (gst_bin_add_func);
klass->remove_element = GST_DEBUG_FUNCPTR (gst_bin_remove_func);
@ -252,10 +256,47 @@ gst_bin_get_clock (GstElement * element)
return result;
}
static void
gst_bin_set_bus (GstElement * element, GstBus * bus)
{
GList *children;
GstBin *bin;
bin = GST_BIN (element);
parent_class->set_bus (element, bus);
GST_LOCK (bin);
for (children = bin->children; children; children = g_list_next (children)) {
GstElement *child = GST_ELEMENT (children->data);
gst_element_set_bus (child, bus);
}
GST_UNLOCK (bin);
}
static void
gst_bin_set_scheduler (GstElement * element, GstScheduler * sched)
{
GList *children;
GstBin *bin;
bin = GST_BIN (element);
parent_class->set_scheduler (element, sched);
GST_LOCK (bin);
for (children = bin->children; children; children = g_list_next (children)) {
GstElement *child = GST_ELEMENT (children->data);
gst_element_set_scheduler (child, sched);
}
GST_UNLOCK (bin);
}
static gboolean
gst_bin_add_func (GstBin * bin, GstElement * element)
{
GstPipeline *manager;
gchar *elem_name;
/* we obviously can't add ourself to ourself */
@ -283,8 +324,9 @@ gst_bin_add_func (GstBin * bin, GstElement * element)
bin->numchildren++;
bin->children_cookie++;
manager = GST_ELEMENT (bin)->manager;
gst_element_set_manager (element, manager);
gst_element_set_manager (element, GST_ELEMENT (bin)->manager);
gst_element_set_bus (element, GST_ELEMENT (bin)->bus);
gst_element_set_scheduler (element, GST_ELEMENT (bin)->scheduler);
GST_UNLOCK (bin);

View file

@ -872,10 +872,11 @@ gst_caps_structure_union (const GstStructure * struct1,
GstCaps *
gst_caps_intersect (const GstCaps * caps1, const GstCaps * caps2)
{
int i, j;
int i, j, k;
GstStructure *struct1;
GstStructure *struct2;
GstCaps *dest;
GstStructure *istruct;
g_return_val_if_fail (GST_IS_CAPS (caps1), NULL);
g_return_val_if_fail (GST_IS_CAPS (caps2), NULL);
@ -889,38 +890,42 @@ gst_caps_intersect (const GstCaps * caps1, const GstCaps * caps2)
return gst_caps_copy (caps1);
dest = gst_caps_new_empty ();
/* run zigzag on top line first
*
* 1 2 4 ..
* 3 5 ..
* 6 ..
* ..
/* run zigzag on top line then right line, this preserves the caps order
* much better than a simple loop.
*
* This algorithm zigzags over the caps structures as demonstrated in
* the folowing matrix:
*
* caps1
* +-------------
* | 1 2 4 7
* caps2 | 3 5 8 10
* | 6 9 11 12
*
* First we iterate over the caps1 structures (top line) intersecting
* the structures diagonally down, then we iterate over the caps2
* structures.
*/
#if 0
for (i = 0; i < caps1->structs->len; i++) {
struct1 = gst_caps_get_structure (caps1, i);
for (j = 0; j < caps2->structs->len; j++) {
}
}
#endif
/* run zigzag on right line
*
* .. 1
* .. 2 4
* .. 3 5 6
*/
for (i = 0; i < caps1->structs->len + caps2->structs->len - 1; i++) {
/* caps1 index goes from 0 to caps1->structs->len-1 */
j = MIN (i, caps1->structs->len - 1);
/* caps2 index stays 0 until i reaches caps1->structs->len, then it counts
* up from 1 to caps2->structs->len - 1 */
k = MAX (0, i - j);
/* FIXME use loop that preserves the order better */
for (i = 0; i < caps1->structs->len; i++) {
struct1 = gst_caps_get_structure (caps1, i);
for (j = 0; j < caps2->structs->len; j++) {
GstStructure *istruct;
/* now run the diagonal line, end condition is the left or bottom
* border */
while (k < caps2->structs->len && j >= 0) {
struct1 = gst_caps_get_structure (caps1, j);
struct2 = gst_caps_get_structure (caps2, k);
struct2 = gst_caps_get_structure (caps2, j);
istruct = gst_caps_structure_intersect (struct1, struct2);
gst_caps_append_structure (dest, istruct);
/* move down left */
k++;
j--;
}
}

View file

@ -1797,30 +1797,41 @@ exit:
}
/* is called with STATE_LOCK */
/* FIXME make MT safe */
static gboolean
gst_element_pads_activate (GstElement * element, gboolean active)
{
GList *pads;
gboolean result = TRUE;
gboolean result;
guint32 cookie;
GST_LOCK (element);
restart:
result = TRUE;
pads = element->pads;
while (pads && result) {
cookie = element->pads_cookie;
for (; pads && result; pads = g_list_next (pads)) {
GstPad *pad = GST_PAD (pads->data);
pads = g_list_next (pads);
gst_object_ref (GST_OBJECT (pad));
GST_UNLOCK (element);
if (!GST_IS_REAL_PAD (pad))
continue;
if (GST_IS_REAL_PAD (pad)) {
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
"%sactivating pad %s", (active ? "" : "(de)"), GST_OBJECT_NAME (pad));
result &= gst_pad_set_active (pad, active);
}
gst_object_unref (GST_OBJECT (pad));
result &= gst_pad_set_active (pad, active);
GST_LOCK (element);
if (cookie != element->pads_cookie)
goto restart;
}
GST_UNLOCK (element);
return result;
}
/* is called with STATE_LOCK */
/* FIXME make MT safe */
static GstElementStateReturn
gst_element_change_state (GstElement * element)
{
@ -1857,10 +1868,12 @@ gst_element_change_state (GstElement * element)
}
break;
case GST_STATE_PAUSED_TO_PLAYING:
GST_LOCK (element);
if (GST_ELEMENT_MANAGER (element)) {
element->base_time =
GST_ELEMENT (GST_ELEMENT_MANAGER (element))->base_time;
}
GST_UNLOCK (element);
break;
case GST_STATE_PLAYING_TO_PAUSED:
break;
@ -2264,16 +2277,16 @@ GstTask *
gst_element_create_task (GstElement * element, GstTaskFunction func,
gpointer data)
{
GstPipeline *pipeline;
GstScheduler *sched;
GstTask *result = NULL;
GST_LOCK (element);
pipeline = GST_ELEMENT_MANAGER (element);
gst_object_ref (GST_OBJECT (pipeline));
sched = GST_ELEMENT_SCHEDULER (element);
gst_object_ref (GST_OBJECT (sched));
GST_UNLOCK (element);
if (pipeline) {
result = gst_scheduler_create_task (pipeline->scheduler, func, data);
gst_object_unref (GST_OBJECT (pipeline));
if (sched) {
result = gst_scheduler_create_task (sched, func, data);
gst_object_unref (GST_OBJECT (sched));
}
return result;

View file

@ -314,6 +314,7 @@ gst_object_unref (GstObject * object)
PATCH_REFCOUNT (object);
}
#else
/* FIXME, not MT safe because glib is not MT safe */
g_object_unref (object);
#endif

View file

@ -234,7 +234,6 @@ gst_real_pad_init (GstRealPad * pad)
pad->peer = NULL;
pad->chainfunc = NULL;
pad->getfunc = NULL;
pad->ghostpads = NULL;
pad->caps = NULL;
@ -251,8 +250,7 @@ gst_real_pad_init (GstRealPad * pad)
pad->formatsfunc = gst_pad_get_formats_default;
pad->querytypefunc = gst_pad_get_query_types_default;
GST_FLAG_SET (pad, GST_PAD_DISABLED);
GST_FLAG_UNSET (pad, GST_PAD_NEGOTIATING);
GST_FLAG_UNSET (pad, GST_PAD_ACTIVE);
pad->stream_lock = g_mutex_new ();
pad->stream_cond = g_cond_new ();
@ -286,7 +284,7 @@ gst_real_pad_get_property (GObject * object, guint prop_id,
switch (prop_id) {
case REAL_ARG_ACTIVE:
g_value_set_boolean (value, !GST_FLAG_IS_SET (object, GST_PAD_DISABLED));
g_value_set_boolean (value, GST_FLAG_IS_SET (object, GST_PAD_ACTIVE));
break;
case REAL_ARG_CAPS:
g_value_set_boxed (value, GST_PAD_CAPS (GST_REAL_PAD (object)));
@ -450,7 +448,7 @@ gst_pad_set_active (GstPad * pad, gboolean active)
if (!active) {
GST_CAT_DEBUG (GST_CAT_PADS, "de-activating pad %s:%s",
GST_DEBUG_PAD_NAME (realpad));
GST_FLAG_SET (realpad, GST_PAD_DISABLED);
GST_FLAG_UNSET (realpad, GST_PAD_ACTIVE);
/* unlock blocked pads so element can resume and stop */
GST_PAD_BLOCK_SIGNAL (realpad);
}
@ -470,7 +468,7 @@ gst_pad_set_active (GstPad * pad, gboolean active)
if (active && result == TRUE) {
GST_CAT_DEBUG (GST_CAT_PADS, "activating pad %s:%s",
GST_DEBUG_PAD_NAME (realpad));
GST_FLAG_UNSET (realpad, GST_PAD_DISABLED);
GST_FLAG_SET (realpad, GST_PAD_ACTIVE);
}
exit:
@ -503,7 +501,7 @@ gst_pad_is_active (GstPad * pad)
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
GST_PAD_REALIZE_AND_LOCK (pad, realpad, lost_ghostpad);
result = !GST_FLAG_IS_SET (realpad, GST_PAD_DISABLED);
result = !!GST_FLAG_IS_SET (realpad, GST_PAD_ACTIVE);
GST_UNLOCK (realpad);
return result;
@ -671,6 +669,24 @@ gst_pad_set_activate_function (GstPad * pad, GstPadActivateFunction activate)
GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (activate));
}
/**
* gst_pad_set_loop_function:
* @pad: a real sink #GstPad.
* @chain: the #GstPadLoopFunction to set.
*
* Sets the given loop function for the pad. The loop function is called
* repeadedly to pull/push buffers from/to the peer pad.
*/
void
gst_pad_set_loop_function (GstPad * pad, GstPadLoopFunction loop)
{
g_return_if_fail (GST_IS_REAL_PAD (pad));
GST_RPAD_LOOPFUNC (pad) = loop;
GST_CAT_DEBUG (GST_CAT_PADS, "loopfunc for %s:%s set to %s",
GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (loop));
}
/**
* gst_pad_set_chain_function:
* @pad: a real sink #GstPad.
@ -691,23 +707,23 @@ gst_pad_set_chain_function (GstPad * pad, GstPadChainFunction chain)
}
/**
* gst_pad_set_get_function:
* gst_pad_set_getrange_function:
* @pad: a real source #GstPad.
* @get: the #GstPadGetFunction to set.
* @get: the #GstPadGetRangeFunction to set.
*
* 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
* Sets the given getrange function for the pad. The getrange function is called to
* produce a new #GstBuffer to start the processing pipeline. Getrange functions cannot
* return %NULL.
*/
void
gst_pad_set_get_function (GstPad * pad, GstPadGetFunction get)
gst_pad_set_getrange_function (GstPad * pad, GstPadGetRangeFunction get)
{
g_return_if_fail (GST_IS_REAL_PAD (pad));
g_return_if_fail (GST_RPAD_DIRECTION (pad) == GST_PAD_SRC);
GST_RPAD_GETFUNC (pad) = get;
GST_RPAD_GETRANGEFUNC (pad) = get;
GST_CAT_DEBUG (GST_CAT_PADS, "getfunc for %s:%s set to %s",
GST_CAT_DEBUG (GST_CAT_PADS, "getrangefunc for %s:%s set to %s",
GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (get));
}
@ -1007,7 +1023,8 @@ gst_pad_set_unlink_function (GstPad * pad, GstPadUnlinkFunction unlink)
* but this is discouraged.
*
* You do not need to call this function if @pad's allowed caps are always the
* same as the pad template caps.
* same as the pad template caps. This can only be true if the padtemplate
* has fixed simple caps.
*
* For most filters, the caps returned by @getcaps is directly affected by the
* allowed caps on other pads. For demuxers and decoders, the caps returned by
@ -1015,7 +1032,8 @@ gst_pad_set_unlink_function (GstPad * pad, GstPadUnlinkFunction unlink)
* @getcaps should return the most specific caps it reasonably can, since this
* helps with autoplugging.
*
* Note that the return value from @getcaps is owned by the caller.
* Note that the return value from @getcaps is owned by the caller, so the caller
* should unref the caps after usage.
*/
void
gst_pad_set_getcaps_function (GstPad * pad, GstPadGetCapsFunction getcaps)
@ -1027,6 +1045,38 @@ gst_pad_set_getcaps_function (GstPad * pad, GstPadGetCapsFunction getcaps)
GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (getcaps));
}
void
gst_pad_set_acceptcaps_function (GstPad * pad,
GstPadAcceptCapsFunction acceptcaps)
{
g_return_if_fail (GST_IS_REAL_PAD (pad));
GST_RPAD_ACCEPTCAPSFUNC (pad) = acceptcaps;
GST_CAT_DEBUG (GST_CAT_PADS, "acceptcapsfunc for %s:%s set to %s",
GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (acceptcaps));
}
void
gst_pad_set_fixatecaps_function (GstPad * pad,
GstPadFixateCapsFunction fixatecaps)
{
g_return_if_fail (GST_IS_REAL_PAD (pad));
GST_RPAD_FIXATECAPSFUNC (pad) = fixatecaps;
GST_CAT_DEBUG (GST_CAT_PADS, "fixatecapsfunc for %s:%s set to %s",
GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (fixatecaps));
}
void
gst_pad_set_setcaps_function (GstPad * pad, GstPadSetCapsFunction setcaps)
{
g_return_if_fail (GST_IS_REAL_PAD (pad));
GST_RPAD_SETCAPSFUNC (pad) = setcaps;
GST_CAT_DEBUG (GST_CAT_PADS, "setcapsfunc for %s:%s set to %s",
GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (setcaps));
}
/**
* gst_pad_set_bufferalloc_function:
* @pad: a real sink #GstPad.
@ -1176,6 +1226,7 @@ lost_ghostpad:
}
}
/* FIXME leftover from an attempt at refactoring... */
static GstPadLinkReturn
gst_pad_link_prepare_filtered (GstPad * srcpad, GstPad * sinkpad,
GstRealPad ** outrealsrc, GstRealPad ** outrealsink,
@ -1245,6 +1296,8 @@ not_srcpad:
}
src_was_linked:
{
GST_CAT_INFO (GST_CAT_PADS, "src %s:%s was linked",
GST_DEBUG_PAD_NAME (realsrc));
/* we do not emit a warning in this case because unlinking cannot
* be made MT safe.*/
GST_UNLOCK (realsrc);
@ -1265,6 +1318,8 @@ not_sinkpad:
}
sink_was_linked:
{
GST_CAT_INFO (GST_CAT_PADS, "sink %s:%s was linked",
GST_DEBUG_PAD_NAME (realsink));
/* we do not emit a warning in this case because unlinking cannot
* be made MT safe.*/
GST_UNLOCK (realsink);
@ -1493,24 +1548,92 @@ gst_pad_relink_filtered (GstPad * srcpad, GstPad * sinkpad,
const GstCaps * filtercaps)
{
GstRealPad *realsrc, *realsink;
GstPadLinkReturn result;
result = gst_pad_link_prepare_filtered (srcpad, sinkpad, &realsrc, &realsink,
filtercaps);
/* FIXME refactor and share code with link/unlink */
if (result != GST_PAD_LINK_OK)
goto prepare_failed;
/* generic checks */
g_return_val_if_fail (GST_IS_PAD (srcpad), GST_PAD_LINK_REFUSED);
g_return_val_if_fail (GST_IS_PAD (sinkpad), GST_PAD_LINK_REFUSED);
GST_CAT_INFO (GST_CAT_PADS, "trying to relink %s:%s and %s:%s",
GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
/* now we need to deal with the real/ghost stuff */
GST_PAD_REALIZE_AND_LOCK (srcpad, realsrc, lost_src_ghostpad);
if (G_UNLIKELY (GST_RPAD_DIRECTION (realsrc) != GST_PAD_SRC))
goto not_srcpad;
GST_PAD_REALIZE_AND_LOCK (sinkpad, realsink, lost_sink_ghostpad);
if (G_UNLIKELY (GST_RPAD_DIRECTION (realsink) != GST_PAD_SINK))
goto not_sinkpad;
if (G_UNLIKELY (GST_RPAD_PEER (realsink) != realsrc))
goto not_linked_together;
if ((GST_PAD (realsrc) != srcpad) || (GST_PAD (realsink) != sinkpad)) {
GST_CAT_INFO (GST_CAT_PADS, "*actually* relinking %s:%s and %s:%s",
GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
}
/* update filter */
if (filtercaps) {
GstCaps *filtercopy;
filtercopy = gst_caps_copy (filtercaps);
filtercopy = gst_caps_ref (filtercopy);
gst_caps_replace (&GST_PAD_APPFILTER (realsrc), filtercopy);
gst_caps_replace (&GST_PAD_APPFILTER (realsink), filtercopy);
} else {
gst_caps_replace (&GST_PAD_APPFILTER (realsrc), NULL);
gst_caps_replace (&GST_PAD_APPFILTER (realsink), NULL);
}
/* clear caps to force renegotiation */
gst_caps_replace (&GST_PAD_CAPS (realsrc), NULL);
gst_caps_replace (&GST_PAD_CAPS (realsink), NULL);
GST_UNLOCK (realsink);
GST_UNLOCK (realsrc);
GST_CAT_INFO (GST_CAT_PADS, "relinked %s:%s and %s:%s, successful",
GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
return GST_PAD_LINK_OK;
prepare_failed:
return result;
lost_src_ghostpad:
{
return GST_PAD_LINK_REFUSED;
}
not_srcpad:
{
g_critical ("pad %s is not a source pad", GST_PAD_NAME (realsrc));
GST_UNLOCK (realsrc);
return GST_PAD_LINK_WRONG_DIRECTION;
}
lost_sink_ghostpad:
{
GST_DEBUG ("lost sink ghostpad");
GST_UNLOCK (realsrc);
return GST_PAD_LINK_REFUSED;
}
not_sinkpad:
{
g_critical ("pad %s is not a sink pad", GST_PAD_NAME (realsink));
GST_UNLOCK (realsink);
GST_UNLOCK (realsrc);
return GST_PAD_LINK_WRONG_DIRECTION;
}
not_linked_together:
{
GST_CAT_INFO (GST_CAT_PADS, "src %s:%s was not linked with sink %s:%s",
GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
/* we do not emit a warning in this case because unlinking cannot
* be made MT safe.*/
GST_UNLOCK (realsink);
GST_UNLOCK (realsrc);
return GST_PAD_LINK_REFUSED;
}
}
/**
@ -1535,7 +1658,7 @@ gst_pad_get_caps (GstPad * pad)
GST_CAT_DEBUG (GST_CAT_CAPS, "get pad caps of %s:%s (%p)",
GST_DEBUG_PAD_NAME (realpad), realpad);
if (GST_PAD_IS_DISPATCHING (realpad)) {
if (GST_RPAD_IS_IN_GETCAPS (realpad)) {
GST_CAT_DEBUG (GST_CAT_CAPS,
"pad %s:%s is already dispatching!", GST_DEBUG_PAD_NAME (realpad));
g_warning ("pad %s:%s recursively called getcaps!",
@ -1548,9 +1671,9 @@ gst_pad_get_caps (GstPad * pad)
GST_CAT_DEBUG (GST_CAT_CAPS, "dispatching to pad getcaps function");
GST_FLAG_SET (realpad, GST_PAD_DISPATCHING);
GST_FLAG_SET (realpad, GST_PAD_IN_GETCAPS);
result = GST_RPAD_GETCAPSFUNC (realpad) (GST_PAD (realpad));
GST_FLAG_UNSET (realpad, GST_PAD_DISPATCHING);
GST_FLAG_UNSET (realpad, GST_PAD_IN_GETCAPS);
if (result == NULL) {
g_critical ("pad %s:%s returned NULL caps from getcaps function\n",
@ -1629,9 +1752,27 @@ done:
gboolean
gst_pad_set_caps (GstPad * pad, GstCaps * caps)
{
GstPadSetCapsFunction setcaps;
g_return_val_if_fail (GST_IS_REAL_PAD (pad), FALSE);
GST_LOCK (pad);
setcaps = GST_RPAD_SETCAPSFUNC (pad);
/* call setcaps function to configure the pad */
if (setcaps != NULL) {
if (!GST_RPAD_IS_IN_SETCAPS (pad)) {
GST_FLAG_SET (pad, GST_PAD_IN_SETCAPS);
GST_UNLOCK (pad);
if (!setcaps (pad, caps))
goto could_not_set;
GST_LOCK (pad);
} else {
GST_CAT_DEBUG (GST_CAT_CAPS, "pad %s:%s was dispatching",
GST_DEBUG_PAD_NAME (pad));
}
}
if (GST_PAD_CAPS (pad))
gst_caps_unref (GST_PAD_CAPS (pad));
@ -1639,11 +1780,81 @@ gst_pad_set_caps (GstPad * pad, GstCaps * caps)
caps = gst_caps_ref (caps);
GST_PAD_CAPS (pad) = caps;
GST_CAT_DEBUG (GST_CAT_CAPS, "%s:%s caps %" GST_PTR_FORMAT,
GST_DEBUG_PAD_NAME (pad), caps);
GST_UNLOCK (pad);
g_object_notify (G_OBJECT (pad), "caps");
return TRUE;
could_not_set:
{
GST_LOCK (pad);
GST_FLAG_UNSET (pad, GST_PAD_IN_SETCAPS);
GST_UNLOCK (pad);
GST_CAT_DEBUG (GST_CAT_CAPS, "caps %" GST_PTR_FORMAT " could not be set",
caps);
return FALSE;
}
}
static gboolean
gst_pad_configure_sink (GstPad * pad, GstCaps * caps)
{
GstPadAcceptCapsFunction acceptcaps;
GstPadSetCapsFunction setcaps;
acceptcaps = GST_RPAD_ACCEPTCAPSFUNC (pad);
setcaps = GST_RPAD_SETCAPSFUNC (pad);
/* See if pad accepts the caps, by calling acceptcaps, only
* needed if no setcaps function */
if (setcaps == NULL && acceptcaps != NULL) {
if (!acceptcaps (pad, caps))
goto not_accepted;
}
/* set caps on pad if call succeeds */
gst_pad_set_caps (pad, caps);
/* no need to unref the caps here, set_caps takes a ref and
* our ref goes away when we leave this function. */
return TRUE;
not_accepted:
{
GST_CAT_DEBUG (GST_CAT_CAPS, "caps %" GST_PTR_FORMAT " not accepted", caps);
return FALSE;
}
}
static gboolean
gst_pad_configure_src (GstPad * pad, GstCaps * caps)
{
GstPadAcceptCapsFunction acceptcaps;
GstPadSetCapsFunction setcaps;
acceptcaps = GST_RPAD_ACCEPTCAPSFUNC (pad);
setcaps = GST_RPAD_SETCAPSFUNC (pad);
/* See if pad accepts the caps, by calling acceptcaps, only
* needed if no setcaps function */
if (setcaps == NULL && acceptcaps != NULL) {
if (!acceptcaps (pad, caps))
goto not_accepted;
}
/* set caps on pad if call succeeds */
gst_pad_set_caps (pad, caps);
/* no need to unref the caps here, set_caps takes a ref and
* our ref goes away when we leave this function. */
return TRUE;
not_accepted:
{
GST_CAT_DEBUG (GST_CAT_CAPS, "caps %" GST_PTR_FORMAT " not accepted", caps);
return FALSE;
}
}
/**
@ -1747,45 +1958,47 @@ gst_pad_realize (GstPad * pad)
/**
* gst_pad_get_allowed_caps:
* @pad: a real #GstPad.
* @srcpad: a #GstPad, it must a a source pad.
*
* Gets the capabilities of the allowed media types that can flow through @pad.
* Gets the capabilities of the allowed media types that can flow through @pad
* and its peer. The pad must be a source 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.
* you no longer need it. This function returns NULL when the @pad has no
* peer.
*
* MT safe.
*/
GstCaps *
gst_pad_get_allowed_caps (GstPad * pad)
gst_pad_get_allowed_caps (GstPad * srcpad)
{
GstCaps *mycaps;
GstCaps *caps;
GstCaps *peercaps;
GstRealPad *peer;
GstRealPad *realpad, *peer;
g_return_val_if_fail (GST_IS_REAL_PAD (pad), NULL);
g_return_val_if_fail (GST_IS_PAD (srcpad), NULL);
GST_PAD_REALIZE_AND_LOCK (srcpad, realpad, lost_ghostpad);
/* FIXME, allow sinkpads too? need to use the nexted locking
* with retry algorithm, see design docs */
if (G_UNLIKELY (!GST_PAD_IS_SRC (realpad)))
goto not_src;
if (G_UNLIKELY ((peer = GST_RPAD_PEER (realpad)) == NULL))
goto no_peer;
GST_CAT_DEBUG (GST_CAT_PROPERTIES, "%s:%s: getting allowed caps",
GST_DEBUG_PAD_NAME (pad));
GST_DEBUG_PAD_NAME (realpad));
mycaps = gst_pad_get_caps (pad);
GST_LOCK (pad);
peer = GST_RPAD_PEER (pad);
if (peer == NULL) {
GST_CAT_DEBUG (GST_CAT_PROPERTIES, "%s:%s: no peer, returning own caps",
GST_DEBUG_PAD_NAME (pad));
GST_UNLOCK (pad);
return mycaps;
} else {
gst_object_ref (GST_OBJECT (peer));
GST_UNLOCK (pad);
}
gst_object_ref (GST_OBJECT_CAST (peer));
GST_UNLOCK (realpad);
mycaps = gst_pad_get_caps (GST_PAD_CAST (realpad));
peercaps = gst_pad_get_caps (GST_PAD_CAST (peer));
gst_object_unref (GST_OBJECT (peer));
gst_object_unref (GST_OBJECT_CAST (peer));
caps = gst_caps_intersect (mycaps, peercaps);
gst_caps_unref (peercaps);
@ -1794,6 +2007,137 @@ gst_pad_get_allowed_caps (GstPad * pad)
GST_CAT_DEBUG (GST_CAT_CAPS, "allowed caps %" GST_PTR_FORMAT, caps);
return caps;
lost_ghostpad:
{
GST_UNLOCK (srcpad);
return NULL;
}
not_src:
{
GST_CAT_DEBUG (GST_CAT_PROPERTIES, "%s:%s: not a source pad",
GST_DEBUG_PAD_NAME (realpad));
GST_UNLOCK (realpad);
return NULL;
}
no_peer:
{
GST_CAT_DEBUG (GST_CAT_PROPERTIES, "%s:%s: no peer",
GST_DEBUG_PAD_NAME (realpad));
GST_UNLOCK (realpad);
return NULL;
}
}
/**
* gst_pad_get_negotiated_caps:
* @pad: a #GstPad.
*
* Gets the capabilities of the media type that currently flows through @pad
* and its peer.
*
* This function can be used on both src and sinkpads. Note that srcpads are
* always negotiated before sinkpads so it is possible that the negotiated caps
* on the srcpad do not match the negotiated caps of the peer.
*
* Returns: the negotiated #GstCaps of the pad link. Free the caps when
* you no longer need it. This function returns NULL when the @pad has no
* peer or is not negotiated yet.
*
* MT safe.
*/
GstCaps *
gst_pad_get_negotiated_caps (GstPad * pad)
{
GstCaps *caps;
GstRealPad *realpad, *peer;
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
GST_PAD_REALIZE_AND_LOCK (pad, realpad, lost_ghostpad);
if (G_UNLIKELY ((peer = GST_RPAD_PEER (realpad)) == NULL))
goto no_peer;
GST_CAT_DEBUG (GST_CAT_PROPERTIES, "%s:%s: getting negotiated caps",
GST_DEBUG_PAD_NAME (realpad));
caps = GST_RPAD_CAPS (realpad);
if (caps)
gst_caps_ref (caps);
GST_UNLOCK (pad);
GST_CAT_DEBUG (GST_CAT_CAPS, "negotiated caps %" GST_PTR_FORMAT, caps);
return caps;
lost_ghostpad:
{
GST_UNLOCK (pad);
return NULL;
}
no_peer:
{
GST_CAT_DEBUG (GST_CAT_PROPERTIES, "%s:%s: no peer",
GST_DEBUG_PAD_NAME (realpad));
GST_UNLOCK (realpad);
return NULL;
}
}
/**
* gst_pad_get_filter_caps:
* @pad: a real #GstPad.
*
* Gets the capabilities of filter that currently configured on @pad
* and its peer.
*
* Returns: the filter #GstCaps of the pad link. Free the caps when
* you no longer need it. This function returns NULL when the @pad has no
* peer or there is no filter configured.
*
* MT safe.
*/
GstCaps *
gst_pad_get_filter_caps (GstPad * pad)
{
GstCaps *caps;
GstRealPad *realpad, *peer;
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
GST_PAD_REALIZE_AND_LOCK (pad, realpad, lost_ghostpad);
if (G_UNLIKELY ((peer = GST_RPAD_PEER (realpad)) == NULL))
goto no_peer;
GST_CAT_DEBUG (GST_CAT_PROPERTIES, "%s:%s: getting filter caps",
GST_DEBUG_PAD_NAME (realpad));
if ((caps = GST_RPAD_APPFILTER (realpad)) != NULL)
gst_caps_ref (caps);
GST_UNLOCK (pad);
GST_CAT_DEBUG (GST_CAT_CAPS, "filter caps %" GST_PTR_FORMAT, caps);
return caps;
lost_ghostpad:
{
GST_UNLOCK (pad);
return NULL;
}
no_peer:
{
GST_CAT_DEBUG (GST_CAT_PROPERTIES, "%s:%s: no peer",
GST_DEBUG_PAD_NAME (realpad));
GST_UNLOCK (realpad);
return NULL;
}
}
/**
@ -1804,33 +2148,38 @@ gst_pad_get_allowed_caps (GstPad * pad)
* @caps: the caps of the new buffer
*
* Allocates a new, empty buffer optimized to push to pad @pad. This
* function only works if @pad is a source pad. You need to check the
* caps of the buffer after performing this function and renegotiate
* to the format if needed.
* function only works if @pad is a source pad and a GST_REAL_PAD and
* has a peer.
* You need to check the caps of the buffer after performing this
* function and renegotiate to the format if needed.
*
* Returns: a new, empty #GstBuffer, or NULL if wrong parameters
* were provided.
* were provided or the peer pad is not able to provide a buffer
* that can be handled by the caller.
*
* MT safe.
*/
GstBuffer *
gst_pad_alloc_buffer (GstPad * pad, guint64 offset, gint size)
gst_pad_alloc_buffer (GstPad * pad, guint64 offset, gint size, GstCaps * caps)
{
GstRealPad *peer;
GstBuffer *result = NULL;
GstPadBufferAllocFunction bufferallocfunc;
GstCaps *caps;
gboolean caps_changed;
g_return_val_if_fail (GST_IS_REAL_PAD (pad), NULL);
g_return_val_if_fail (GST_PAD_IS_SRC (pad), NULL);
GST_LOCK (pad);
if (G_UNLIKELY ((peer = GST_RPAD_PEER (pad)) == NULL))
goto fallback;
goto no_peer;
if (G_LIKELY ((bufferallocfunc = peer->bufferallocfunc) == NULL))
if (G_LIKELY ((bufferallocfunc = peer->bufferallocfunc) == NULL)) {
GST_UNLOCK (pad);
goto fallback;
}
gst_object_ref (GST_OBJECT_CAST (peer));
GST_UNLOCK (pad);
GST_CAT_DEBUG (GST_CAT_PADS,
@ -1838,29 +2187,48 @@ gst_pad_alloc_buffer (GstPad * pad, guint64 offset, gint size)
GST_DEBUG_FUNCPTR_NAME (bufferallocfunc),
&bufferallocfunc, GST_DEBUG_PAD_NAME (peer));
result =
bufferallocfunc (GST_PAD_CAST (peer), offset, size, GST_PAD_CAPS (pad));
result = bufferallocfunc (GST_PAD_CAST (peer), offset, size, caps);
gst_object_unref (GST_OBJECT_CAST (peer));
if (G_UNLIKELY (result == NULL)) {
GST_LOCK (pad);
goto fallback;
}
/* FIXME, move capnego this into a base class? */
caps = GST_BUFFER_CAPS (result);
caps_changed = caps && caps != GST_RPAD_CAPS (pad);
/* we got a new datatype on the pad, see if it can handle it */
if (G_UNLIKELY (caps_changed)) {
if (G_UNLIKELY (!gst_pad_configure_src (GST_PAD_CAST (pad), caps)))
goto not_negotiated;
}
return result;
no_peer:
{
/* pad has no peer */
GST_CAT_DEBUG (GST_CAT_PADS,
"%s:%s called bufferallocfunc but had no peer, returning NULL",
GST_DEBUG_PAD_NAME (pad));
GST_UNLOCK (pad);
return NULL;
}
/* fallback case, allocate a buffer of our own, add pad caps. */
fallback:
{
caps = GST_PAD_CAPS (pad);
gst_caps_ref (caps);
GST_UNLOCK (pad);
result = gst_buffer_new_and_alloc (size);
gst_buffer_set_caps (result, caps);
gst_caps_unref (caps);
return result;
}
not_negotiated:
{
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
"alloc function retured unacceptable buffer");
return NULL;
}
}
static void
@ -2119,6 +2487,8 @@ gst_pad_push (GstPad * pad, GstBuffer * buffer)
GstRealPad *peer;
GstFlowReturn ret;
GstPadChainFunction chainfunc;
GstCaps *caps;
gboolean caps_changed;
g_return_val_if_fail (GST_IS_REAL_PAD (pad), GST_FLOW_ERROR);
g_return_val_if_fail (GST_RPAD_DIRECTION (pad) == GST_PAD_SRC,
@ -2126,8 +2496,8 @@ gst_pad_push (GstPad * pad, GstBuffer * buffer)
g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
GST_LOCK (pad);
GST_LOCK (pad);
while (G_UNLIKELY (GST_RPAD_IS_BLOCKED (pad)))
handle_pad_block (GST_REAL_PAD_CAST (pad));
@ -2140,6 +2510,15 @@ gst_pad_push (GstPad * pad, GstBuffer * buffer)
gst_object_ref (GST_OBJECT_CAST (peer));
GST_UNLOCK (pad);
/* FIXME, move capnego this into a base class? */
caps = GST_BUFFER_CAPS (buffer);
caps_changed = caps && caps != GST_RPAD_CAPS (peer);
/* we got a new datatype on the peer pad, see if it can handle it */
if (G_UNLIKELY (caps_changed)) {
if (G_UNLIKELY (!gst_pad_configure_sink (GST_PAD_CAST (peer), caps)))
goto not_negotiated;
}
/* NOTE: we read the peer chainfunc unlocked.
* we cannot hold the lock for the peer so we might send
* the data to the wrong function. This is not really a
@ -2160,83 +2539,33 @@ gst_pad_push (GstPad * pad, GstBuffer * buffer)
/* ERROR recovery here */
not_linked:
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
"pushing, but it was not linked");
GST_UNLOCK_RETURN (pad, GST_FLOW_NOT_CONNECTED);
{
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
"pushing, but it was not linked");
GST_UNLOCK_RETURN (pad, GST_FLOW_NOT_CONNECTED);
}
not_active:
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "pushing, but it was inactive");
GST_UNLOCK_RETURN (pad, GST_FLOW_WRONG_STATE);
{
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
"pushing, but it was inactive");
GST_UNLOCK_RETURN (pad, GST_FLOW_WRONG_STATE);
}
not_negotiated:
{
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
"pushing buffer but peer did not accept");
return GST_FLOW_NOT_NEGOTIATED;
}
no_function:
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "pushing, but not chainhandler");
g_warning ("push on pad %s:%s but it has no chainhandler, file a bug.",
GST_DEBUG_PAD_NAME (peer));
gst_object_unref (GST_OBJECT (peer));
return GST_FLOW_ERROR;
}
/**
* gst_pad_pull:
* @pad: a sink #GstPad.
* @buffer: a pointer to hold the #GstBuffer.
*
* Pulls a buffer from the peer pad. May only be called by @pad's
* parent.
*
* Returns: a #GstFlowReturn from the peer pad.
*
* MT safe.
*/
GstFlowReturn
gst_pad_pull (GstPad * pad, GstBuffer ** buffer)
{
GstRealPad *peer;
GstFlowReturn ret;
GstPadGetFunction getfunc;
g_return_val_if_fail (GST_IS_REAL_PAD (pad), GST_FLOW_ERROR);
g_return_val_if_fail (GST_RPAD_DIRECTION (pad) == GST_PAD_SINK,
GST_FLOW_ERROR);
g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
GST_LOCK (pad);
while (G_UNLIKELY (GST_RPAD_IS_BLOCKED (pad)))
handle_pad_block (GST_REAL_PAD_CAST (pad));
if (G_UNLIKELY ((peer = GST_RPAD_PEER (pad)) == NULL))
goto not_connected;
gst_object_ref (GST_OBJECT_CAST (peer));
GST_UNLOCK (pad);
/* see note in above function */
if (G_UNLIKELY ((getfunc = peer->getfunc) == NULL))
goto no_function;
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
"calling getfunc %s of peer pad %s:%s",
GST_DEBUG_FUNCPTR_NAME (getfunc), GST_DEBUG_PAD_NAME (peer));
ret = getfunc (GST_PAD_CAST (peer), buffer);
gst_object_unref (GST_OBJECT_CAST (peer));
return ret;
/* ERROR recovery here */
not_connected:
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
"pulling, but it was not linked");
GST_UNLOCK_RETURN (pad, GST_FLOW_NOT_CONNECTED);
no_function:
GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL),
("pull on pad %s:%s but the peer pad %s:%s has no getfunc",
GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (peer)));
gst_object_unref (GST_OBJECT (peer));
return GST_FLOW_ERROR;
{
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
"pushing, but not chainhandler");
GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL),
("push on pad %s:%s but the peer pad %s:%s has no chainfunction",
GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (peer)));
gst_object_unref (GST_OBJECT (peer));
return GST_FLOW_ERROR;
}
}
/**

View file

@ -32,6 +32,7 @@
#include <gst/gstevent.h>
#include <gst/gstprobe.h>
#include <gst/gstquery.h>
#include <gst/gsttask.h>
G_BEGIN_DECLS
@ -109,6 +110,12 @@ typedef enum {
GST_FLOW_NOT_SUPPORTED = -6 /* function not supported */
} GstFlowReturn;
typedef enum {
GST_ACTIVATE_NONE,
GST_ACTIVATE_PUSH,
GST_ACTIVATE_PULL,
} GstActivateMode;
/* convenience functions */
#ifdef G_HAVE_ISO_VARARGS
#define GST_PAD_QUERY_TYPE_FUNCTION(functionname, ...) GST_QUERY_TYPE_FUNCTION (GstPad *, functionname, __VA_ARGS__);
@ -125,10 +132,10 @@ typedef enum {
typedef gboolean (*GstPadActivateFunction) (GstPad *pad, gboolean active);
/* data passing */
typedef gboolean (*GstPadLoopFunction) (GstPad *pad);
typedef GstFlowReturn (*GstPadChainFunction) (GstPad *pad, GstBuffer *buffer);
typedef GstFlowReturn (*GstPadGetFunction) (GstPad *pad, GstBuffer **buffer);
typedef GstFlowReturn (*GstPadGetRangeFunction) (GstPad *pad, guint64 offset,
guint64 length, GstBuffer **buffer);
guint length, GstBuffer **buffer);
typedef gboolean (*GstPadEventFunction) (GstPad *pad, GstEvent *event);
/* convert/query/format functions */
@ -148,6 +155,9 @@ typedef void (*GstPadUnlinkFunction) (GstPad *pad);
/* caps nego */
typedef GstCaps* (*GstPadGetCapsFunction) (GstPad *pad);
typedef gboolean (*GstPadSetCapsFunction) (GstPad *pad, GstCaps *caps);
typedef gboolean (*GstPadAcceptCapsFunction) (GstPad *pad, GstCaps *caps);
typedef GstCaps* (*GstPadFixateCapsFunction) (GstPad *pad, GstCaps *caps);
typedef GstBuffer* (*GstPadBufferAllocFunction) (GstPad *pad, guint64 offset, guint size,
GstCaps *caps);
/* misc */
@ -162,12 +172,13 @@ typedef enum {
} GstPadDirection;
typedef enum {
GST_PAD_DISABLED = GST_OBJECT_FLAG_LAST,
GST_PAD_ACTIVE = GST_OBJECT_FLAG_LAST,
GST_PAD_BLOCKED,
GST_PAD_NEGOTIATING,
GST_PAD_DISPATCHING,
GST_PAD_FLUSHING,
GST_PAD_IN_GETCAPS,
GST_PAD_IN_SETCAPS,
GST_PAD_FLAG_LAST = GST_OBJECT_FLAG_LAST + 4
GST_PAD_FLAG_LAST = GST_OBJECT_FLAG_LAST + 8
} GstPadFlags;
struct _GstPad {
@ -196,6 +207,7 @@ struct _GstRealPad {
/* streaming lock and cond */
GMutex *stream_lock;
GCond *stream_cond;
GstTask *task;
/*< public >*/ /* with LOCK */
/* block cond, mutex is from the object */
@ -207,9 +219,13 @@ struct _GstRealPad {
GstCaps *caps;
GstCaps *appfilter;
GstPadGetCapsFunction getcapsfunc;
GstPadSetCapsFunction setcapsfunc;
GstPadAcceptCapsFunction acceptcapsfunc;
GstPadFixateCapsFunction fixatecapsfunc;
GstPadActivateFunction activatefunc;
/* pad link */
GstPadLinkFunction linkfunc;
GstPadUnlinkFunction unlinkfunc;
GstRealPad *peer;
@ -217,13 +233,14 @@ struct _GstRealPad {
gpointer sched_private;
/* data transport functions */
GstPadLoopFunction loopfunc;
GstPadChainFunction chainfunc;
GstPadGetFunction getfunc;
GstPadGetRangeFunction getrangefunc;
GstPadEventFunction eventfunc;
GstPadEventMaskFunction eventmaskfunc;
/* ghostpads */
GList *ghostpads;
guint32 ghostpads_cookie;
@ -277,12 +294,10 @@ struct _GstGhostPadClass {
/* GstRealPad */
#define GST_RPAD_DIRECTION(pad) (GST_REAL_PAD_CAST(pad)->direction)
#define GST_RPAD_CAPS(pad) (GST_REAL_PAD_CAST(pad)->caps)
#define GST_RPAD_APPFILTER(pad) (GST_REAL_PAD_CAST(pad)->appfilter)
#define GST_RPAD_PEER(pad) (GST_REAL_PAD_CAST(pad)->peer)
#define GST_RPAD_TASK(pad) (GST_REAL_PAD_CAST(pad)->task)
#define GST_RPAD_ACTIVATEFUNC(pad) (GST_REAL_PAD_CAST(pad)->activatefunc)
#define GST_RPAD_LOOPFUNC(pad) (GST_REAL_PAD_CAST(pad)->loopfunc)
#define GST_RPAD_CHAINFUNC(pad) (GST_REAL_PAD_CAST(pad)->chainfunc)
#define GST_RPAD_GETFUNC(pad) (GST_REAL_PAD_CAST(pad)->getfunc)
#define GST_RPAD_GETRANGEFUNC(pad) (GST_REAL_PAD_CAST(pad)->getrangefunc)
#define GST_RPAD_EVENTFUNC(pad) (GST_REAL_PAD_CAST(pad)->eventfunc)
#define GST_RPAD_CONVERTFUNC(pad) (GST_REAL_PAD_CAST(pad)->convertfunc)
@ -292,31 +307,39 @@ struct _GstGhostPadClass {
#define GST_RPAD_QUERYTYPEFUNC(pad) (GST_REAL_PAD_CAST(pad)->querytypefunc)
#define GST_RPAD_EVENTMASKFUNC(pad) (GST_REAL_PAD_CAST(pad)->eventmaskfunc)
#define GST_RPAD_PEER(pad) (GST_REAL_PAD_CAST(pad)->peer)
#define GST_RPAD_LINKFUNC(pad) (GST_REAL_PAD_CAST(pad)->linkfunc)
#define GST_RPAD_UNLINKFUNC(pad) (GST_REAL_PAD_CAST(pad)->unlinkfunc)
#define GST_RPAD_CAPS(pad) (GST_REAL_PAD_CAST(pad)->caps)
#define GST_RPAD_APPFILTER(pad) (GST_REAL_PAD_CAST(pad)->appfilter)
#define GST_RPAD_GETCAPSFUNC(pad) (GST_REAL_PAD_CAST(pad)->getcapsfunc)
#define GST_RPAD_SETCAPSFUNC(pad) (GST_REAL_PAD_CAST(pad)->setcapsfunc)
#define GST_RPAD_ACCEPTCAPSFUNC(pad) (GST_REAL_PAD_CAST(pad)->acceptcapsfunc)
#define GST_RPAD_FIXATECAPSFUNC(pad) (GST_REAL_PAD_CAST(pad)->fixatecapsfunc)
#define GST_RPAD_BUFFERALLOCFUNC(pad) (GST_REAL_PAD_CAST(pad)->bufferallocfunc)
#define GST_RPAD_IS_LINKED(pad) (GST_RPAD_PEER(pad) != NULL)
#define GST_RPAD_IS_ACTIVE(pad) (!GST_FLAG_IS_SET(pad, GST_PAD_DISABLED))
#define GST_RPAD_IS_ACTIVE(pad) (GST_FLAG_IS_SET (pad, GST_PAD_ACTIVE))
#define GST_RPAD_IS_BLOCKED(pad) (GST_FLAG_IS_SET (pad, GST_PAD_BLOCKED))
#define GST_RPAD_IS_NEGOTIATING(pad) (GST_FLAG_IS_SET (pad, GST_PAD_NEGOTIATING))
#define GST_RPAD_IS_DISPATCHING(pad) (GST_FLAG_IS_SET (pad, GST_PAD_DISPATCHING))
#define GST_RPAD_IS_FLUSHING(pad) (GST_FLAG_IS_SET (pad, GST_PAD_FLUSHING))
#define GST_RPAD_IS_IN_GETCAPS(pad) (GST_FLAG_IS_SET (pad, GST_PAD_IN_GETCAPS))
#define GST_RPAD_IS_IN_SETCAPS(pad) (GST_FLAG_IS_SET (pad, GST_PAD_IN_SETCAPS))
#define GST_RPAD_IS_USABLE(pad) (GST_RPAD_IS_LINKED (pad) && \
GST_RPAD_IS_ACTIVE(pad) && GST_RPAD_IS_ACTIVE(GST_RPAD_PEER (pad)))
#define GST_RPAD_CAN_PULL(pad) (GST_IS_REAL_PAD(pad) && GST_REAL_PAD(pad)->gethandler != NULL)
#define GST_RPAD_IS_SRC(pad) (GST_RPAD_DIRECTION(pad) == GST_PAD_SRC)
#define GST_RPAD_IS_SINK(pad) (GST_RPAD_DIRECTION(pad) == GST_PAD_SINK)
#define GST_STREAM_GET_LOCK(pad) (GST_PAD_REALIZE(pad)->stream_lock)
#define GST_STREAM_LOCK(pad) (g_mutex_lock(GST_STREAM_GET_LOCK(pad)))
#define GST_STREAM_TRYLOCK(pad) (g_mutex_trylock(GST_STREAM_GET_LOCK(pad)))
#define GST_STREAM_UNLOCK(pad) (g_mutex_unlock(GST_STREAM_GET_LOCK(pad)))
#define GST_STREAM_GET_COND(pad) (GST_PAD_REALIZE(pad)->stream_cond)
#define GST_STREAM_GET_LOCK(pad) (GST_PAD_REALIZE(pad)->stream_lock)
#define GST_STREAM_LOCK(pad) (g_mutex_lock(GST_STREAM_GET_LOCK(pad)))
#define GST_STREAM_TRYLOCK(pad) (g_mutex_trylock(GST_STREAM_GET_LOCK(pad)))
#define GST_STREAM_UNLOCK(pad) (g_mutex_unlock(GST_STREAM_GET_LOCK(pad)))
#define GST_STREAM_GET_COND(pad) (GST_PAD_REALIZE(pad)->stream_cond)
#define GST_PAD_BLOCK_GET_COND(pad) (GST_PAD_REALIZE(pad)->block_cond)
#define GST_PAD_BLOCK_WAIT(pad) (g_cond_wait(GST_PAD_BLOCK_GET_COND (pad), GST_GET_LOCK (pad)))
#define GST_PAD_BLOCK_SIGNAL(pad) (g_cond_signal(GST_PAD_BLOCK_GET_COND (pad)))
#define GST_PAD_BLOCK_GET_COND(pad) (GST_PAD_REALIZE(pad)->block_cond)
#define GST_PAD_BLOCK_WAIT(pad) (g_cond_wait(GST_PAD_BLOCK_GET_COND (pad), GST_GET_LOCK (pad)))
#define GST_PAD_BLOCK_SIGNAL(pad) (g_cond_signal(GST_PAD_BLOCK_GET_COND (pad)))
/* GstGhostPad */
#define GST_GPAD_REALPAD(pad) (((GstGhostPad *)(pad))->realpad)
@ -333,7 +356,8 @@ struct _GstGhostPadClass {
#define GST_PAD_IS_ACTIVE(pad) (GST_RPAD_IS_ACTIVE(GST_PAD_REALIZE(pad)))
#define GST_PAD_IS_BLOCKED(pad) (GST_RPAD_IS_BLOCKED(GST_PAD_REALIZE(pad)))
#define GST_PAD_IS_NEGOTIATING(pad) (GST_RPAD_IS_NEGOTIATING(GST_PAD_REALIZE(pad)))
#define GST_PAD_IS_DISPATCHING(pad) (GST_RPAD_IS_DISPATCHING(GST_PAD_REALIZE(pad)))
#define GST_PAD_IS_IN_GETCAPS(pad) (GST_RPAD_IS_IN_GETCAPS(GST_PAD_REALIZE(pad)))
#define GST_PAD_IS_IN_SETCAPS(pad) (GST_RPAD_IS_IN_SETCAPS(GST_PAD_REALIZE(pad)))
#define GST_PAD_IS_USABLE(pad) (GST_RPAD_IS_USABLE(GST_PAD_REALIZE(pad)))
#define GST_PAD_CAN_PULL(pad) (GST_RPAD_CAN_PULL(GST_PAD_REALIZE(pad)))
#define GST_PAD_IS_SRC(pad) (GST_RPAD_IS_SRC(GST_PAD_REALIZE(pad)))
@ -433,13 +457,14 @@ gpointer gst_pad_get_element_private (GstPad *pad);
GstPadTemplate* gst_pad_get_pad_template (GstPad *pad);
void gst_pad_set_bufferalloc_function (GstPad *pad, GstPadBufferAllocFunction bufalloc);
GstBuffer* gst_pad_alloc_buffer (GstPad *pad, guint64 offset, gint size);
GstBuffer* gst_pad_alloc_buffer (GstPad *pad, guint64 offset, gint size,
GstCaps *caps);
/* data passing setup functions */
void gst_pad_set_activate_function (GstPad *pad, GstPadActivateFunction activate);
void gst_pad_set_loop_function (GstPad *pad, GstPadLoopFunction loop);
void gst_pad_set_chain_function (GstPad *pad, GstPadChainFunction chain);
void gst_pad_set_get_function (GstPad *pad, GstPadGetFunction get);
void gst_pad_set_get_range_function (GstPad *pad, GstPadGetRangeFunction get);
void gst_pad_set_getrange_function (GstPad *pad, GstPadGetRangeFunction get);
void gst_pad_set_event_function (GstPad *pad, GstPadEventFunction event);
void gst_pad_set_event_mask_function (GstPad *pad, GstPadEventMaskFunction mask_func);
@ -465,16 +490,25 @@ GstPad* gst_pad_realize (GstPad *pad);
/* capsnego functions */
void gst_pad_set_getcaps_function (GstPad *pad, GstPadGetCapsFunction getcaps);
void gst_pad_set_acceptcaps_function (GstPad *pad, GstPadAcceptCapsFunction acceptcaps);
void gst_pad_set_fixatecaps_function (GstPad *pad, GstPadFixateCapsFunction fixatecaps);
void gst_pad_set_setcaps_function (GstPad *pad, GstPadSetCapsFunction setcaps);
G_CONST_RETURN GstCaps* gst_pad_get_pad_template_caps (GstPad *pad);
GstCaps * gst_pad_get_allowed_caps (GstPad * pad);
/* capsnego function for connected/unconnected pads */
GstCaps * gst_pad_get_caps (GstPad * pad);
GstCaps* gst_pad_fixate_caps (GstPad * pad, GstCaps *caps);
gboolean gst_pad_accept_caps (GstPad * pad, GstCaps *caps);
gboolean gst_pad_set_caps (GstPad * pad, GstCaps *caps);
/* capsnego for connected pads */
GstCaps * gst_pad_get_allowed_caps (GstPad * srcpad);
GstCaps * gst_pad_get_negotiated_caps (GstPad * pad);
GstCaps * gst_pad_get_filter_caps (GstPad * pad);
/* data passing functions */
GstFlowReturn gst_pad_push (GstPad *pad, GstBuffer *buffer);
GstFlowReturn gst_pad_pull (GstPad *pad, GstBuffer **buffer);
GstFlowReturn gst_pad_pull_range (GstPad *pad, guint64 offset, guint size,
GstBuffer **buffer);
gboolean gst_pad_push_event (GstPad *pad, GstEvent *event);

View file

@ -116,25 +116,28 @@ static void
gst_pipeline_init (GTypeInstance * instance, gpointer g_class)
{
GstPipeline *pipeline = GST_PIPELINE (instance);
GstBus *bus;
GstScheduler *scheduler;
/* get an instance of the default scheduler */
pipeline->scheduler =
gst_scheduler_factory_make (NULL, GST_ELEMENT (pipeline));
scheduler = gst_scheduler_factory_make (NULL, GST_ELEMENT (pipeline));
/* FIXME need better error handling */
if (pipeline->scheduler == NULL) {
if (scheduler == NULL) {
const gchar *name = gst_scheduler_factory_get_default_name ();
g_error ("Critical error: could not get scheduler \"%s\"\n"
"Are you sure you have a registry ?\n"
"Run gst-register as root if you haven't done so yet.", name);
}
pipeline->bus = g_object_new (gst_bus_get_type (), NULL);
gst_bus_set_sync_handler (pipeline->bus,
bus = g_object_new (gst_bus_get_type (), NULL);
gst_bus_set_sync_handler (bus,
(GstBusSyncHandler) pipeline_bus_handler, pipeline);
pipeline->eosed = NULL;
/* we are our own manager */
GST_ELEMENT_MANAGER (pipeline) = pipeline;
gst_element_set_bus (GST_ELEMENT (pipeline), bus);
gst_element_set_scheduler (GST_ELEMENT (pipeline), scheduler);
}
static void
@ -142,11 +145,7 @@ gst_pipeline_dispose (GObject * object)
{
GstPipeline *pipeline = GST_PIPELINE (object);
g_assert (GST_IS_SCHEDULER (pipeline->scheduler));
gst_scheduler_reset (pipeline->scheduler);
gst_object_replace ((GstObject **) & pipeline->bus, NULL);
gst_object_replace ((GstObject **) & pipeline->scheduler, NULL);
gst_scheduler_reset (GST_ELEMENT_SCHEDULER (object));
gst_object_replace ((GstObject **) & pipeline->fixed_clock, NULL);
G_OBJECT_CLASS (parent_class)->dispose (object);
@ -273,7 +272,7 @@ gst_pipeline_change_state (GstElement * element)
switch (GST_STATE_TRANSITION (element)) {
case GST_STATE_NULL_TO_READY:
gst_scheduler_setup (pipeline->scheduler);
gst_scheduler_setup (GST_ELEMENT_SCHEDULER (pipeline));
break;
case GST_STATE_READY_TO_PAUSED:
gst_element_set_clock (element, gst_element_get_clock (element));
@ -314,7 +313,7 @@ gst_pipeline_change_state (GstElement * element)
GstScheduler *
gst_pipeline_get_scheduler (GstPipeline * pipeline)
{
return pipeline->scheduler;
return gst_element_get_scheduler (GST_ELEMENT (pipeline));
}
/**
@ -328,7 +327,7 @@ gst_pipeline_get_scheduler (GstPipeline * pipeline)
GstBus *
gst_pipeline_get_bus (GstPipeline * pipeline)
{
return pipeline->bus;
return gst_element_get_bus (GST_ELEMENT (pipeline));
}
static GstClock *
@ -438,18 +437,3 @@ gst_pipeline_auto_clock (GstPipeline * pipeline)
GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline using automatic clock");
}
/**
* gst_pipeline_post_message:
* @pipeline: the pipeline
* @message: the message
*
* Post a message on the message bus of this pipeline.
*
* Returns: TRUE if the message could be posted.
*/
gboolean
gst_pipeline_post_message (GstPipeline * pipeline, GstMessage * message)
{
return gst_bus_post (pipeline->bus, message);
}

View file

@ -48,8 +48,6 @@ typedef enum {
struct _GstPipeline {
GstBin bin;
GstBus *bus;
GstScheduler *scheduler;
GstClock *fixed_clock; /* fixed clock if any */
GList *eosed; /* list of elements that posted EOS */
@ -68,13 +66,12 @@ GstElement* gst_pipeline_new (const gchar *name);
GstScheduler* gst_pipeline_get_scheduler (GstPipeline *pipeline);
GstBus* gst_pipeline_get_bus (GstPipeline *pipeline);
void gst_pipeline_use_clock (GstPipeline *pipeline, GstClock *clock);
void gst_pipeline_set_clock (GstPipeline *pipeline, GstClock *clock);
GstClock* gst_pipeline_get_clock (GstPipeline *pipeline);
void gst_pipeline_auto_clock (GstPipeline *pipeline);
gboolean gst_pipeline_post_message (GstPipeline *pipeline, GstMessage *message);
G_END_DECLS
#endif /* __GST_PIPELINE_H__ */

View file

@ -125,9 +125,9 @@ static void gst_queue_get_property (GObject * object,
guint prop_id, GValue * value, GParamSpec * pspec);
static GstFlowReturn gst_queue_chain (GstPad * pad, GstBuffer * buffer);
static GstFlowReturn gst_queue_get (GstPad * pad, GstBuffer ** buffer);
static GstBuffer *gst_queue_bufferalloc (GstPad * pad, guint64 offset,
guint size, GstCaps * caps);
static gboolean gst_queue_loop (GstPad * pad);
static gboolean gst_queue_handle_sink_event (GstPad * pad, GstEvent * event);
@ -312,7 +312,7 @@ gst_queue_init (GstQueue * queue)
queue->srcpad =
gst_pad_new_from_template (gst_static_pad_template_get (&srctemplate),
"src");
gst_pad_set_get_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_get));
gst_pad_set_loop_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_loop));
gst_pad_set_activate_function (queue->srcpad,
GST_DEBUG_FUNCPTR (gst_queue_src_activate));
gst_pad_set_link_function (queue->srcpad,
@ -433,8 +433,6 @@ gst_queue_locked_flush (GstQueue * queue)
while (!g_queue_is_empty (queue->queue)) {
GstData *data = g_queue_pop_head (queue->queue);
/* First loose the reference we added when putting that data in the queue */
gst_data_unref (data);
/* Then loose another reference because we are supposed to destroy that
data when flushing */
gst_data_unref (data);
@ -492,7 +490,6 @@ gst_queue_handle_sink_event (GstPad * pad, GstEvent * event)
break;
}
gst_event_ref (event);
g_queue_push_tail (queue->queue, event);
g_cond_signal (queue->item_add);
GST_QUEUE_MUTEX_UNLOCK;
@ -621,11 +618,6 @@ gst_queue_chain (GstPad * pad, GstBuffer * buffer)
}
}
/* put the buffer on the tail of the list. We keep a reference,
* so that the buffer is read-only while in here. There's a good
* reason to do so: we have a size and time counter, and any
* modification to the content could change any of the two. */
gst_buffer_ref (buffer);
g_queue_push_tail (queue->queue, buffer);
/* add buffer to the statistics */
@ -648,14 +640,14 @@ out_unref:
return GST_FLOW_OK;
}
static GstFlowReturn
gst_queue_get (GstPad * pad, GstBuffer ** buffer)
static gboolean
gst_queue_loop (GstPad * pad)
{
GstQueue *queue;
GstData *data;
GstFlowReturn result = GST_FLOW_OK;
gboolean result = TRUE;
queue = GST_QUEUE (gst_object_get_parent (GST_OBJECT (pad)));
queue = GST_QUEUE (GST_PAD_PARENT (pad));
/* have to lock for thread-safety */
GST_QUEUE_MUTEX_LOCK;
@ -696,23 +688,16 @@ restart:
if (GST_BUFFER_DURATION (data) != GST_CLOCK_TIME_NONE)
queue->cur_level.time -= GST_BUFFER_DURATION (data);
*buffer = GST_BUFFER (data);
gst_pad_push (pad, GST_BUFFER (data));
} else {
if (GST_EVENT_TYPE (data) == GST_EVENT_EOS) {
result = GST_FLOW_WRONG_STATE;
result = FALSE;
}
gst_pad_push_event (queue->srcpad, GST_EVENT (data));
if (result == GST_FLOW_OK)
if (result == TRUE)
goto restart;
else
goto done;
}
/* Now that we're done, we can lose our own reference to
* the item, since we're no longer in danger. */
gst_data_unref (data);
done:
STATUS (queue, "after _get()");
GST_CAT_LOG_OBJECT (queue_dataflow, queue, "signalling item_del");
@ -784,37 +769,6 @@ gst_queue_handle_src_query (GstPad * pad,
return TRUE;
}
static void
gst_queue_loop (GstElement * element)
{
GstQueue *queue;
GstTask *task;
GstBuffer *buffer;
GstFlowReturn ret;
g_return_if_fail (element != NULL);
g_return_if_fail (GST_IS_QUEUE (element));
queue = GST_QUEUE (element);
task = queue->task;
ret = gst_queue_get (queue->srcpad, &buffer);
if (ret != GST_FLOW_OK) {
GST_CAT_LOG_OBJECT (queue_dataflow, queue, "stopping, get returned %d",
ret);
gst_task_stop (task);
return;
}
ret = gst_pad_push (queue->srcpad, buffer);
if (ret != GST_FLOW_OK) {
GST_CAT_LOG_OBJECT (queue_dataflow, queue, "stopping, push returned %d",
ret);
gst_task_stop (task);
return;
}
}
static gboolean
gst_queue_src_activate (GstPad * pad, gboolean active)
{
@ -825,18 +779,18 @@ gst_queue_src_activate (GstPad * pad, gboolean active)
if (active) {
/* if we have a scheduler we can start the task */
if (GST_ELEMENT_MANAGER (queue)) {
if (GST_ELEMENT_SCHEDULER (queue)) {
GST_STREAM_LOCK (pad);
queue->task =
gst_scheduler_create_task (GST_ELEMENT_MANAGER (queue)->scheduler,
(GstTaskFunction) gst_queue_loop, queue);
gst_scheduler_create_task (GST_ELEMENT_SCHEDULER (queue),
(GstTaskFunction) gst_queue_loop, pad);
gst_task_start (queue->task);
GST_STREAM_UNLOCK (pad);
result = TRUE;
}
} else {
/* step 1, unblock chain and get functions */
/* step 1, unblock chain and loop functions */
queue->interrupt = TRUE;
g_cond_signal (queue->item_add);
g_cond_signal (queue->item_del);
@ -865,8 +819,7 @@ gst_queue_change_state (GstElement * element)
GST_CAT_LOG_OBJECT (GST_CAT_STATES, element, "starting state change");
/* lock the queue so another thread (not in sync with this thread's state)
* can't call this queue's _get (or whatever)
*/
* can't call this queue's _loop (or whatever) */
GST_QUEUE_MUTEX_LOCK;
switch (GST_STATE_TRANSITION (element)) {

View file

@ -25,7 +25,7 @@
G_BEGIN_DECLS
typedef void (*GstTaskFunction) (void *data);
typedef gboolean (*GstTaskFunction) (void *data);
/* --- standard type macros --- */
#define GST_TYPE_TASK (gst_task_get_type ())

View file

@ -1294,6 +1294,16 @@ gst_pad_can_link_filtered (GstPad * srcpad, GstPad * sinkpad,
GST_DEBUG_PAD_NAME (realsink));
return FALSE;
}
if (!GST_PAD_IS_SRC (realsrc)) {
GST_CAT_INFO (GST_CAT_PADS, "Real src pad %s:%s is not source pad, failed",
GST_DEBUG_PAD_NAME (realsrc));
return FALSE;
}
if (!GST_PAD_IS_SINK (realsink)) {
GST_CAT_INFO (GST_CAT_PADS, "Real sink pad %s:%s is not sink pad, failed",
GST_DEBUG_PAD_NAME (realsink));
return FALSE;
}
if (GST_PAD_PARENT (realsrc) == NULL) {
GST_CAT_INFO (GST_CAT_PADS, "Real src pad %s:%s has no parent, failed",
GST_DEBUG_PAD_NAME (realsrc));

View file

@ -236,14 +236,18 @@ static void
gst_thread_scheduler_func (GstThreadSchedulerTask * task,
GstThreadScheduler * sched)
{
gboolean res;
gst_object_ref (GST_OBJECT (task));
GST_DEBUG_OBJECT (sched, "Entering task %p, thread %p", task,
g_thread_self ());
g_mutex_lock (task->lock);
while (task->state == STATE_STARTED) {
while (G_LIKELY (task->state == STATE_STARTED)) {
g_mutex_unlock (task->lock);
task->func (task->data);
res = task->func (task->data);
g_mutex_lock (task->lock);
if (G_UNLIKELY (!res))
task->state = STATE_STOPPED;
}
g_mutex_unlock (task->lock);
GST_DEBUG_OBJECT (sched, "Exit task %p, thread %p", task, g_thread_self ());

View file

@ -1 +1 @@
SUBDIRS = bytestream control dataprotocol getbits
SUBDIRS = control dataprotocol getbits

View file

@ -332,7 +332,7 @@ gst_fakesink_event (GstPad * pad, GstEvent * event)
{
gst_element_finish_preroll (GST_ELEMENT (fakesink),
GST_STREAM_GET_LOCK (pad));
gst_pipeline_post_message (GST_ELEMENT_MANAGER (fakesink),
gst_element_post_message (GST_ELEMENT (fakesink),
gst_message_new_eos (GST_OBJECT (fakesink)));
break;
}

View file

@ -189,8 +189,7 @@ static void gst_fakesrc_set_clock (GstElement * element, GstClock * clock);
static GstElementStateReturn gst_fakesrc_change_state (GstElement * element);
static GstFlowReturn gst_fakesrc_get (GstPad * pad, GstBuffer ** buffer);
static void gst_fakesrc_loop (GstElement * element);
static gboolean gst_fakesrc_loop (GstPad * pad);
static guint gst_fakesrc_signals[LAST_SIGNAL] = { 0 };
@ -471,13 +470,8 @@ gst_fakesrc_update_functions (GstFakeSrc * src)
while (pads) {
GstPad *pad = GST_PAD (pads->data);
if (src->loop_based) {
gst_pad_set_get_function (pad, NULL);
} else {
gst_pad_set_get_function (pad, GST_DEBUG_FUNCPTR (gst_fakesrc_get));
}
gst_pad_set_activate_function (pad, gst_fakesrc_activate);
gst_pad_set_loop_function (pad, gst_fakesrc_loop);
gst_pad_set_event_function (pad, gst_fakesrc_event_handler);
gst_pad_set_event_mask_function (pad, gst_fakesrc_get_event_mask);
gst_pad_set_query_function (pad, gst_fakesrc_query);
@ -784,20 +778,16 @@ gst_fakesrc_create_buffer (GstFakeSrc * src)
return buf;
}
static GstFlowReturn
gst_fakesrc_get (GstPad * pad, GstBuffer ** buffer)
static gboolean
gst_fakesrc_loop (GstPad * pad)
{
GstFakeSrc *src;
GstBuffer *buf;
GstClockTime time;
GstFlowReturn result = GST_FLOW_OK;
g_return_val_if_fail (pad != NULL, GST_FLOW_ERROR);
gboolean result = TRUE;
src = GST_FAKESRC (GST_OBJECT_PARENT (pad));
g_return_val_if_fail (GST_IS_FAKESRC (src), GST_FLOW_ERROR);
GST_STREAM_LOCK (pad);
if (src->need_flush) {
src->need_flush = FALSE;
@ -809,14 +799,14 @@ gst_fakesrc_get (GstPad * pad, GstBuffer ** buffer)
gst_pad_push_event (pad, gst_event_new (GST_EVENT_SEGMENT_DONE));
} else {
gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
result = GST_FLOW_UNEXPECTED;
result = FALSE;
goto done;
}
}
if (src->rt_num_buffers == 0) {
gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
result = GST_FLOW_UNEXPECTED;
result = FALSE;
goto done;
} else {
if (src->rt_num_buffers > 0)
@ -826,7 +816,7 @@ gst_fakesrc_get (GstPad * pad, GstBuffer ** buffer)
if (src->eos) {
GST_INFO ("fakesrc is setting eos on pad");
gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
result = GST_FLOW_UNEXPECTED;
result = FALSE;
goto done;
}
@ -866,7 +856,7 @@ gst_fakesrc_get (GstPad * pad, GstBuffer ** buffer)
src->bytes_sent += GST_BUFFER_SIZE (buf);
*buffer = buf;
gst_pad_push (pad, buf);
done:
GST_STREAM_UNLOCK (pad);
@ -874,26 +864,24 @@ done:
return result;
}
#if 0
/**
* gst_fakesrc_loop:
* @element: the faksesrc to loop
*
* generate an empty buffer and push it to the next element.
*/
static void
gst_fakesrc_loop (GstElement * element)
static gboolean
gst_fakesrc_loop (GstPad * pad)
{
GstFakeSrc *src;
const GList *pads;
GstTask *task;
g_return_if_fail (element != NULL);
g_return_if_fail (GST_IS_FAKESRC (element));
src = GST_FAKESRC (element);
src = GST_FAKESRC (GST_PAD_PARENT (pad));
task = src->task;
pads = element->pads;
pads = GST_ELEMENT (src)->pads;
while (pads) {
GstPad *pad = GST_PAD (pads->data);
@ -902,22 +890,21 @@ gst_fakesrc_loop (GstElement * element)
ret = gst_fakesrc_get (pad, &buffer);
if (ret != GST_FLOW_OK) {
gst_task_stop (task);
return;
return FALSE;
}
ret = gst_pad_push (pad, buffer);
if (ret != GST_FLOW_OK) {
gst_task_stop (task);
return;
return FALSE;
}
if (src->eos) {
gst_task_stop (task);
return;
return FALSE;
}
pads = g_list_next (pads);
}
return TRUE;
}
#endif
static gboolean
gst_fakesrc_activate (GstPad * pad, gboolean active)
@ -929,11 +916,11 @@ gst_fakesrc_activate (GstPad * pad, gboolean active)
if (active) {
/* if we have a scheduler we can start the task */
if (GST_ELEMENT_MANAGER (fakesrc)) {
if (GST_ELEMENT_SCHEDULER (fakesrc)) {
GST_STREAM_LOCK (pad);
fakesrc->task =
gst_scheduler_create_task (GST_ELEMENT_MANAGER (fakesrc)->scheduler,
(GstTaskFunction) gst_fakesrc_loop, fakesrc);
gst_scheduler_create_task (GST_ELEMENT_SCHEDULER (fakesrc),
(GstTaskFunction) gst_fakesrc_loop, pad);
gst_task_start (fakesrc->task);
GST_STREAM_UNLOCK (pad);

View file

@ -171,6 +171,8 @@ static void gst_filesrc_get_property (GObject * object, guint prop_id,
static gboolean gst_filesrc_check_filesize (GstFileSrc * src);
static GstFlowReturn gst_filesrc_get (GstPad * pad, GstBuffer ** buffer);
static GstFlowReturn gst_filesrc_getrange (GstPad * pad, guint64 offset,
guint length, GstBuffer ** buffer);
static gboolean gst_filesrc_srcpad_event (GstPad * pad, GstEvent * event);
static gboolean gst_filesrc_srcpad_query (GstPad * pad, GstQueryType type,
GstFormat * format, gint64 * value);
@ -248,7 +250,7 @@ gst_filesrc_init (GstFileSrc * src)
src->srcpad =
gst_pad_new_from_template (gst_static_pad_template_get (&srctemplate),
"src");
gst_pad_set_get_function (src->srcpad, gst_filesrc_get);
gst_pad_set_getrange_function (src->srcpad, gst_filesrc_getrange);
gst_pad_set_activate_function (src->srcpad, gst_filesrc_activate);
gst_pad_set_event_function (src->srcpad, gst_filesrc_srcpad_event);
gst_pad_set_event_mask_function (src->srcpad, gst_filesrc_get_event_mask);
@ -688,13 +690,27 @@ gst_filesrc_get_read (GstFileSrc * src)
return GST_DATA (buf);
}
static GstFlowReturn
gst_filesrc_getrange (GstPad * pad, guint64 offset, guint length,
GstBuffer ** buffer)
{
GstFileSrc *src;
src = GST_FILESRC (GST_PAD_PARENT (pad));
src->curoffset = offset;
src->block_size = length;
return gst_filesrc_get (pad, buffer);
}
static GstFlowReturn
gst_filesrc_get (GstPad * pad, GstBuffer ** buffer)
{
GstFileSrc *src;
GstData *data;
src = GST_FILESRC (gst_pad_get_parent (pad));
src = GST_FILESRC (GST_PAD_PARENT (pad));
g_return_val_if_fail (GST_FLAG_IS_SET (src, GST_FILESRC_OPEN),
GST_FLOW_WRONG_STATE);
@ -863,24 +879,25 @@ gst_filesrc_close_file (GstFileSrc * src)
GST_FLAG_UNSET (src, GST_FILESRC_OPEN);
}
static void
static gboolean
gst_filesrc_loop (GstElement * element)
{
GstFileSrc *filesrc;
GstFlowReturn result;
gboolean result;
GstBuffer *buffer;
filesrc = GST_FILESRC (element);
result = gst_filesrc_get (filesrc->srcpad, &buffer);
if (result != GST_FLOW_OK) {
gst_task_stop (filesrc->task);
return;
return FALSE;
}
result = gst_pad_push (filesrc->srcpad, buffer);
if (result != GST_FLOW_OK) {
gst_task_stop (filesrc->task);
return FALSE;
}
return TRUE;
}

View file

@ -125,9 +125,9 @@ static void gst_queue_get_property (GObject * object,
guint prop_id, GValue * value, GParamSpec * pspec);
static GstFlowReturn gst_queue_chain (GstPad * pad, GstBuffer * buffer);
static GstFlowReturn gst_queue_get (GstPad * pad, GstBuffer ** buffer);
static GstBuffer *gst_queue_bufferalloc (GstPad * pad, guint64 offset,
guint size, GstCaps * caps);
static gboolean gst_queue_loop (GstPad * pad);
static gboolean gst_queue_handle_sink_event (GstPad * pad, GstEvent * event);
@ -312,7 +312,7 @@ gst_queue_init (GstQueue * queue)
queue->srcpad =
gst_pad_new_from_template (gst_static_pad_template_get (&srctemplate),
"src");
gst_pad_set_get_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_get));
gst_pad_set_loop_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_loop));
gst_pad_set_activate_function (queue->srcpad,
GST_DEBUG_FUNCPTR (gst_queue_src_activate));
gst_pad_set_link_function (queue->srcpad,
@ -433,8 +433,6 @@ gst_queue_locked_flush (GstQueue * queue)
while (!g_queue_is_empty (queue->queue)) {
GstData *data = g_queue_pop_head (queue->queue);
/* First loose the reference we added when putting that data in the queue */
gst_data_unref (data);
/* Then loose another reference because we are supposed to destroy that
data when flushing */
gst_data_unref (data);
@ -492,7 +490,6 @@ gst_queue_handle_sink_event (GstPad * pad, GstEvent * event)
break;
}
gst_event_ref (event);
g_queue_push_tail (queue->queue, event);
g_cond_signal (queue->item_add);
GST_QUEUE_MUTEX_UNLOCK;
@ -621,11 +618,6 @@ gst_queue_chain (GstPad * pad, GstBuffer * buffer)
}
}
/* put the buffer on the tail of the list. We keep a reference,
* so that the buffer is read-only while in here. There's a good
* reason to do so: we have a size and time counter, and any
* modification to the content could change any of the two. */
gst_buffer_ref (buffer);
g_queue_push_tail (queue->queue, buffer);
/* add buffer to the statistics */
@ -648,14 +640,14 @@ out_unref:
return GST_FLOW_OK;
}
static GstFlowReturn
gst_queue_get (GstPad * pad, GstBuffer ** buffer)
static gboolean
gst_queue_loop (GstPad * pad)
{
GstQueue *queue;
GstData *data;
GstFlowReturn result = GST_FLOW_OK;
gboolean result = TRUE;
queue = GST_QUEUE (gst_object_get_parent (GST_OBJECT (pad)));
queue = GST_QUEUE (GST_PAD_PARENT (pad));
/* have to lock for thread-safety */
GST_QUEUE_MUTEX_LOCK;
@ -696,23 +688,16 @@ restart:
if (GST_BUFFER_DURATION (data) != GST_CLOCK_TIME_NONE)
queue->cur_level.time -= GST_BUFFER_DURATION (data);
*buffer = GST_BUFFER (data);
gst_pad_push (pad, GST_BUFFER (data));
} else {
if (GST_EVENT_TYPE (data) == GST_EVENT_EOS) {
result = GST_FLOW_WRONG_STATE;
result = FALSE;
}
gst_pad_push_event (queue->srcpad, GST_EVENT (data));
if (result == GST_FLOW_OK)
if (result == TRUE)
goto restart;
else
goto done;
}
/* Now that we're done, we can lose our own reference to
* the item, since we're no longer in danger. */
gst_data_unref (data);
done:
STATUS (queue, "after _get()");
GST_CAT_LOG_OBJECT (queue_dataflow, queue, "signalling item_del");
@ -784,37 +769,6 @@ gst_queue_handle_src_query (GstPad * pad,
return TRUE;
}
static void
gst_queue_loop (GstElement * element)
{
GstQueue *queue;
GstTask *task;
GstBuffer *buffer;
GstFlowReturn ret;
g_return_if_fail (element != NULL);
g_return_if_fail (GST_IS_QUEUE (element));
queue = GST_QUEUE (element);
task = queue->task;
ret = gst_queue_get (queue->srcpad, &buffer);
if (ret != GST_FLOW_OK) {
GST_CAT_LOG_OBJECT (queue_dataflow, queue, "stopping, get returned %d",
ret);
gst_task_stop (task);
return;
}
ret = gst_pad_push (queue->srcpad, buffer);
if (ret != GST_FLOW_OK) {
GST_CAT_LOG_OBJECT (queue_dataflow, queue, "stopping, push returned %d",
ret);
gst_task_stop (task);
return;
}
}
static gboolean
gst_queue_src_activate (GstPad * pad, gboolean active)
{
@ -825,18 +779,18 @@ gst_queue_src_activate (GstPad * pad, gboolean active)
if (active) {
/* if we have a scheduler we can start the task */
if (GST_ELEMENT_MANAGER (queue)) {
if (GST_ELEMENT_SCHEDULER (queue)) {
GST_STREAM_LOCK (pad);
queue->task =
gst_scheduler_create_task (GST_ELEMENT_MANAGER (queue)->scheduler,
(GstTaskFunction) gst_queue_loop, queue);
gst_scheduler_create_task (GST_ELEMENT_SCHEDULER (queue),
(GstTaskFunction) gst_queue_loop, pad);
gst_task_start (queue->task);
GST_STREAM_UNLOCK (pad);
result = TRUE;
}
} else {
/* step 1, unblock chain and get functions */
/* step 1, unblock chain and loop functions */
queue->interrupt = TRUE;
g_cond_signal (queue->item_add);
g_cond_signal (queue->item_del);
@ -865,8 +819,7 @@ gst_queue_change_state (GstElement * element)
GST_CAT_LOG_OBJECT (GST_CAT_STATES, element, "starting state change");
/* lock the queue so another thread (not in sync with this thread's state)
* can't call this queue's _get (or whatever)
*/
* can't call this queue's _loop (or whatever) */
GST_QUEUE_MUTEX_LOCK;
switch (GST_STATE_TRANSITION (element)) {

View file

@ -627,9 +627,9 @@ print_pad_info (GstElement * element)
if (realpad->chainfunc)
n_print (" Has chainfunc(): %s\n",
GST_DEBUG_FUNCPTR_NAME (realpad->chainfunc));
if (realpad->getfunc)
n_print (" Has getfunc(): %s\n",
GST_DEBUG_FUNCPTR_NAME (realpad->getfunc));
if (realpad->getrangefunc)
n_print (" Has getrangefunc(): %s\n",
GST_DEBUG_FUNCPTR_NAME (realpad->getrangefunc));
if (realpad->formatsfunc != gst_pad_get_formats_default) {
n_print (" Supports seeking/conversion/query formats:\n");
print_formats (gst_pad_get_formats (GST_PAD (realpad)));

View file

@ -471,7 +471,7 @@ main (int argc, char *argv[])
}
loop = g_main_loop_new (NULL, FALSE);
gst_bus_add_watch (GST_PIPELINE (pipeline)->bus,
gst_bus_add_watch (gst_element_get_bus (GST_ELEMENT (pipeline)),
(GstBusHandler) message_received, pipeline);

View file

@ -602,9 +602,9 @@ print_element_info (GstElementFactory * factory)
if (realpad->chainfunc)
PUT_STRING (4, "<chain-based function=\"%s\"/>",
GST_DEBUG_FUNCPTR_NAME (realpad->chainfunc));
if (realpad->getfunc)
PUT_STRING (4, "<get-based function=\"%s\"/>",
GST_DEBUG_FUNCPTR_NAME (realpad->getfunc));
if (realpad->getrangefunc)
PUT_STRING (4, "<get-range-based function=\"%s\"/>",
GST_DEBUG_FUNCPTR_NAME (realpad->getrangefunc));
if (realpad->formatsfunc != gst_pad_get_formats_default) {
PUT_STRING (4, "<formats-function function=\"%s\">",
GST_DEBUG_FUNCPTR_NAME (realpad->formatsfunc));