mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-16 19:25:18 +00:00
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:
parent
ccb77fc69f
commit
457e99ab07
24 changed files with 850 additions and 462 deletions
55
ChangeLog
55
ChangeLog
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
48
gst/gstbin.c
48
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);
|
||||
|
||||
|
|
|
@ -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--;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
607
gst/gstpad.c
607
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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
92
gst/gstpad.h
92
gst/gstpad.h
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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 ())
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 ());
|
||||
|
|
|
@ -1 +1 @@
|
|||
SUBDIRS = bytestream control dataprotocol getbits
|
||||
SUBDIRS = control dataprotocol getbits
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in a new issue