diff --git a/ChangeLog b/ChangeLog index 09ca338e4b..4bd49ce44a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,58 @@ +2004-12-20 Wim Taymans + + * 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 * check/gst/gstobject.c: diff --git a/gst/elements/gstfakesink.c b/gst/elements/gstfakesink.c index 76135d2593..08ec8dfbba 100644 --- a/gst/elements/gstfakesink.c +++ b/gst/elements/gstfakesink.c @@ -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; } diff --git a/gst/elements/gstfakesrc.c b/gst/elements/gstfakesrc.c index 570f0fe661..1bbecc8e53 100644 --- a/gst/elements/gstfakesrc.c +++ b/gst/elements/gstfakesrc.c @@ -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); diff --git a/gst/elements/gstfilesrc.c b/gst/elements/gstfilesrc.c index 5dca556b21..c7f6f6d747 100644 --- a/gst/elements/gstfilesrc.c +++ b/gst/elements/gstfilesrc.c @@ -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; } diff --git a/gst/gstbin.c b/gst/gstbin.c index b4346ad58f..d4a29dcfb9 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -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); diff --git a/gst/gstcaps.c b/gst/gstcaps.c index df73055bfc..f7eaa3d580 100644 --- a/gst/gstcaps.c +++ b/gst/gstcaps.c @@ -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--; } } diff --git a/gst/gstelement.c b/gst/gstelement.c index 9e06da25f0..17eb08c4b7 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -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; diff --git a/gst/gstobject.c b/gst/gstobject.c index 1165f0ee22..b7f2de0ee8 100644 --- a/gst/gstobject.c +++ b/gst/gstobject.c @@ -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 diff --git a/gst/gstpad.c b/gst/gstpad.c index 683cdffb4a..5696b3d4ca 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -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; + } } /** diff --git a/gst/gstpad.h b/gst/gstpad.h index 9327a4f22c..71f7e2af56 100644 --- a/gst/gstpad.h +++ b/gst/gstpad.h @@ -32,6 +32,7 @@ #include #include #include +#include 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); diff --git a/gst/gstpipeline.c b/gst/gstpipeline.c index 97652733b7..1d0dab1b3a 100644 --- a/gst/gstpipeline.c +++ b/gst/gstpipeline.c @@ -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); -} diff --git a/gst/gstpipeline.h b/gst/gstpipeline.h index d8e31805c1..830b4e18dd 100644 --- a/gst/gstpipeline.h +++ b/gst/gstpipeline.h @@ -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__ */ diff --git a/gst/gstqueue.c b/gst/gstqueue.c index 8727967025..325d1f104c 100644 --- a/gst/gstqueue.c +++ b/gst/gstqueue.c @@ -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)) { diff --git a/gst/gsttask.h b/gst/gsttask.h index 4b7caad8d9..429fd7606b 100644 --- a/gst/gsttask.h +++ b/gst/gsttask.h @@ -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 ()) diff --git a/gst/gstutils.c b/gst/gstutils.c index 4739e72035..a9220290fa 100644 --- a/gst/gstutils.c +++ b/gst/gstutils.c @@ -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)); diff --git a/gst/schedulers/threadscheduler.c b/gst/schedulers/threadscheduler.c index e473f7c11f..f7e87c3e9b 100644 --- a/gst/schedulers/threadscheduler.c +++ b/gst/schedulers/threadscheduler.c @@ -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 ()); diff --git a/libs/gst/Makefile.am b/libs/gst/Makefile.am index 86d6564def..e778366c40 100644 --- a/libs/gst/Makefile.am +++ b/libs/gst/Makefile.am @@ -1 +1 @@ -SUBDIRS = bytestream control dataprotocol getbits +SUBDIRS = control dataprotocol getbits diff --git a/plugins/elements/gstfakesink.c b/plugins/elements/gstfakesink.c index 76135d2593..08ec8dfbba 100644 --- a/plugins/elements/gstfakesink.c +++ b/plugins/elements/gstfakesink.c @@ -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; } diff --git a/plugins/elements/gstfakesrc.c b/plugins/elements/gstfakesrc.c index 570f0fe661..1bbecc8e53 100644 --- a/plugins/elements/gstfakesrc.c +++ b/plugins/elements/gstfakesrc.c @@ -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); diff --git a/plugins/elements/gstfilesrc.c b/plugins/elements/gstfilesrc.c index 5dca556b21..c7f6f6d747 100644 --- a/plugins/elements/gstfilesrc.c +++ b/plugins/elements/gstfilesrc.c @@ -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; } diff --git a/plugins/elements/gstqueue.c b/plugins/elements/gstqueue.c index 8727967025..325d1f104c 100644 --- a/plugins/elements/gstqueue.c +++ b/plugins/elements/gstqueue.c @@ -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)) { diff --git a/tools/gst-inspect.c b/tools/gst-inspect.c index 1609d7d858..f951e9ab22 100644 --- a/tools/gst-inspect.c +++ b/tools/gst-inspect.c @@ -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))); diff --git a/tools/gst-launch.c b/tools/gst-launch.c index c72280484e..37d7fcd05c 100644 --- a/tools/gst-launch.c +++ b/tools/gst-launch.c @@ -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); diff --git a/tools/gst-xmlinspect.c b/tools/gst-xmlinspect.c index 723bc8431a..9ce4233104 100644 --- a/tools/gst-xmlinspect.c +++ b/tools/gst-xmlinspect.c @@ -602,9 +602,9 @@ print_element_info (GstElementFactory * factory) if (realpad->chainfunc) PUT_STRING (4, "", GST_DEBUG_FUNCPTR_NAME (realpad->chainfunc)); - if (realpad->getfunc) - PUT_STRING (4, "", - GST_DEBUG_FUNCPTR_NAME (realpad->getfunc)); + if (realpad->getrangefunc) + PUT_STRING (4, "", + GST_DEBUG_FUNCPTR_NAME (realpad->getrangefunc)); if (realpad->formatsfunc != gst_pad_get_formats_default) { PUT_STRING (4, "", GST_DEBUG_FUNCPTR_NAME (realpad->formatsfunc));