gst/elements/gstfakesrc.c (gst_fakesrc_class_init): Add HAS_LOOP and HAS_GETRANGE properties, readwrite + construct.

Original commit message from CVS:
2005-02-18  Andy Wingo  <wingo@pobox.com>

* gst/elements/gstfakesrc.c (gst_fakesrc_class_init): Add HAS_LOOP
and HAS_GETRANGE properties, readwrite + construct.
(gst_fakesrc_set_pad_functions)
(gst_fakesrc_set_all_pad_functions): New procs, like in fakesrc.
(gst_fakesrc_set_property, gst_fakesrc_get_property): Same as
fakesrc.
(gst_fakesrc_get_range_unlocked): New proc, factored out of the
core of _loop.
(gst_fakesrc_get_range): Getrange implementation for fakesink.
(gst_fakesrc_loop): Interface with get_range_unlocked.
(gst_fakesrc_activate): Add support for both activation modes,
with assertions.

* gst/elements/gstfakesink.h:
* gst/elements/gstfakesrc.h: Add has_loop and has_chain instance
variables.

* gst/elements/gstfakesink.c (gst_fakesink_class_init): Add
HAS_LOOP and HAS_CHAIN object properties, readwrite but also set
on construction.
(gst_fakesink_set_pad_functions): New proc, sets the functions on
one pad, setting the loop and chain functions properly.
(gst_fakesink_set_all_pad_functions): New proc, does
set_pad_functions on all pads.
(gst_fakesink_request_new_pad): Call set_pad_functions.
(gst_fakesink_set_property, gst_fakesink_get_property): When the
HAS_LOOP and HAS_CHAIN properties are set, reset the functions on
all pads.
(gst_fakesink_activate): Assert that the appropriate functions are
available for the activation mode.
(gst_fakesink_loop): Don't unref the buffer, chain_unlocked does
it for us.
This commit is contained in:
Andy Wingo 2005-02-18 11:21:50 +00:00
parent 325219ea1a
commit 69e9ca3e5f
9 changed files with 399 additions and 164 deletions

View file

@ -1,3 +1,38 @@
2005-02-18 Andy Wingo <wingo@pobox.com>
* gst/elements/gstfakesrc.c (gst_fakesrc_class_init): Add HAS_LOOP
and HAS_GETRANGE properties, readwrite + construct.
(gst_fakesrc_set_pad_functions)
(gst_fakesrc_set_all_pad_functions): New procs, like in fakesrc.
(gst_fakesrc_set_property, gst_fakesrc_get_property): Same as
fakesrc.
(gst_fakesrc_get_range_unlocked): New proc, factored out of the
core of _loop.
(gst_fakesrc_get_range): Getrange implementation for fakesink.
(gst_fakesrc_loop): Interface with get_range_unlocked.
(gst_fakesrc_activate): Add support for both activation modes,
with assertions.
* gst/elements/gstfakesink.h:
* gst/elements/gstfakesrc.h: Add has_loop and has_chain instance
variables.
* gst/elements/gstfakesink.c (gst_fakesink_class_init): Add
HAS_LOOP and HAS_CHAIN object properties, readwrite but also set
on construction.
(gst_fakesink_set_pad_functions): New proc, sets the functions on
one pad, setting the loop and chain functions properly.
(gst_fakesink_set_all_pad_functions): New proc, does
set_pad_functions on all pads.
(gst_fakesink_request_new_pad): Call set_pad_functions.
(gst_fakesink_set_property, gst_fakesink_get_property): When the
HAS_LOOP and HAS_CHAIN properties are set, reset the functions on
all pads.
(gst_fakesink_activate): Assert that the appropriate functions are
available for the activation mode.
(gst_fakesink_loop): Don't unref the buffer, chain_unlocked does
it for us.
2005-02-16 Wim Taymans <wim@fluendo.com>
* gst/elements/gstfakesink.c: (gst_fakesink_activate),

View file

@ -61,7 +61,9 @@ enum
ARG_DUMP,
ARG_SYNC,
ARG_SIGNAL_HANDOFFS,
ARG_LAST_MESSAGE
ARG_LAST_MESSAGE,
ARG_HAS_LOOP,
ARG_HAS_CHAIN
};
GstStaticPadTemplate fakesink_sink_template = GST_STATIC_PAD_TEMPLATE ("sink%d",
@ -171,6 +173,14 @@ gst_fakesink_class_init (GstFakeSinkClass * klass)
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUMP,
g_param_spec_boolean ("dump", "Dump", "Dump received bytes to stdout",
FALSE, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HAS_LOOP,
g_param_spec_boolean ("has-loop", "has-loop",
"Enable loop-based operation", TRUE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HAS_CHAIN,
g_param_spec_boolean ("has-chain", "has-chain",
"Enable chain-based operation", TRUE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
gst_fakesink_signals[SIGNAL_HANDOFF] =
g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
@ -194,11 +204,6 @@ gst_fakesink_init (GstFakeSink * fakesink)
gst_pad_new_from_template (gst_static_pad_template_get (&sinktemplate),
"sink");
gst_element_add_pad (GST_ELEMENT (fakesink), pad);
gst_pad_set_activate_function (pad,
GST_DEBUG_FUNCPTR (gst_fakesink_activate));
gst_pad_set_chain_function (pad, GST_DEBUG_FUNCPTR (gst_fakesink_chain));
gst_pad_set_loop_function (pad, GST_DEBUG_FUNCPTR (gst_fakesink_loop));
gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_fakesink_event));
fakesink->silent = FALSE;
fakesink->dump = FALSE;
@ -210,6 +215,33 @@ gst_fakesink_init (GstFakeSink * fakesink)
GST_RPAD_TASK (pad) = NULL;
}
static void
gst_fakesink_set_pad_functions (GstFakeSink * this, GstPad * pad)
{
gst_pad_set_activate_function (pad,
GST_DEBUG_FUNCPTR (gst_fakesink_activate));
gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_fakesink_event));
if (this->has_chain)
gst_pad_set_chain_function (pad, GST_DEBUG_FUNCPTR (gst_fakesink_chain));
else
gst_pad_set_chain_function (pad, NULL);
if (this->has_loop)
gst_pad_set_loop_function (pad, GST_DEBUG_FUNCPTR (gst_fakesink_loop));
else
gst_pad_set_loop_function (pad, NULL);
}
static void
gst_fakesink_set_all_pad_functions (GstFakeSink * this)
{
GList *l;
for (l = GST_ELEMENT_PADS (this); l; l = l->next)
gst_fakesink_set_pad_functions (this, (GstPad *) l->data);
}
static void
gst_fakesink_set_clock (GstElement * element, GstClock * clock)
{
@ -241,8 +273,7 @@ gst_fakesink_request_new_pad (GstElement * element, GstPadTemplate * templ,
sinkpad = gst_pad_new_from_template (templ, name);
g_free (name);
gst_pad_set_chain_function (sinkpad, GST_DEBUG_FUNCPTR (gst_fakesink_chain));
gst_fakesink_set_pad_functions (fakesink, sinkpad);
gst_element_add_pad (GST_ELEMENT (fakesink), sinkpad);
return sinkpad;
@ -258,6 +289,14 @@ gst_fakesink_set_property (GObject * object, guint prop_id,
sink = GST_FAKESINK (object);
switch (prop_id) {
case ARG_HAS_LOOP:
sink->has_loop = g_value_get_boolean (value);
gst_fakesink_set_all_pad_functions (sink);
break;
case ARG_HAS_CHAIN:
sink->has_chain = g_value_get_boolean (value);
gst_fakesink_set_all_pad_functions (sink);
break;
case ARG_SILENT:
sink->silent = g_value_get_boolean (value);
break;
@ -328,10 +367,12 @@ gst_fakesink_activate (GstPad * pad, GstActivateMode mode)
switch (mode) {
case GST_ACTIVATE_PUSH:
g_return_val_if_fail (fakesink->has_chain, FALSE);
result = TRUE;
break;
case GST_ACTIVATE_PULL:
/* if we have a scheduler we can start the task */
g_return_val_if_fail (fakesink->has_loop, FALSE);
if (GST_ELEMENT_SCHEDULER (fakesink)) {
GST_STREAM_LOCK (pad);
GST_RPAD_TASK (pad) =
@ -483,8 +524,6 @@ gst_fakesink_loop (GstPad * pad)
exit:
GST_STREAM_UNLOCK (pad);
if (buf)
gst_buffer_unref (buf);
return;
paused:

View file

@ -60,6 +60,8 @@ struct _GstFakeSink {
gboolean silent;
gboolean dump;
gboolean has_loop;
gboolean has_chain;
gboolean sync;
gboolean signal_handoffs;
GstClock *clock;

View file

@ -64,7 +64,8 @@ enum
{
ARG_0,
ARG_NUM_SOURCES,
ARG_LOOP_BASED,
ARG_HAS_LOOP,
ARG_HAS_GETRANGE,
ARG_OUTPUT,
ARG_DATA,
ARG_SIZETYPE,
@ -179,7 +180,6 @@ GST_BOILERPLATE_FULL (GstFakeSrc, gst_fakesrc, GstElement, GST_TYPE_ELEMENT,
static GstPad *gst_fakesrc_request_new_pad (GstElement * element,
GstPadTemplate * templ, const gchar * unused);
static void gst_fakesrc_update_functions (GstFakeSrc * src);
static gboolean gst_fakesrc_activate (GstPad * pad, GstActivateMode mode);
static void gst_fakesrc_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
@ -190,6 +190,8 @@ static void gst_fakesrc_set_clock (GstElement * element, GstClock * clock);
static GstElementStateReturn gst_fakesrc_change_state (GstElement * element);
static void gst_fakesrc_loop (GstPad * pad);
static GstFlowReturn gst_fakesrc_get_range (GstPad * pad, guint64 offset,
guint length, GstBuffer ** buf);
static guint gst_fakesrc_signals[LAST_SIGNAL] = { 0 };
@ -220,9 +222,14 @@ gst_fakesrc_class_init (GstFakeSrcClass * klass)
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_SOURCES,
g_param_spec_int ("num-sources", "num-sources", "Number of sources",
1, G_MAXINT, 1, G_PARAM_READABLE));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOOP_BASED,
g_param_spec_boolean ("loop-based", "loop-based",
"Enable loop-based operation", FALSE, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HAS_LOOP,
g_param_spec_boolean ("has-loop", "has-loop",
"Enable loop-based operation", TRUE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HAS_GETRANGE,
g_param_spec_boolean ("has-getrange", "has-getrange",
"Enable getrange-based operation", TRUE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_OUTPUT,
g_param_spec_enum ("output", "output", "Output method (currently unused)",
GST_TYPE_FAKESRC_OUTPUT, FAKESRC_FIRST_LAST_LOOP, G_PARAM_READWRITE));
@ -300,9 +307,6 @@ gst_fakesrc_init (GstFakeSrc * fakesrc)
"src");
gst_element_add_pad (GST_ELEMENT (fakesrc), pad);
fakesrc->loop_based = FALSE;
gst_fakesrc_update_functions (fakesrc);
fakesrc->output = FAKESRC_FIRST_LAST_LOOP;
fakesrc->segment_start = -1;
fakesrc->segment_end = -1;
@ -336,35 +340,6 @@ gst_fakesrc_set_clock (GstElement * element, GstClock * clock)
src->clock = clock;
}
static GstPad *
gst_fakesrc_request_new_pad (GstElement * element, GstPadTemplate * templ,
const gchar * unused)
{
gchar *name;
GstPad *srcpad;
GstFakeSrc *fakesrc;
g_return_val_if_fail (GST_IS_FAKESRC (element), NULL);
if (templ->direction != GST_PAD_SRC) {
g_warning ("gstfakesrc: request new pad that is not a SRC pad\n");
return NULL;
}
fakesrc = GST_FAKESRC (element);
name = g_strdup_printf ("src%d", GST_ELEMENT (fakesrc)->numsrcpads);
srcpad = gst_pad_new_from_template (templ, name);
gst_element_add_pad (GST_ELEMENT (fakesrc), srcpad);
gst_fakesrc_update_functions (fakesrc);
g_free (name);
return srcpad;
}
static const GstFormat *
gst_fakesrc_get_formats (GstPad * pad)
{
@ -455,23 +430,61 @@ gst_fakesrc_event_handler (GstPad * pad, GstEvent * event)
}
static void
gst_fakesrc_update_functions (GstFakeSrc * src)
gst_fakesrc_set_pad_functions (GstFakeSrc * src, GstPad * pad)
{
GList *pads;
gst_pad_set_activate_function (pad, gst_fakesrc_activate);
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);
gst_pad_set_query_type_function (pad, gst_fakesrc_get_query_types);
gst_pad_set_formats_function (pad, gst_fakesrc_get_formats);
pads = GST_ELEMENT (src)->pads;
while (pads) {
GstPad *pad = GST_PAD (pads->data);
gst_pad_set_activate_function (pad, gst_fakesrc_activate);
if (src->has_loop)
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);
gst_pad_set_query_type_function (pad, gst_fakesrc_get_query_types);
gst_pad_set_formats_function (pad, gst_fakesrc_get_formats);
pads = g_list_next (pads);
else
gst_pad_set_loop_function (pad, NULL);
if (src->has_getrange)
gst_pad_set_getrange_function (pad, gst_fakesrc_get_range);
else
gst_pad_set_getrange_function (pad, NULL);
}
static void
gst_fakesrc_set_all_pad_functions (GstFakeSrc * src)
{
GList *l;
for (l = GST_ELEMENT_PADS (src); l; l = l->next)
gst_fakesrc_set_pad_functions (src, (GstPad *) l->data);
}
static GstPad *
gst_fakesrc_request_new_pad (GstElement * element, GstPadTemplate * templ,
const gchar * unused)
{
gchar *name;
GstPad *srcpad;
GstFakeSrc *fakesrc;
g_return_val_if_fail (GST_IS_FAKESRC (element), NULL);
if (templ->direction != GST_PAD_SRC) {
g_warning ("gstfakesrc: request new pad that is not a SRC pad\n");
return NULL;
}
fakesrc = GST_FAKESRC (element);
name = g_strdup_printf ("src%d", GST_ELEMENT (fakesrc)->numsrcpads);
srcpad = gst_pad_new_from_template (templ, name);
gst_element_add_pad (GST_ELEMENT (fakesrc), srcpad);
gst_fakesrc_set_pad_functions (fakesrc, srcpad);
g_free (name);
return srcpad;
}
static void
@ -493,13 +506,16 @@ gst_fakesrc_set_property (GObject * object, guint prop_id, const GValue * value,
{
GstFakeSrc *src;
/* it's not null if we got it, but it might not be ours */
src = GST_FAKESRC (object);
switch (prop_id) {
case ARG_LOOP_BASED:
src->loop_based = g_value_get_boolean (value);
gst_fakesrc_update_functions (src);
case ARG_HAS_LOOP:
src->has_loop = g_value_get_boolean (value);
gst_fakesrc_set_all_pad_functions (src);
break;
case ARG_HAS_GETRANGE:
src->has_getrange = g_value_get_boolean (value);
gst_fakesrc_set_all_pad_functions (src);
break;
case ARG_OUTPUT:
g_warning ("not yet implemented");
@ -577,8 +593,11 @@ gst_fakesrc_get_property (GObject * object, guint prop_id, GValue * value,
case ARG_NUM_SOURCES:
g_value_set_int (value, GST_ELEMENT (src)->numsrcpads);
break;
case ARG_LOOP_BASED:
g_value_set_boolean (value, src->loop_based);
case ARG_HAS_LOOP:
g_value_set_boolean (value, src->has_loop);
break;
case ARG_HAS_GETRANGE:
g_value_set_boolean (value, src->has_getrange);
break;
case ARG_OUTPUT:
g_value_set_enum (value, src->output);
@ -771,34 +790,28 @@ gst_fakesrc_create_buffer (GstFakeSrc * src)
return buf;
}
static void
gst_fakesrc_loop (GstPad * pad)
static GstFlowReturn
gst_fakesrc_get_range_unlocked (GstPad * pad, guint64 offset, guint length,
GstBuffer ** ret)
{
GstFakeSrc *src;
GstBuffer *buf;
GstClockTime time;
GstFlowReturn ret;
src = GST_FAKESRC (GST_OBJECT_PARENT (pad));
GST_STREAM_LOCK (pad);
if (src->need_flush) {
src->need_flush = FALSE;
gst_pad_push_event (pad, gst_event_new (GST_EVENT_FLUSH));
}
if (src->buffer_count == src->segment_end) {
if (src->segment_loop) {
//gst_pad_push_event (pad, gst_event_new (GST_EVENT_SEGMENT_DONE));
} else {
gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
goto pause;
return GST_FLOW_UNEXPECTED;
}
}
if (src->rt_num_buffers == 0) {
gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
goto pause;
return GST_FLOW_UNEXPECTED;
} else {
if (src->rt_num_buffers > 0)
src->rt_num_buffers--;
@ -807,7 +820,7 @@ gst_fakesrc_loop (GstPad * pad)
if (src->eos) {
GST_INFO ("fakesrc is setting eos on pad");
gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
goto pause;
return GST_FLOW_UNEXPECTED;
}
buf = gst_fakesrc_create_buffer (src);
@ -846,6 +859,46 @@ gst_fakesrc_loop (GstPad * pad)
src->bytes_sent += GST_BUFFER_SIZE (buf);
*ret = buf;
return GST_FLOW_OK;
}
static GstFlowReturn
gst_fakesrc_get_range (GstPad * pad, guint64 offset, guint length,
GstBuffer ** ret)
{
GstFlowReturn fret;
GST_STREAM_LOCK (pad);
fret = gst_fakesrc_get_range_unlocked (pad, offset, length, ret);
GST_STREAM_UNLOCK (pad);
return fret;
}
static void
gst_fakesrc_loop (GstPad * pad)
{
GstFakeSrc *src;
GstBuffer *buf = NULL;
GstFlowReturn ret;
src = GST_FAKESRC (GST_OBJECT_PARENT (pad));
GST_STREAM_LOCK (pad);
if (src->need_flush) {
src->need_flush = FALSE;
gst_pad_push_event (pad, gst_event_new (GST_EVENT_FLUSH));
}
ret = gst_fakesrc_get_range_unlocked (pad, src->buffer_count,
DEFAULT_SIZEMAX, &buf);
if (ret != GST_FLOW_OK) {
goto pause;
}
ret = gst_pad_push (pad, buf);
if (ret != GST_FLOW_OK) {
goto pause;
@ -871,6 +924,7 @@ gst_fakesrc_activate (GstPad * pad, GstActivateMode mode)
switch (mode) {
case GST_ACTIVATE_PUSH:
/* if we have a scheduler we can start the task */
g_return_val_if_fail (fakesrc->has_loop, FALSE);
if (GST_ELEMENT_SCHEDULER (fakesrc)) {
GST_STREAM_LOCK (pad);
fakesrc->task =
@ -883,6 +937,8 @@ gst_fakesrc_activate (GstPad * pad, GstActivateMode mode)
}
break;
case GST_ACTIVATE_PULL:
g_return_val_if_fail (fakesrc->has_getrange, FALSE);
result = TRUE;
break;
case GST_ACTIVATE_NONE:
/* step 1, unblock clock sync (if any) */
@ -890,9 +946,11 @@ gst_fakesrc_activate (GstPad * pad, GstActivateMode mode)
/* step 2, make sure streaming finishes */
GST_STREAM_LOCK (pad);
/* step 3, stop the task */
gst_task_stop (fakesrc->task);
gst_object_unref (GST_OBJECT (fakesrc->task));
fakesrc->task = NULL;
if (fakesrc->task) {
gst_task_stop (fakesrc->task);
gst_object_unref (GST_OBJECT (fakesrc->task));
fakesrc->task = NULL;
}
GST_STREAM_UNLOCK (pad);
result = TRUE;

View file

@ -76,7 +76,8 @@ typedef struct _GstFakeSrcClass GstFakeSrcClass;
struct _GstFakeSrc {
GstElement element;
gboolean loop_based;
gboolean has_loop;
gboolean has_getrange;
gboolean eos;
GstTask *task;

View file

@ -61,7 +61,9 @@ enum
ARG_DUMP,
ARG_SYNC,
ARG_SIGNAL_HANDOFFS,
ARG_LAST_MESSAGE
ARG_LAST_MESSAGE,
ARG_HAS_LOOP,
ARG_HAS_CHAIN
};
GstStaticPadTemplate fakesink_sink_template = GST_STATIC_PAD_TEMPLATE ("sink%d",
@ -171,6 +173,14 @@ gst_fakesink_class_init (GstFakeSinkClass * klass)
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUMP,
g_param_spec_boolean ("dump", "Dump", "Dump received bytes to stdout",
FALSE, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HAS_LOOP,
g_param_spec_boolean ("has-loop", "has-loop",
"Enable loop-based operation", TRUE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HAS_CHAIN,
g_param_spec_boolean ("has-chain", "has-chain",
"Enable chain-based operation", TRUE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
gst_fakesink_signals[SIGNAL_HANDOFF] =
g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
@ -194,11 +204,6 @@ gst_fakesink_init (GstFakeSink * fakesink)
gst_pad_new_from_template (gst_static_pad_template_get (&sinktemplate),
"sink");
gst_element_add_pad (GST_ELEMENT (fakesink), pad);
gst_pad_set_activate_function (pad,
GST_DEBUG_FUNCPTR (gst_fakesink_activate));
gst_pad_set_chain_function (pad, GST_DEBUG_FUNCPTR (gst_fakesink_chain));
gst_pad_set_loop_function (pad, GST_DEBUG_FUNCPTR (gst_fakesink_loop));
gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_fakesink_event));
fakesink->silent = FALSE;
fakesink->dump = FALSE;
@ -210,6 +215,33 @@ gst_fakesink_init (GstFakeSink * fakesink)
GST_RPAD_TASK (pad) = NULL;
}
static void
gst_fakesink_set_pad_functions (GstFakeSink * this, GstPad * pad)
{
gst_pad_set_activate_function (pad,
GST_DEBUG_FUNCPTR (gst_fakesink_activate));
gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_fakesink_event));
if (this->has_chain)
gst_pad_set_chain_function (pad, GST_DEBUG_FUNCPTR (gst_fakesink_chain));
else
gst_pad_set_chain_function (pad, NULL);
if (this->has_loop)
gst_pad_set_loop_function (pad, GST_DEBUG_FUNCPTR (gst_fakesink_loop));
else
gst_pad_set_loop_function (pad, NULL);
}
static void
gst_fakesink_set_all_pad_functions (GstFakeSink * this)
{
GList *l;
for (l = GST_ELEMENT_PADS (this); l; l = l->next)
gst_fakesink_set_pad_functions (this, (GstPad *) l->data);
}
static void
gst_fakesink_set_clock (GstElement * element, GstClock * clock)
{
@ -241,8 +273,7 @@ gst_fakesink_request_new_pad (GstElement * element, GstPadTemplate * templ,
sinkpad = gst_pad_new_from_template (templ, name);
g_free (name);
gst_pad_set_chain_function (sinkpad, GST_DEBUG_FUNCPTR (gst_fakesink_chain));
gst_fakesink_set_pad_functions (fakesink, sinkpad);
gst_element_add_pad (GST_ELEMENT (fakesink), sinkpad);
return sinkpad;
@ -258,6 +289,14 @@ gst_fakesink_set_property (GObject * object, guint prop_id,
sink = GST_FAKESINK (object);
switch (prop_id) {
case ARG_HAS_LOOP:
sink->has_loop = g_value_get_boolean (value);
gst_fakesink_set_all_pad_functions (sink);
break;
case ARG_HAS_CHAIN:
sink->has_chain = g_value_get_boolean (value);
gst_fakesink_set_all_pad_functions (sink);
break;
case ARG_SILENT:
sink->silent = g_value_get_boolean (value);
break;
@ -328,10 +367,12 @@ gst_fakesink_activate (GstPad * pad, GstActivateMode mode)
switch (mode) {
case GST_ACTIVATE_PUSH:
g_return_val_if_fail (fakesink->has_chain, FALSE);
result = TRUE;
break;
case GST_ACTIVATE_PULL:
/* if we have a scheduler we can start the task */
g_return_val_if_fail (fakesink->has_loop, FALSE);
if (GST_ELEMENT_SCHEDULER (fakesink)) {
GST_STREAM_LOCK (pad);
GST_RPAD_TASK (pad) =
@ -483,8 +524,6 @@ gst_fakesink_loop (GstPad * pad)
exit:
GST_STREAM_UNLOCK (pad);
if (buf)
gst_buffer_unref (buf);
return;
paused:

View file

@ -60,6 +60,8 @@ struct _GstFakeSink {
gboolean silent;
gboolean dump;
gboolean has_loop;
gboolean has_chain;
gboolean sync;
gboolean signal_handoffs;
GstClock *clock;

View file

@ -64,7 +64,8 @@ enum
{
ARG_0,
ARG_NUM_SOURCES,
ARG_LOOP_BASED,
ARG_HAS_LOOP,
ARG_HAS_GETRANGE,
ARG_OUTPUT,
ARG_DATA,
ARG_SIZETYPE,
@ -179,7 +180,6 @@ GST_BOILERPLATE_FULL (GstFakeSrc, gst_fakesrc, GstElement, GST_TYPE_ELEMENT,
static GstPad *gst_fakesrc_request_new_pad (GstElement * element,
GstPadTemplate * templ, const gchar * unused);
static void gst_fakesrc_update_functions (GstFakeSrc * src);
static gboolean gst_fakesrc_activate (GstPad * pad, GstActivateMode mode);
static void gst_fakesrc_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
@ -190,6 +190,8 @@ static void gst_fakesrc_set_clock (GstElement * element, GstClock * clock);
static GstElementStateReturn gst_fakesrc_change_state (GstElement * element);
static void gst_fakesrc_loop (GstPad * pad);
static GstFlowReturn gst_fakesrc_get_range (GstPad * pad, guint64 offset,
guint length, GstBuffer ** buf);
static guint gst_fakesrc_signals[LAST_SIGNAL] = { 0 };
@ -220,9 +222,14 @@ gst_fakesrc_class_init (GstFakeSrcClass * klass)
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUM_SOURCES,
g_param_spec_int ("num-sources", "num-sources", "Number of sources",
1, G_MAXINT, 1, G_PARAM_READABLE));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOOP_BASED,
g_param_spec_boolean ("loop-based", "loop-based",
"Enable loop-based operation", FALSE, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HAS_LOOP,
g_param_spec_boolean ("has-loop", "has-loop",
"Enable loop-based operation", TRUE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HAS_GETRANGE,
g_param_spec_boolean ("has-getrange", "has-getrange",
"Enable getrange-based operation", TRUE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_OUTPUT,
g_param_spec_enum ("output", "output", "Output method (currently unused)",
GST_TYPE_FAKESRC_OUTPUT, FAKESRC_FIRST_LAST_LOOP, G_PARAM_READWRITE));
@ -300,9 +307,6 @@ gst_fakesrc_init (GstFakeSrc * fakesrc)
"src");
gst_element_add_pad (GST_ELEMENT (fakesrc), pad);
fakesrc->loop_based = FALSE;
gst_fakesrc_update_functions (fakesrc);
fakesrc->output = FAKESRC_FIRST_LAST_LOOP;
fakesrc->segment_start = -1;
fakesrc->segment_end = -1;
@ -336,35 +340,6 @@ gst_fakesrc_set_clock (GstElement * element, GstClock * clock)
src->clock = clock;
}
static GstPad *
gst_fakesrc_request_new_pad (GstElement * element, GstPadTemplate * templ,
const gchar * unused)
{
gchar *name;
GstPad *srcpad;
GstFakeSrc *fakesrc;
g_return_val_if_fail (GST_IS_FAKESRC (element), NULL);
if (templ->direction != GST_PAD_SRC) {
g_warning ("gstfakesrc: request new pad that is not a SRC pad\n");
return NULL;
}
fakesrc = GST_FAKESRC (element);
name = g_strdup_printf ("src%d", GST_ELEMENT (fakesrc)->numsrcpads);
srcpad = gst_pad_new_from_template (templ, name);
gst_element_add_pad (GST_ELEMENT (fakesrc), srcpad);
gst_fakesrc_update_functions (fakesrc);
g_free (name);
return srcpad;
}
static const GstFormat *
gst_fakesrc_get_formats (GstPad * pad)
{
@ -455,23 +430,61 @@ gst_fakesrc_event_handler (GstPad * pad, GstEvent * event)
}
static void
gst_fakesrc_update_functions (GstFakeSrc * src)
gst_fakesrc_set_pad_functions (GstFakeSrc * src, GstPad * pad)
{
GList *pads;
gst_pad_set_activate_function (pad, gst_fakesrc_activate);
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);
gst_pad_set_query_type_function (pad, gst_fakesrc_get_query_types);
gst_pad_set_formats_function (pad, gst_fakesrc_get_formats);
pads = GST_ELEMENT (src)->pads;
while (pads) {
GstPad *pad = GST_PAD (pads->data);
gst_pad_set_activate_function (pad, gst_fakesrc_activate);
if (src->has_loop)
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);
gst_pad_set_query_type_function (pad, gst_fakesrc_get_query_types);
gst_pad_set_formats_function (pad, gst_fakesrc_get_formats);
pads = g_list_next (pads);
else
gst_pad_set_loop_function (pad, NULL);
if (src->has_getrange)
gst_pad_set_getrange_function (pad, gst_fakesrc_get_range);
else
gst_pad_set_getrange_function (pad, NULL);
}
static void
gst_fakesrc_set_all_pad_functions (GstFakeSrc * src)
{
GList *l;
for (l = GST_ELEMENT_PADS (src); l; l = l->next)
gst_fakesrc_set_pad_functions (src, (GstPad *) l->data);
}
static GstPad *
gst_fakesrc_request_new_pad (GstElement * element, GstPadTemplate * templ,
const gchar * unused)
{
gchar *name;
GstPad *srcpad;
GstFakeSrc *fakesrc;
g_return_val_if_fail (GST_IS_FAKESRC (element), NULL);
if (templ->direction != GST_PAD_SRC) {
g_warning ("gstfakesrc: request new pad that is not a SRC pad\n");
return NULL;
}
fakesrc = GST_FAKESRC (element);
name = g_strdup_printf ("src%d", GST_ELEMENT (fakesrc)->numsrcpads);
srcpad = gst_pad_new_from_template (templ, name);
gst_element_add_pad (GST_ELEMENT (fakesrc), srcpad);
gst_fakesrc_set_pad_functions (fakesrc, srcpad);
g_free (name);
return srcpad;
}
static void
@ -493,13 +506,16 @@ gst_fakesrc_set_property (GObject * object, guint prop_id, const GValue * value,
{
GstFakeSrc *src;
/* it's not null if we got it, but it might not be ours */
src = GST_FAKESRC (object);
switch (prop_id) {
case ARG_LOOP_BASED:
src->loop_based = g_value_get_boolean (value);
gst_fakesrc_update_functions (src);
case ARG_HAS_LOOP:
src->has_loop = g_value_get_boolean (value);
gst_fakesrc_set_all_pad_functions (src);
break;
case ARG_HAS_GETRANGE:
src->has_getrange = g_value_get_boolean (value);
gst_fakesrc_set_all_pad_functions (src);
break;
case ARG_OUTPUT:
g_warning ("not yet implemented");
@ -577,8 +593,11 @@ gst_fakesrc_get_property (GObject * object, guint prop_id, GValue * value,
case ARG_NUM_SOURCES:
g_value_set_int (value, GST_ELEMENT (src)->numsrcpads);
break;
case ARG_LOOP_BASED:
g_value_set_boolean (value, src->loop_based);
case ARG_HAS_LOOP:
g_value_set_boolean (value, src->has_loop);
break;
case ARG_HAS_GETRANGE:
g_value_set_boolean (value, src->has_getrange);
break;
case ARG_OUTPUT:
g_value_set_enum (value, src->output);
@ -771,34 +790,28 @@ gst_fakesrc_create_buffer (GstFakeSrc * src)
return buf;
}
static void
gst_fakesrc_loop (GstPad * pad)
static GstFlowReturn
gst_fakesrc_get_range_unlocked (GstPad * pad, guint64 offset, guint length,
GstBuffer ** ret)
{
GstFakeSrc *src;
GstBuffer *buf;
GstClockTime time;
GstFlowReturn ret;
src = GST_FAKESRC (GST_OBJECT_PARENT (pad));
GST_STREAM_LOCK (pad);
if (src->need_flush) {
src->need_flush = FALSE;
gst_pad_push_event (pad, gst_event_new (GST_EVENT_FLUSH));
}
if (src->buffer_count == src->segment_end) {
if (src->segment_loop) {
//gst_pad_push_event (pad, gst_event_new (GST_EVENT_SEGMENT_DONE));
} else {
gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
goto pause;
return GST_FLOW_UNEXPECTED;
}
}
if (src->rt_num_buffers == 0) {
gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
goto pause;
return GST_FLOW_UNEXPECTED;
} else {
if (src->rt_num_buffers > 0)
src->rt_num_buffers--;
@ -807,7 +820,7 @@ gst_fakesrc_loop (GstPad * pad)
if (src->eos) {
GST_INFO ("fakesrc is setting eos on pad");
gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
goto pause;
return GST_FLOW_UNEXPECTED;
}
buf = gst_fakesrc_create_buffer (src);
@ -846,6 +859,46 @@ gst_fakesrc_loop (GstPad * pad)
src->bytes_sent += GST_BUFFER_SIZE (buf);
*ret = buf;
return GST_FLOW_OK;
}
static GstFlowReturn
gst_fakesrc_get_range (GstPad * pad, guint64 offset, guint length,
GstBuffer ** ret)
{
GstFlowReturn fret;
GST_STREAM_LOCK (pad);
fret = gst_fakesrc_get_range_unlocked (pad, offset, length, ret);
GST_STREAM_UNLOCK (pad);
return fret;
}
static void
gst_fakesrc_loop (GstPad * pad)
{
GstFakeSrc *src;
GstBuffer *buf = NULL;
GstFlowReturn ret;
src = GST_FAKESRC (GST_OBJECT_PARENT (pad));
GST_STREAM_LOCK (pad);
if (src->need_flush) {
src->need_flush = FALSE;
gst_pad_push_event (pad, gst_event_new (GST_EVENT_FLUSH));
}
ret = gst_fakesrc_get_range_unlocked (pad, src->buffer_count,
DEFAULT_SIZEMAX, &buf);
if (ret != GST_FLOW_OK) {
goto pause;
}
ret = gst_pad_push (pad, buf);
if (ret != GST_FLOW_OK) {
goto pause;
@ -871,6 +924,7 @@ gst_fakesrc_activate (GstPad * pad, GstActivateMode mode)
switch (mode) {
case GST_ACTIVATE_PUSH:
/* if we have a scheduler we can start the task */
g_return_val_if_fail (fakesrc->has_loop, FALSE);
if (GST_ELEMENT_SCHEDULER (fakesrc)) {
GST_STREAM_LOCK (pad);
fakesrc->task =
@ -883,6 +937,8 @@ gst_fakesrc_activate (GstPad * pad, GstActivateMode mode)
}
break;
case GST_ACTIVATE_PULL:
g_return_val_if_fail (fakesrc->has_getrange, FALSE);
result = TRUE;
break;
case GST_ACTIVATE_NONE:
/* step 1, unblock clock sync (if any) */
@ -890,9 +946,11 @@ gst_fakesrc_activate (GstPad * pad, GstActivateMode mode)
/* step 2, make sure streaming finishes */
GST_STREAM_LOCK (pad);
/* step 3, stop the task */
gst_task_stop (fakesrc->task);
gst_object_unref (GST_OBJECT (fakesrc->task));
fakesrc->task = NULL;
if (fakesrc->task) {
gst_task_stop (fakesrc->task);
gst_object_unref (GST_OBJECT (fakesrc->task));
fakesrc->task = NULL;
}
GST_STREAM_UNLOCK (pad);
result = TRUE;

View file

@ -76,7 +76,8 @@ typedef struct _GstFakeSrcClass GstFakeSrcClass;
struct _GstFakeSrc {
GstElement element;
gboolean loop_based;
gboolean has_loop;
gboolean has_getrange;
gboolean eos;
GstTask *task;