mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
check/pipelines/simple_launch_lines.c (run_pipeline): Check element_set_state's return val.
Original commit message from CVS: 2005-08-26 Andy Wingo <wingo@pobox.com> * check/pipelines/simple_launch_lines.c (run_pipeline): Check element_set_state's return val. (test_2_elements): Add test that's been disabled for months. * gst/elements/gstfakesink.c: Cleanups. Add can-activate-push and can-activate-pull properties. * gst/elements/gstfakesrc.c: Cleanups. Add can-activate-push and can-activate-pull properties. Implement is_seekable so fakesrc can operate in pull mode. * gst/base/gstbasesink.c (GstBaseSink): Remove has-loop, has-chain properties. (gst_base_sink_activate, gst_base_sink_activate_pull) (gst_base_sink_activate_push): Make activation mode choosing work. Cleanups. (gst_base_sink_chain, gst_base_sink_loop): Assert activation mode is right. Make pull mode work. Post an eos before pausing in pull mode. (gst_base_sink_change_state): Pay attention to the core's change_state() return val. * gst/base/gstbasesrc.c (GstBaseSrc): Remove has-loop, has-getrange properties. Cleanups. * gst/base/gstbasesrc.h (GstBaseSrc): Remove has_loop, has_getrange and replace with can_activate_pull and can_activate_push. * gst/base/gstbasesink.h (GstBaseSink): Rearrange fields, add locking comments. Remove has_loop, has_chain and replace with can_activate_pull and can_activate_push.
This commit is contained in:
parent
e4b8f77538
commit
9d1b5e07b3
17 changed files with 529 additions and 372 deletions
35
ChangeLog
35
ChangeLog
|
@ -1,3 +1,38 @@
|
|||
2005-08-26 Andy Wingo <wingo@pobox.com>
|
||||
|
||||
* check/pipelines/simple_launch_lines.c (run_pipeline): Check
|
||||
element_set_state's return val.
|
||||
(test_2_elements): Add test that's been disabled for months.
|
||||
|
||||
* gst/elements/gstfakesink.c: Cleanups. Add can-activate-push and
|
||||
can-activate-pull properties.
|
||||
|
||||
* gst/elements/gstfakesrc.c: Cleanups. Add can-activate-push and
|
||||
can-activate-pull properties. Implement is_seekable so fakesrc can
|
||||
operate in pull mode.
|
||||
|
||||
* gst/base/gstbasesink.c (GstBaseSink): Remove has-loop, has-chain
|
||||
properties.
|
||||
(gst_base_sink_activate, gst_base_sink_activate_pull)
|
||||
(gst_base_sink_activate_push): Make activation mode choosing work.
|
||||
Cleanups.
|
||||
(gst_base_sink_chain, gst_base_sink_loop): Assert activation mode
|
||||
is right. Make pull mode work. Post an eos before pausing in pull
|
||||
mode.
|
||||
(gst_base_sink_change_state): Pay attention to the core's
|
||||
change_state() return val.
|
||||
|
||||
* gst/base/gstbasesrc.c (GstBaseSrc): Remove has-loop,
|
||||
has-getrange properties. Cleanups.
|
||||
|
||||
* gst/base/gstbasesrc.h (GstBaseSrc): Remove has_loop,
|
||||
has_getrange and replace with can_activate_pull and
|
||||
can_activate_push.
|
||||
|
||||
* gst/base/gstbasesink.h (GstBaseSink): Rearrange fields, add
|
||||
locking comments. Remove has_loop, has_chain and replace with
|
||||
can_activate_pull and can_activate_push.
|
||||
|
||||
2005-08-26 Jan Schmidt <thaytan@mad.scientist.com>
|
||||
|
||||
* configure.ac:
|
||||
|
|
|
@ -45,7 +45,10 @@ run_pipeline (GstElement * pipe, gchar * descr,
|
|||
|
||||
bus = gst_element_get_bus (pipe);
|
||||
g_assert (bus);
|
||||
gst_element_set_state (pipe, GST_STATE_PLAYING);
|
||||
if (gst_element_set_state (pipe, GST_STATE_PLAYING) != GST_STATE_SUCCESS) {
|
||||
g_critical ("Couldn't set pipeline to PLAYING");
|
||||
goto done;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
revent = gst_bus_poll (bus, GST_MESSAGE_ANY, GST_SECOND / 2);
|
||||
|
@ -67,6 +70,7 @@ run_pipeline (GstElement * pipe, gchar * descr,
|
|||
revent, tevent, descr);
|
||||
}
|
||||
|
||||
done:
|
||||
gst_element_set_state (pipe, GST_STATE_NULL);
|
||||
gst_object_unref (pipe);
|
||||
}
|
||||
|
@ -75,29 +79,25 @@ GST_START_TEST (test_2_elements)
|
|||
{
|
||||
gchar *s;
|
||||
|
||||
/* has-loop got unimplemented at some point, so these aren't actually testing
|
||||
* what they're supposed to -- a big ol' FIXME */
|
||||
|
||||
s = "fakesrc has-loop=false ! fakesink has-loop=true";
|
||||
s = "fakesrc can-activate-push=false ! fakesink can-activate-pull=true";
|
||||
run_pipeline (setup_pipeline (s), s,
|
||||
GST_MESSAGE_STATE_CHANGED, GST_MESSAGE_UNKNOWN);
|
||||
|
||||
s = "fakesrc has-loop=true ! fakesink has-loop=false";
|
||||
s = "fakesrc can-activate-push=true ! fakesink can-activate-pull=false";
|
||||
run_pipeline (setup_pipeline (s), s,
|
||||
GST_MESSAGE_STATE_CHANGED, GST_MESSAGE_UNKNOWN);
|
||||
|
||||
s = "fakesrc has-loop=false num-buffers=10 ! fakesink has-loop=true";
|
||||
s = "fakesrc can-activate-push=false num-buffers=10 ! fakesink can-activate-pull=true";
|
||||
run_pipeline (setup_pipeline (s), s,
|
||||
GST_MESSAGE_STATE_CHANGED, GST_MESSAGE_EOS);
|
||||
|
||||
s = "fakesrc has-loop=true num-buffers=10 ! fakesink has-loop=false";
|
||||
s = "fakesrc can-activate-push=true num-buffers=10 ! fakesink can-activate-pull=false";
|
||||
run_pipeline (setup_pipeline (s), s,
|
||||
GST_MESSAGE_STATE_CHANGED, GST_MESSAGE_EOS);
|
||||
|
||||
/* Should raise a critical, but doesn't with has-loop not working
|
||||
s = "fakesrc has-loop=false ! fakesink has-loop=false";
|
||||
ASSERT_CRITICAL (run_pipeline (setup_pipeline (s), s,
|
||||
GST_MESSAGE_STATE_CHANGED, GST_MESSAGE_UNKNOWN)); */
|
||||
s = "fakesrc can-activate-push=false ! fakesink can-activate-pull=false";
|
||||
ASSERT_CRITICAL (run_pipeline (setup_pipeline (s), s,
|
||||
GST_MESSAGE_STATE_CHANGED, GST_MESSAGE_UNKNOWN));
|
||||
}
|
||||
GST_END_TEST static void
|
||||
got_handoff (GstElement * sink, GstBuffer * buf, GstPad * pad, gpointer unused)
|
||||
|
|
|
@ -54,16 +54,13 @@ enum
|
|||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
/* FIXME, need to figure out a better way to handle the pull mode */
|
||||
#define DEFAULT_SIZE 1024
|
||||
#define DEFAULT_HAS_LOOP FALSE
|
||||
#define DEFAULT_HAS_CHAIN TRUE
|
||||
#define DEFAULT_CAN_ACTIVATE_PULL FALSE /* fixme: enable me */
|
||||
#define DEFAULT_CAN_ACTIVATE_PUSH TRUE
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_HAS_LOOP,
|
||||
PROP_HAS_CHAIN,
|
||||
PROP_PREROLL_QUEUE_LEN
|
||||
};
|
||||
|
||||
|
@ -116,7 +113,7 @@ static GstElementStateReturn gst_base_sink_change_state (GstElement * element);
|
|||
|
||||
static GstFlowReturn gst_base_sink_chain (GstPad * pad, GstBuffer * buffer);
|
||||
static void gst_base_sink_loop (GstPad * pad);
|
||||
static GstFlowReturn gst_base_sink_chain (GstPad * pad, GstBuffer * buffer);
|
||||
static gboolean gst_base_sink_activate (GstPad * pad);
|
||||
static gboolean gst_base_sink_activate_push (GstPad * pad, gboolean active);
|
||||
static gboolean gst_base_sink_activate_pull (GstPad * pad, gboolean active);
|
||||
static gboolean gst_base_sink_event (GstPad * pad, GstEvent * event);
|
||||
|
@ -147,14 +144,6 @@ gst_base_sink_class_init (GstBaseSinkClass * klass)
|
|||
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_base_sink_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_base_sink_get_property);
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HAS_LOOP,
|
||||
g_param_spec_boolean ("has-loop", "has-loop",
|
||||
"Enable loop-based operation", DEFAULT_HAS_LOOP,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HAS_CHAIN,
|
||||
g_param_spec_boolean ("has-chain", "has-chain",
|
||||
"Enable chain-based operation", DEFAULT_HAS_CHAIN,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
/* FIXME, this next value should be configured using an event from the
|
||||
* upstream element */
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass),
|
||||
|
@ -255,12 +244,25 @@ gst_base_sink_init (GstBaseSink * basesink, gpointer g_class)
|
|||
GST_DEBUG_FUNCPTR (gst_base_sink_pad_setcaps));
|
||||
gst_pad_set_bufferalloc_function (basesink->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_sink_pad_buffer_alloc));
|
||||
gst_pad_set_activate_function (basesink->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_sink_activate));
|
||||
gst_pad_set_activatepush_function (basesink->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_sink_activate_push));
|
||||
gst_pad_set_activatepull_function (basesink->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_sink_activate_pull));
|
||||
gst_pad_set_event_function (basesink->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_sink_event));
|
||||
gst_pad_set_chain_function (basesink->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_sink_chain));
|
||||
gst_element_add_pad (GST_ELEMENT (basesink), basesink->sinkpad);
|
||||
|
||||
basesink->pad_mode = GST_ACTIVATE_NONE;
|
||||
GST_PAD_TASK (basesink->sinkpad) = NULL;
|
||||
basesink->preroll_queue = g_queue_new ();
|
||||
|
||||
basesink->can_activate_push = DEFAULT_CAN_ACTIVATE_PUSH;
|
||||
basesink->can_activate_pull = DEFAULT_CAN_ACTIVATE_PULL;
|
||||
|
||||
GST_FLAG_SET (basesink, GST_ELEMENT_IS_SINK);
|
||||
}
|
||||
|
||||
|
@ -276,30 +278,6 @@ gst_base_sink_finalize (GObject * object)
|
|||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_base_sink_set_pad_functions (GstBaseSink * this, GstPad * pad)
|
||||
{
|
||||
gst_pad_set_activatepush_function (pad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_sink_activate_push));
|
||||
gst_pad_set_activatepull_function (pad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_sink_activate_pull));
|
||||
gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_base_sink_event));
|
||||
|
||||
if (this->has_chain)
|
||||
gst_pad_set_chain_function (pad, GST_DEBUG_FUNCPTR (gst_base_sink_chain));
|
||||
else
|
||||
gst_pad_set_chain_function (pad, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_base_sink_set_all_pad_functions (GstBaseSink * this)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = GST_ELEMENT_PADS (this); l; l = l->next)
|
||||
gst_base_sink_set_pad_functions (this, (GstPad *) l->data);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_base_sink_set_clock (GstElement * element, GstClock * clock)
|
||||
{
|
||||
|
@ -314,23 +292,9 @@ static void
|
|||
gst_base_sink_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstBaseSink *sink;
|
||||
|
||||
sink = GST_BASE_SINK (object);
|
||||
GstBaseSink *sink = GST_BASE_SINK (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_HAS_LOOP:
|
||||
GST_LOCK (sink);
|
||||
sink->has_loop = g_value_get_boolean (value);
|
||||
gst_base_sink_set_all_pad_functions (sink);
|
||||
GST_UNLOCK (sink);
|
||||
break;
|
||||
case PROP_HAS_CHAIN:
|
||||
GST_LOCK (sink);
|
||||
sink->has_chain = g_value_get_boolean (value);
|
||||
gst_base_sink_set_all_pad_functions (sink);
|
||||
GST_UNLOCK (sink);
|
||||
break;
|
||||
case PROP_PREROLL_QUEUE_LEN:
|
||||
/* preroll lock necessary to serialize with finish_preroll */
|
||||
GST_PREROLL_LOCK (sink->sinkpad);
|
||||
|
@ -347,18 +311,10 @@ static void
|
|||
gst_base_sink_get_property (GObject * object, guint prop_id, GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstBaseSink *sink;
|
||||
|
||||
sink = GST_BASE_SINK (object);
|
||||
GstBaseSink *sink = GST_BASE_SINK (object);
|
||||
|
||||
GST_LOCK (sink);
|
||||
switch (prop_id) {
|
||||
case PROP_HAS_LOOP:
|
||||
g_value_set_boolean (value, sink->has_loop);
|
||||
break;
|
||||
case PROP_HAS_CHAIN:
|
||||
g_value_set_boolean (value, sink->has_chain);
|
||||
break;
|
||||
case PROP_PREROLL_QUEUE_LEN:
|
||||
g_value_set_uint (value, sink->preroll_queue_max_len);
|
||||
break;
|
||||
|
@ -1037,15 +993,23 @@ gst_base_sink_chain (GstPad * pad, GstBuffer * buf)
|
|||
|
||||
basesink = GST_BASE_SINK (gst_pad_get_parent (pad));
|
||||
|
||||
if (!(basesink->pad_mode == GST_ACTIVATE_PUSH)) {
|
||||
GST_LOCK (pad);
|
||||
g_warning ("Push on pad %s:%s, but it was not activated in push mode",
|
||||
GST_DEBUG_PAD_NAME (pad));
|
||||
GST_UNLOCK (pad);
|
||||
result = GST_FLOW_UNEXPECTED;
|
||||
goto done;
|
||||
}
|
||||
|
||||
result = gst_base_sink_handle_object (basesink, pad, GST_MINI_OBJECT (buf));
|
||||
|
||||
done:
|
||||
gst_object_unref (basesink);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* FIXME, not all sinks can operate in pull mode
|
||||
*/
|
||||
static void
|
||||
gst_base_sink_loop (GstPad * pad)
|
||||
{
|
||||
|
@ -1061,7 +1025,7 @@ gst_base_sink_loop (GstPad * pad)
|
|||
if (result != GST_FLOW_OK)
|
||||
goto paused;
|
||||
|
||||
result = gst_base_sink_chain (pad, buf);
|
||||
result = gst_base_sink_handle_object (basesink, pad, GST_MINI_OBJECT (buf));
|
||||
if (result != GST_FLOW_OK)
|
||||
goto paused;
|
||||
|
||||
|
@ -1072,6 +1036,7 @@ gst_base_sink_loop (GstPad * pad)
|
|||
|
||||
paused:
|
||||
{
|
||||
gst_base_sink_event (pad, gst_event_new_eos ());
|
||||
gst_object_unref (basesink);
|
||||
gst_pad_pause_task (pad);
|
||||
return;
|
||||
|
@ -1111,23 +1076,62 @@ gst_base_sink_deactivate (GstBaseSink * basesink, GstPad * pad)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_base_sink_activate_push (GstPad * pad, gboolean active)
|
||||
gst_base_sink_activate (GstPad * pad)
|
||||
{
|
||||
gboolean result = FALSE;
|
||||
GstBaseSink *basesink;
|
||||
|
||||
basesink = GST_BASE_SINK (gst_pad_get_parent (pad));
|
||||
|
||||
if (active) {
|
||||
if (!basesink->has_chain)
|
||||
goto done;
|
||||
GST_DEBUG_OBJECT (basesink, "Trying pull mode first");
|
||||
|
||||
if (basesink->can_activate_pull && gst_pad_check_pull_range (pad)
|
||||
&& gst_pad_activate_pull (pad, TRUE)) {
|
||||
GST_DEBUG_OBJECT (basesink, "Success activating pull mode");
|
||||
result = TRUE;
|
||||
} else {
|
||||
result = gst_base_sink_deactivate (basesink, pad);
|
||||
GST_DEBUG_OBJECT (basesink, "Falling back to push mode");
|
||||
if (gst_pad_activate_push (pad, TRUE)) {
|
||||
GST_DEBUG_OBJECT (basesink, "Success activating push mode");
|
||||
result = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
GST_WARNING_OBJECT (basesink, "Could not activate pad in either mode");
|
||||
}
|
||||
|
||||
gst_object_unref (basesink);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_base_sink_activate_push (GstPad * pad, gboolean active)
|
||||
{
|
||||
gboolean result;
|
||||
GstBaseSink *basesink;
|
||||
|
||||
basesink = GST_BASE_SINK (gst_pad_get_parent (pad));
|
||||
|
||||
if (active) {
|
||||
if (!basesink->can_activate_push) {
|
||||
result = FALSE;
|
||||
basesink->pad_mode = GST_ACTIVATE_NONE;
|
||||
} else {
|
||||
result = TRUE;
|
||||
basesink->pad_mode = GST_ACTIVATE_PUSH;
|
||||
}
|
||||
} else {
|
||||
if (G_UNLIKELY (basesink->pad_mode != GST_ACTIVATE_PUSH)) {
|
||||
g_warning ("Internal GStreamer activation error!!!");
|
||||
result = FALSE;
|
||||
} else {
|
||||
result = gst_base_sink_deactivate (basesink, pad);
|
||||
basesink->pad_mode = GST_ACTIVATE_NONE;
|
||||
}
|
||||
}
|
||||
basesink->pad_mode = GST_ACTIVATE_PUSH;
|
||||
|
||||
done:
|
||||
gst_object_unref (basesink);
|
||||
|
||||
return result;
|
||||
|
@ -1143,15 +1147,42 @@ gst_base_sink_activate_pull (GstPad * pad, gboolean active)
|
|||
basesink = GST_BASE_SINK (gst_pad_get_parent (pad));
|
||||
|
||||
if (active) {
|
||||
/* if we have a scheduler we can start the task */
|
||||
if (!basesink->has_loop)
|
||||
goto done;
|
||||
result =
|
||||
gst_pad_start_task (pad, (GstTaskFunction) gst_base_sink_loop, pad);
|
||||
if (!basesink->can_activate_pull) {
|
||||
result = FALSE;
|
||||
basesink->pad_mode = GST_ACTIVATE_NONE;
|
||||
} else {
|
||||
GstPad *peer = gst_pad_get_peer (pad);
|
||||
|
||||
if (G_UNLIKELY (peer == NULL)) {
|
||||
g_warning ("Trying to activate pad in pull mode, but no peer");
|
||||
result = FALSE;
|
||||
} else {
|
||||
if (gst_pad_activate_pull (peer, TRUE)) {
|
||||
basesink->have_newsegment = TRUE;
|
||||
basesink->segment_start = basesink->segment_stop = 0;
|
||||
result =
|
||||
gst_pad_start_task (pad, (GstTaskFunction) gst_base_sink_loop,
|
||||
pad);
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (pad, "Failed to activate peer in pull mode");
|
||||
result = FALSE;
|
||||
}
|
||||
gst_object_unref (peer);
|
||||
}
|
||||
|
||||
basesink->pad_mode = result ? GST_ACTIVATE_PULL : GST_ACTIVATE_NONE;
|
||||
}
|
||||
} else {
|
||||
result = gst_base_sink_deactivate (basesink, pad);
|
||||
if (G_UNLIKELY (basesink->pad_mode != GST_ACTIVATE_PULL)) {
|
||||
g_warning ("Internal GStreamer activation error!!!");
|
||||
result = FALSE;
|
||||
} else {
|
||||
basesink->have_newsegment = FALSE;
|
||||
result = gst_base_sink_deactivate (basesink, pad);
|
||||
basesink->pad_mode = GST_ACTIVATE_NONE;
|
||||
}
|
||||
}
|
||||
done:
|
||||
|
||||
gst_object_unref (basesink);
|
||||
|
||||
return result;
|
||||
|
@ -1216,7 +1247,14 @@ gst_base_sink_change_state (GstElement * element)
|
|||
break;
|
||||
}
|
||||
|
||||
GST_ELEMENT_CLASS (parent_class)->change_state (element);
|
||||
{
|
||||
GstElementStateReturn bret;
|
||||
|
||||
bret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
|
||||
|
||||
if (bret != GST_STATE_SUCCESS)
|
||||
goto activate_failed;
|
||||
}
|
||||
|
||||
switch (transition) {
|
||||
case GST_STATE_PLAYING_TO_PAUSED:
|
||||
|
@ -1270,4 +1308,9 @@ start_failed:
|
|||
GST_DEBUG ("failed to start");
|
||||
return GST_STATE_FAILURE;
|
||||
}
|
||||
activate_failed:
|
||||
{
|
||||
GST_DEBUG ("element failed to change states -- activation problem?");
|
||||
return GST_STATE_FAILURE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,35 +56,37 @@ typedef struct _GstBaseSinkClass GstBaseSinkClass;
|
|||
struct _GstBaseSink {
|
||||
GstElement element;
|
||||
|
||||
/*< protected >*/
|
||||
GstPad *sinkpad;
|
||||
GstActivateMode pad_mode;
|
||||
|
||||
/*< protected >*/ /* with LOCK */
|
||||
guint64 offset;
|
||||
gboolean can_activate_pull;
|
||||
gboolean can_activate_push;
|
||||
|
||||
/*< protected >*/ /* with PREROLL_LOCK */
|
||||
GQueue *preroll_queue;
|
||||
gint preroll_queue_max_len;
|
||||
gint preroll_queued;
|
||||
gint buffers_queued;
|
||||
gint events_queued;
|
||||
gboolean eos;
|
||||
gboolean need_preroll;
|
||||
gboolean have_preroll;
|
||||
gboolean playing_async;
|
||||
|
||||
guint64 offset;
|
||||
gboolean has_loop;
|
||||
gboolean has_chain;
|
||||
|
||||
GstClock *clock;
|
||||
GstClockID clock_id;
|
||||
GstClockTime end_time;
|
||||
|
||||
/*< protected >*/ /* with STREAM_LOCK */
|
||||
gboolean have_newsegment;
|
||||
|
||||
gdouble segment_rate;
|
||||
gint64 segment_start;
|
||||
gint64 segment_stop;
|
||||
gint64 segment_base;
|
||||
|
||||
gboolean eos;
|
||||
gboolean need_preroll;
|
||||
gboolean have_preroll;
|
||||
gboolean playing_async;
|
||||
/*< private >*/ /* with LOCK */
|
||||
GstClock *clock;
|
||||
GstClockID clock_id;
|
||||
GstClockTime end_time;
|
||||
|
||||
/*< private >*/
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
|
|
|
@ -68,8 +68,6 @@ enum
|
|||
{
|
||||
PROP_0,
|
||||
PROP_BLOCKSIZE,
|
||||
PROP_HAS_LOOP,
|
||||
PROP_HAS_GETRANGE,
|
||||
PROP_NUM_BUFFERS,
|
||||
};
|
||||
|
||||
|
@ -129,7 +127,6 @@ static gboolean gst_base_src_stop (GstBaseSrc * basesrc);
|
|||
|
||||
static GstElementStateReturn gst_base_src_change_state (GstElement * element);
|
||||
|
||||
static void gst_base_src_set_dataflow_funcs (GstBaseSrc * this);
|
||||
static void gst_base_src_loop (GstPad * pad);
|
||||
static gboolean gst_base_src_check_get_range (GstPad * pad);
|
||||
static GstFlowReturn gst_base_src_get_range (GstPad * pad, guint64 offset,
|
||||
|
@ -161,16 +158,6 @@ gst_base_src_class_init (GstBaseSrcClass * klass)
|
|||
"Size in bytes to read per buffer", 1, G_MAXULONG, DEFAULT_BLOCKSIZE,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HAS_LOOP,
|
||||
g_param_spec_boolean ("has-loop", "Has loop function",
|
||||
"True if the element should expose a loop function", TRUE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HAS_GETRANGE,
|
||||
g_param_spec_boolean ("has-getrange", "Has getrange function",
|
||||
"True if the element should expose a getrange function", TRUE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_NUM_BUFFERS,
|
||||
g_param_spec_int ("num-buffers", "num-buffers",
|
||||
"Number of buffers to output before sending EOS", -1, G_MAXINT,
|
||||
|
@ -194,6 +181,9 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
|
|||
basesrc->num_buffers = DEFAULT_NUM_BUFFERS;
|
||||
basesrc->num_buffers_left = -1;
|
||||
|
||||
basesrc->can_activate_push = TRUE;
|
||||
basesrc->pad_mode = GST_ACTIVATE_NONE;
|
||||
|
||||
pad_template =
|
||||
gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src");
|
||||
g_return_if_fail (pad_template != NULL);
|
||||
|
@ -205,6 +195,7 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
|
|||
gst_pad_set_event_function (pad, gst_base_src_event_handler);
|
||||
gst_pad_set_query_function (pad, gst_base_src_query);
|
||||
gst_pad_set_checkgetrange_function (pad, gst_base_src_check_get_range);
|
||||
gst_pad_set_getrange_function (pad, gst_base_src_get_range);
|
||||
gst_pad_set_getcaps_function (pad, gst_base_src_getcaps);
|
||||
gst_pad_set_setcaps_function (pad, gst_base_src_setcaps);
|
||||
|
||||
|
@ -270,17 +261,6 @@ gst_base_src_is_live (GstBaseSrc * src)
|
|||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_base_src_set_dataflow_funcs (GstBaseSrc * this)
|
||||
{
|
||||
GST_DEBUG ("updating dataflow functions");
|
||||
|
||||
if (this->has_getrange)
|
||||
gst_pad_set_getrange_function (this->srcpad, gst_base_src_get_range);
|
||||
else
|
||||
gst_pad_set_getrange_function (this->srcpad, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_base_src_setcaps (GstPad * pad, GstCaps * caps)
|
||||
{
|
||||
|
@ -540,14 +520,6 @@ gst_base_src_set_property (GObject * object, guint prop_id,
|
|||
case PROP_BLOCKSIZE:
|
||||
src->blocksize = g_value_get_ulong (value);
|
||||
break;
|
||||
case PROP_HAS_LOOP:
|
||||
src->has_loop = g_value_get_boolean (value);
|
||||
gst_base_src_set_dataflow_funcs (src);
|
||||
break;
|
||||
case PROP_HAS_GETRANGE:
|
||||
src->has_getrange = g_value_get_boolean (value);
|
||||
gst_base_src_set_dataflow_funcs (src);
|
||||
break;
|
||||
case PROP_NUM_BUFFERS:
|
||||
src->num_buffers = g_value_get_int (value);
|
||||
break;
|
||||
|
@ -569,12 +541,6 @@ gst_base_src_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
case PROP_BLOCKSIZE:
|
||||
g_value_set_ulong (value, src->blocksize);
|
||||
break;
|
||||
case PROP_HAS_LOOP:
|
||||
g_value_set_boolean (value, src->has_loop);
|
||||
break;
|
||||
case PROP_HAS_GETRANGE:
|
||||
g_value_set_boolean (value, src->has_getrange);
|
||||
break;
|
||||
case PROP_NUM_BUFFERS:
|
||||
g_value_set_int (value, src->num_buffers);
|
||||
break;
|
||||
|
@ -1008,6 +974,10 @@ gst_base_src_activate_push (GstPad * pad, gboolean active)
|
|||
/* prepare subclass first */
|
||||
if (active) {
|
||||
GST_DEBUG_OBJECT (basesrc, "Activating in push mode");
|
||||
|
||||
if (!basesrc->can_activate_push)
|
||||
goto no_push_activation;
|
||||
|
||||
if (!gst_base_src_start (basesrc))
|
||||
goto error_start;
|
||||
|
||||
|
@ -1017,6 +987,11 @@ gst_base_src_activate_push (GstPad * pad, gboolean active)
|
|||
return gst_base_src_deactivate (basesrc, pad);
|
||||
}
|
||||
|
||||
no_push_activation:
|
||||
{
|
||||
GST_DEBUG_OBJECT (basesrc, "Subclass disabled push-mode activation");
|
||||
return FALSE;
|
||||
}
|
||||
error_start:
|
||||
{
|
||||
gst_base_src_stop (basesrc);
|
||||
|
|
|
@ -78,8 +78,8 @@ struct _GstBaseSrc {
|
|||
|
||||
/* MT-protected (with LOCK) */
|
||||
gint blocksize; /* size of buffers when operating push based */
|
||||
gboolean has_loop; /* some scheduling properties */
|
||||
gboolean has_getrange;
|
||||
gboolean can_activate_push; /* some scheduling properties */
|
||||
GstActivateMode pad_mode;
|
||||
gboolean seekable;
|
||||
gboolean random_access;
|
||||
|
||||
|
|
|
@ -64,16 +64,21 @@ enum
|
|||
#define DEFAULT_SYNC FALSE
|
||||
#define DEFAULT_SIGNAL_HANDOFFS FALSE
|
||||
#define DEFAULT_LAST_MESSAGE NULL
|
||||
#define DEFAULT_LAST_MESSAGE NULL
|
||||
#define DEFAULT_CAN_ACTIVATE_PUSH TRUE
|
||||
#define DEFAULT_CAN_ACTIVATE_PULL FALSE
|
||||
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_STATE_ERROR,
|
||||
ARG_SILENT,
|
||||
ARG_DUMP,
|
||||
ARG_SYNC,
|
||||
ARG_SIGNAL_HANDOFFS,
|
||||
ARG_LAST_MESSAGE,
|
||||
PROP_0,
|
||||
PROP_STATE_ERROR,
|
||||
PROP_SILENT,
|
||||
PROP_DUMP,
|
||||
PROP_SYNC,
|
||||
PROP_SIGNAL_HANDOFFS,
|
||||
PROP_LAST_MESSAGE,
|
||||
PROP_CAN_ACTIVATE_PUSH,
|
||||
PROP_CAN_ACTIVATE_PULL
|
||||
};
|
||||
|
||||
#define GST_TYPE_FAKE_SINK_STATE_ERROR (gst_fake_sink_state_error_get_type())
|
||||
|
@ -152,28 +157,38 @@ gst_fake_sink_class_init (GstFakeSinkClass * klass)
|
|||
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_fake_sink_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_fake_sink_get_property);
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_STATE_ERROR,
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_STATE_ERROR,
|
||||
g_param_spec_enum ("state_error", "State Error",
|
||||
"Generate a state change error", GST_TYPE_FAKE_SINK_STATE_ERROR,
|
||||
DEFAULT_STATE_ERROR, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_LAST_MESSAGE,
|
||||
g_param_spec_string ("last_message", "Last Message",
|
||||
"The message describing current status", DEFAULT_LAST_MESSAGE,
|
||||
G_PARAM_READABLE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SYNC,
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SYNC,
|
||||
g_param_spec_boolean ("sync", "Sync", "Sync on the clock", DEFAULT_SYNC,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIGNAL_HANDOFFS,
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SIGNAL_HANDOFFS,
|
||||
g_param_spec_boolean ("signal-handoffs", "Signal handoffs",
|
||||
"Send a signal before unreffing the buffer", DEFAULT_SIGNAL_HANDOFFS,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT,
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SILENT,
|
||||
g_param_spec_boolean ("silent", "Silent",
|
||||
"Don't produce last_message events", DEFAULT_SILENT,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUMP,
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DUMP,
|
||||
g_param_spec_boolean ("dump", "Dump", "Dump received bytes to stdout",
|
||||
DEFAULT_DUMP, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass),
|
||||
PROP_CAN_ACTIVATE_PUSH,
|
||||
g_param_spec_boolean ("can-activate-push", "Can activate push",
|
||||
"Can activate in push mode", DEFAULT_CAN_ACTIVATE_PUSH,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass),
|
||||
PROP_CAN_ACTIVATE_PULL,
|
||||
g_param_spec_boolean ("can-activate-pull", "Can activate pull",
|
||||
"Can activate in pull mode", DEFAULT_CAN_ACTIVATE_PULL,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
/**
|
||||
* GstFakeSink::handoff:
|
||||
|
@ -218,21 +233,27 @@ gst_fake_sink_set_property (GObject * object, guint prop_id,
|
|||
sink = GST_FAKE_SINK (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_SILENT:
|
||||
case PROP_SILENT:
|
||||
sink->silent = g_value_get_boolean (value);
|
||||
break;
|
||||
case ARG_STATE_ERROR:
|
||||
case PROP_STATE_ERROR:
|
||||
sink->state_error = g_value_get_enum (value);
|
||||
break;
|
||||
case ARG_DUMP:
|
||||
case PROP_DUMP:
|
||||
sink->dump = g_value_get_boolean (value);
|
||||
break;
|
||||
case ARG_SYNC:
|
||||
case PROP_SYNC:
|
||||
sink->sync = g_value_get_boolean (value);
|
||||
break;
|
||||
case ARG_SIGNAL_HANDOFFS:
|
||||
case PROP_SIGNAL_HANDOFFS:
|
||||
sink->signal_handoffs = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_CAN_ACTIVATE_PUSH:
|
||||
GST_BASE_SINK (sink)->can_activate_push = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_CAN_ACTIVATE_PULL:
|
||||
GST_BASE_SINK (sink)->can_activate_pull = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -248,24 +269,30 @@ gst_fake_sink_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
sink = GST_FAKE_SINK (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_STATE_ERROR:
|
||||
case PROP_STATE_ERROR:
|
||||
g_value_set_enum (value, sink->state_error);
|
||||
break;
|
||||
case ARG_SILENT:
|
||||
case PROP_SILENT:
|
||||
g_value_set_boolean (value, sink->silent);
|
||||
break;
|
||||
case ARG_DUMP:
|
||||
case PROP_DUMP:
|
||||
g_value_set_boolean (value, sink->dump);
|
||||
break;
|
||||
case ARG_SYNC:
|
||||
case PROP_SYNC:
|
||||
g_value_set_boolean (value, sink->sync);
|
||||
break;
|
||||
case ARG_SIGNAL_HANDOFFS:
|
||||
case PROP_SIGNAL_HANDOFFS:
|
||||
g_value_set_boolean (value, sink->signal_handoffs);
|
||||
break;
|
||||
case ARG_LAST_MESSAGE:
|
||||
case PROP_LAST_MESSAGE:
|
||||
g_value_set_string (value, sink->last_message);
|
||||
break;
|
||||
case PROP_CAN_ACTIVATE_PUSH:
|
||||
g_value_set_boolean (value, GST_BASE_SINK (sink)->can_activate_push);
|
||||
break;
|
||||
case PROP_CAN_ACTIVATE_PULL:
|
||||
g_value_set_boolean (value, GST_BASE_SINK (sink)->can_activate_pull);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
|
|
@ -74,6 +74,8 @@ enum
|
|||
#define DEFAULT_SILENT FALSE
|
||||
#define DEFAULT_DUMP FALSE
|
||||
#define DEFAULT_PARENTSIZE 4096*10
|
||||
#define DEFAULT_CAN_ACTIVATE_PULL TRUE
|
||||
#define DEFAULT_CAN_ACTIVATE_PUSH TRUE
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -93,8 +95,8 @@ enum
|
|||
PROP_DUMP,
|
||||
PROP_PARENTSIZE,
|
||||
PROP_LAST_MESSAGE,
|
||||
PROP_HAS_LOOP,
|
||||
PROP_HAS_GETRANGE,
|
||||
PROP_CAN_ACTIVATE_PULL,
|
||||
PROP_CAN_ACTIVATE_PUSH,
|
||||
PROP_IS_LIVE
|
||||
};
|
||||
|
||||
|
@ -196,6 +198,7 @@ static void gst_fake_src_get_property (GObject * object, guint prop_id,
|
|||
|
||||
static gboolean gst_fake_src_start (GstBaseSrc * basesrc);
|
||||
static gboolean gst_fake_src_stop (GstBaseSrc * basesrc);
|
||||
static gboolean gst_fake_src_is_seekable (GstBaseSrc * basesrc);
|
||||
|
||||
static gboolean gst_fake_src_event_handler (GstBaseSrc * src, GstEvent * event);
|
||||
static GstFlowReturn gst_fake_src_create (GstBaseSrc * src, guint64 offset,
|
||||
|
@ -280,13 +283,15 @@ gst_fake_src_class_init (GstFakeSrcClass * klass)
|
|||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DUMP,
|
||||
g_param_spec_boolean ("dump", "Dump", "Dump produced bytes to stdout",
|
||||
DEFAULT_DUMP, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HAS_LOOP,
|
||||
g_param_spec_boolean ("has-loop", "Has loop function",
|
||||
"True if the element exposes a loop function", TRUE,
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass),
|
||||
PROP_CAN_ACTIVATE_PUSH,
|
||||
g_param_spec_boolean ("can-activate-push", "Can activate push",
|
||||
"Can activate in push mode", DEFAULT_CAN_ACTIVATE_PUSH,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HAS_GETRANGE,
|
||||
g_param_spec_boolean ("has-getrange", "Has getrange function",
|
||||
"True if the element exposes a getrange function", TRUE,
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass),
|
||||
PROP_CAN_ACTIVATE_PULL,
|
||||
g_param_spec_boolean ("can-activate-pull", "Can activate pull",
|
||||
"Can activate in pull mode", DEFAULT_CAN_ACTIVATE_PULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_IS_LIVE,
|
||||
g_param_spec_boolean ("is-live", "Is this a live source",
|
||||
|
@ -307,7 +312,7 @@ gst_fake_src_class_init (GstFakeSrcClass * klass)
|
|||
gst_marshal_VOID__OBJECT_OBJECT, G_TYPE_NONE, 2, GST_TYPE_BUFFER,
|
||||
GST_TYPE_PAD);
|
||||
|
||||
/*gstbase_src_class->is_seekable = GST_DEBUG_FUNCPTR (gst_fake_src_is_seekable); */
|
||||
gstbase_src_class->is_seekable = GST_DEBUG_FUNCPTR (gst_fake_src_is_seekable);
|
||||
gstbase_src_class->start = GST_DEBUG_FUNCPTR (gst_fake_src_start);
|
||||
gstbase_src_class->stop = GST_DEBUG_FUNCPTR (gst_fake_src_stop);
|
||||
gstbase_src_class->event = GST_DEBUG_FUNCPTR (gst_fake_src_event_handler);
|
||||
|
@ -430,13 +435,13 @@ gst_fake_src_set_property (GObject * object, guint prop_id,
|
|||
case PROP_DUMP:
|
||||
src->dump = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_HAS_LOOP:
|
||||
case PROP_CAN_ACTIVATE_PUSH:
|
||||
g_return_if_fail (!GST_FLAG_IS_SET (object, GST_BASE_SRC_STARTED));
|
||||
src->has_loop = g_value_get_boolean (value);
|
||||
GST_BASE_SRC (src)->can_activate_push = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_HAS_GETRANGE:
|
||||
case PROP_CAN_ACTIVATE_PULL:
|
||||
g_return_if_fail (!GST_FLAG_IS_SET (object, GST_BASE_SRC_STARTED));
|
||||
src->has_getrange = g_value_get_boolean (value);
|
||||
src->can_activate_pull = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_IS_LIVE:
|
||||
gst_base_src_set_live (basesrc, g_value_get_boolean (value));
|
||||
|
@ -502,11 +507,11 @@ gst_fake_src_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
case PROP_LAST_MESSAGE:
|
||||
g_value_set_string (value, src->last_message);
|
||||
break;
|
||||
case PROP_HAS_LOOP:
|
||||
g_value_set_boolean (value, src->has_loop);
|
||||
case PROP_CAN_ACTIVATE_PUSH:
|
||||
g_value_set_boolean (value, GST_BASE_SRC (src)->can_activate_push);
|
||||
break;
|
||||
case PROP_HAS_GETRANGE:
|
||||
g_value_set_boolean (value, src->has_getrange);
|
||||
case PROP_CAN_ACTIVATE_PULL:
|
||||
g_value_set_boolean (value, src->can_activate_pull);
|
||||
break;
|
||||
case PROP_IS_LIVE:
|
||||
g_value_set_boolean (value, gst_base_src_is_live (basesrc));
|
||||
|
@ -744,3 +749,11 @@ gst_fake_src_stop (GstBaseSrc * basesrc)
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_fake_src_is_seekable (GstBaseSrc * basesrc)
|
||||
{
|
||||
GstFakeSrc *src = GST_FAKE_SRC (basesrc);
|
||||
|
||||
return src->can_activate_pull;
|
||||
}
|
||||
|
|
|
@ -105,6 +105,7 @@ struct _GstFakeSrc {
|
|||
gboolean silent;
|
||||
gboolean signal_handoffs;
|
||||
gboolean dump;
|
||||
gboolean can_activate_pull;
|
||||
|
||||
guint64 bytes_sent;
|
||||
|
||||
|
|
|
@ -54,16 +54,13 @@ enum
|
|||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
/* FIXME, need to figure out a better way to handle the pull mode */
|
||||
#define DEFAULT_SIZE 1024
|
||||
#define DEFAULT_HAS_LOOP FALSE
|
||||
#define DEFAULT_HAS_CHAIN TRUE
|
||||
#define DEFAULT_CAN_ACTIVATE_PULL FALSE /* fixme: enable me */
|
||||
#define DEFAULT_CAN_ACTIVATE_PUSH TRUE
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_HAS_LOOP,
|
||||
PROP_HAS_CHAIN,
|
||||
PROP_PREROLL_QUEUE_LEN
|
||||
};
|
||||
|
||||
|
@ -116,7 +113,7 @@ static GstElementStateReturn gst_base_sink_change_state (GstElement * element);
|
|||
|
||||
static GstFlowReturn gst_base_sink_chain (GstPad * pad, GstBuffer * buffer);
|
||||
static void gst_base_sink_loop (GstPad * pad);
|
||||
static GstFlowReturn gst_base_sink_chain (GstPad * pad, GstBuffer * buffer);
|
||||
static gboolean gst_base_sink_activate (GstPad * pad);
|
||||
static gboolean gst_base_sink_activate_push (GstPad * pad, gboolean active);
|
||||
static gboolean gst_base_sink_activate_pull (GstPad * pad, gboolean active);
|
||||
static gboolean gst_base_sink_event (GstPad * pad, GstEvent * event);
|
||||
|
@ -147,14 +144,6 @@ gst_base_sink_class_init (GstBaseSinkClass * klass)
|
|||
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_base_sink_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_base_sink_get_property);
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HAS_LOOP,
|
||||
g_param_spec_boolean ("has-loop", "has-loop",
|
||||
"Enable loop-based operation", DEFAULT_HAS_LOOP,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HAS_CHAIN,
|
||||
g_param_spec_boolean ("has-chain", "has-chain",
|
||||
"Enable chain-based operation", DEFAULT_HAS_CHAIN,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
/* FIXME, this next value should be configured using an event from the
|
||||
* upstream element */
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass),
|
||||
|
@ -255,12 +244,25 @@ gst_base_sink_init (GstBaseSink * basesink, gpointer g_class)
|
|||
GST_DEBUG_FUNCPTR (gst_base_sink_pad_setcaps));
|
||||
gst_pad_set_bufferalloc_function (basesink->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_sink_pad_buffer_alloc));
|
||||
gst_pad_set_activate_function (basesink->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_sink_activate));
|
||||
gst_pad_set_activatepush_function (basesink->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_sink_activate_push));
|
||||
gst_pad_set_activatepull_function (basesink->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_sink_activate_pull));
|
||||
gst_pad_set_event_function (basesink->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_sink_event));
|
||||
gst_pad_set_chain_function (basesink->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_sink_chain));
|
||||
gst_element_add_pad (GST_ELEMENT (basesink), basesink->sinkpad);
|
||||
|
||||
basesink->pad_mode = GST_ACTIVATE_NONE;
|
||||
GST_PAD_TASK (basesink->sinkpad) = NULL;
|
||||
basesink->preroll_queue = g_queue_new ();
|
||||
|
||||
basesink->can_activate_push = DEFAULT_CAN_ACTIVATE_PUSH;
|
||||
basesink->can_activate_pull = DEFAULT_CAN_ACTIVATE_PULL;
|
||||
|
||||
GST_FLAG_SET (basesink, GST_ELEMENT_IS_SINK);
|
||||
}
|
||||
|
||||
|
@ -276,30 +278,6 @@ gst_base_sink_finalize (GObject * object)
|
|||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_base_sink_set_pad_functions (GstBaseSink * this, GstPad * pad)
|
||||
{
|
||||
gst_pad_set_activatepush_function (pad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_sink_activate_push));
|
||||
gst_pad_set_activatepull_function (pad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_sink_activate_pull));
|
||||
gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_base_sink_event));
|
||||
|
||||
if (this->has_chain)
|
||||
gst_pad_set_chain_function (pad, GST_DEBUG_FUNCPTR (gst_base_sink_chain));
|
||||
else
|
||||
gst_pad_set_chain_function (pad, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_base_sink_set_all_pad_functions (GstBaseSink * this)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = GST_ELEMENT_PADS (this); l; l = l->next)
|
||||
gst_base_sink_set_pad_functions (this, (GstPad *) l->data);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_base_sink_set_clock (GstElement * element, GstClock * clock)
|
||||
{
|
||||
|
@ -314,23 +292,9 @@ static void
|
|||
gst_base_sink_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstBaseSink *sink;
|
||||
|
||||
sink = GST_BASE_SINK (object);
|
||||
GstBaseSink *sink = GST_BASE_SINK (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_HAS_LOOP:
|
||||
GST_LOCK (sink);
|
||||
sink->has_loop = g_value_get_boolean (value);
|
||||
gst_base_sink_set_all_pad_functions (sink);
|
||||
GST_UNLOCK (sink);
|
||||
break;
|
||||
case PROP_HAS_CHAIN:
|
||||
GST_LOCK (sink);
|
||||
sink->has_chain = g_value_get_boolean (value);
|
||||
gst_base_sink_set_all_pad_functions (sink);
|
||||
GST_UNLOCK (sink);
|
||||
break;
|
||||
case PROP_PREROLL_QUEUE_LEN:
|
||||
/* preroll lock necessary to serialize with finish_preroll */
|
||||
GST_PREROLL_LOCK (sink->sinkpad);
|
||||
|
@ -347,18 +311,10 @@ static void
|
|||
gst_base_sink_get_property (GObject * object, guint prop_id, GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstBaseSink *sink;
|
||||
|
||||
sink = GST_BASE_SINK (object);
|
||||
GstBaseSink *sink = GST_BASE_SINK (object);
|
||||
|
||||
GST_LOCK (sink);
|
||||
switch (prop_id) {
|
||||
case PROP_HAS_LOOP:
|
||||
g_value_set_boolean (value, sink->has_loop);
|
||||
break;
|
||||
case PROP_HAS_CHAIN:
|
||||
g_value_set_boolean (value, sink->has_chain);
|
||||
break;
|
||||
case PROP_PREROLL_QUEUE_LEN:
|
||||
g_value_set_uint (value, sink->preroll_queue_max_len);
|
||||
break;
|
||||
|
@ -1037,15 +993,23 @@ gst_base_sink_chain (GstPad * pad, GstBuffer * buf)
|
|||
|
||||
basesink = GST_BASE_SINK (gst_pad_get_parent (pad));
|
||||
|
||||
if (!(basesink->pad_mode == GST_ACTIVATE_PUSH)) {
|
||||
GST_LOCK (pad);
|
||||
g_warning ("Push on pad %s:%s, but it was not activated in push mode",
|
||||
GST_DEBUG_PAD_NAME (pad));
|
||||
GST_UNLOCK (pad);
|
||||
result = GST_FLOW_UNEXPECTED;
|
||||
goto done;
|
||||
}
|
||||
|
||||
result = gst_base_sink_handle_object (basesink, pad, GST_MINI_OBJECT (buf));
|
||||
|
||||
done:
|
||||
gst_object_unref (basesink);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* FIXME, not all sinks can operate in pull mode
|
||||
*/
|
||||
static void
|
||||
gst_base_sink_loop (GstPad * pad)
|
||||
{
|
||||
|
@ -1061,7 +1025,7 @@ gst_base_sink_loop (GstPad * pad)
|
|||
if (result != GST_FLOW_OK)
|
||||
goto paused;
|
||||
|
||||
result = gst_base_sink_chain (pad, buf);
|
||||
result = gst_base_sink_handle_object (basesink, pad, GST_MINI_OBJECT (buf));
|
||||
if (result != GST_FLOW_OK)
|
||||
goto paused;
|
||||
|
||||
|
@ -1072,6 +1036,7 @@ gst_base_sink_loop (GstPad * pad)
|
|||
|
||||
paused:
|
||||
{
|
||||
gst_base_sink_event (pad, gst_event_new_eos ());
|
||||
gst_object_unref (basesink);
|
||||
gst_pad_pause_task (pad);
|
||||
return;
|
||||
|
@ -1111,23 +1076,62 @@ gst_base_sink_deactivate (GstBaseSink * basesink, GstPad * pad)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_base_sink_activate_push (GstPad * pad, gboolean active)
|
||||
gst_base_sink_activate (GstPad * pad)
|
||||
{
|
||||
gboolean result = FALSE;
|
||||
GstBaseSink *basesink;
|
||||
|
||||
basesink = GST_BASE_SINK (gst_pad_get_parent (pad));
|
||||
|
||||
if (active) {
|
||||
if (!basesink->has_chain)
|
||||
goto done;
|
||||
GST_DEBUG_OBJECT (basesink, "Trying pull mode first");
|
||||
|
||||
if (basesink->can_activate_pull && gst_pad_check_pull_range (pad)
|
||||
&& gst_pad_activate_pull (pad, TRUE)) {
|
||||
GST_DEBUG_OBJECT (basesink, "Success activating pull mode");
|
||||
result = TRUE;
|
||||
} else {
|
||||
result = gst_base_sink_deactivate (basesink, pad);
|
||||
GST_DEBUG_OBJECT (basesink, "Falling back to push mode");
|
||||
if (gst_pad_activate_push (pad, TRUE)) {
|
||||
GST_DEBUG_OBJECT (basesink, "Success activating push mode");
|
||||
result = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
GST_WARNING_OBJECT (basesink, "Could not activate pad in either mode");
|
||||
}
|
||||
|
||||
gst_object_unref (basesink);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_base_sink_activate_push (GstPad * pad, gboolean active)
|
||||
{
|
||||
gboolean result;
|
||||
GstBaseSink *basesink;
|
||||
|
||||
basesink = GST_BASE_SINK (gst_pad_get_parent (pad));
|
||||
|
||||
if (active) {
|
||||
if (!basesink->can_activate_push) {
|
||||
result = FALSE;
|
||||
basesink->pad_mode = GST_ACTIVATE_NONE;
|
||||
} else {
|
||||
result = TRUE;
|
||||
basesink->pad_mode = GST_ACTIVATE_PUSH;
|
||||
}
|
||||
} else {
|
||||
if (G_UNLIKELY (basesink->pad_mode != GST_ACTIVATE_PUSH)) {
|
||||
g_warning ("Internal GStreamer activation error!!!");
|
||||
result = FALSE;
|
||||
} else {
|
||||
result = gst_base_sink_deactivate (basesink, pad);
|
||||
basesink->pad_mode = GST_ACTIVATE_NONE;
|
||||
}
|
||||
}
|
||||
basesink->pad_mode = GST_ACTIVATE_PUSH;
|
||||
|
||||
done:
|
||||
gst_object_unref (basesink);
|
||||
|
||||
return result;
|
||||
|
@ -1143,15 +1147,42 @@ gst_base_sink_activate_pull (GstPad * pad, gboolean active)
|
|||
basesink = GST_BASE_SINK (gst_pad_get_parent (pad));
|
||||
|
||||
if (active) {
|
||||
/* if we have a scheduler we can start the task */
|
||||
if (!basesink->has_loop)
|
||||
goto done;
|
||||
result =
|
||||
gst_pad_start_task (pad, (GstTaskFunction) gst_base_sink_loop, pad);
|
||||
if (!basesink->can_activate_pull) {
|
||||
result = FALSE;
|
||||
basesink->pad_mode = GST_ACTIVATE_NONE;
|
||||
} else {
|
||||
GstPad *peer = gst_pad_get_peer (pad);
|
||||
|
||||
if (G_UNLIKELY (peer == NULL)) {
|
||||
g_warning ("Trying to activate pad in pull mode, but no peer");
|
||||
result = FALSE;
|
||||
} else {
|
||||
if (gst_pad_activate_pull (peer, TRUE)) {
|
||||
basesink->have_newsegment = TRUE;
|
||||
basesink->segment_start = basesink->segment_stop = 0;
|
||||
result =
|
||||
gst_pad_start_task (pad, (GstTaskFunction) gst_base_sink_loop,
|
||||
pad);
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (pad, "Failed to activate peer in pull mode");
|
||||
result = FALSE;
|
||||
}
|
||||
gst_object_unref (peer);
|
||||
}
|
||||
|
||||
basesink->pad_mode = result ? GST_ACTIVATE_PULL : GST_ACTIVATE_NONE;
|
||||
}
|
||||
} else {
|
||||
result = gst_base_sink_deactivate (basesink, pad);
|
||||
if (G_UNLIKELY (basesink->pad_mode != GST_ACTIVATE_PULL)) {
|
||||
g_warning ("Internal GStreamer activation error!!!");
|
||||
result = FALSE;
|
||||
} else {
|
||||
basesink->have_newsegment = FALSE;
|
||||
result = gst_base_sink_deactivate (basesink, pad);
|
||||
basesink->pad_mode = GST_ACTIVATE_NONE;
|
||||
}
|
||||
}
|
||||
done:
|
||||
|
||||
gst_object_unref (basesink);
|
||||
|
||||
return result;
|
||||
|
@ -1216,7 +1247,14 @@ gst_base_sink_change_state (GstElement * element)
|
|||
break;
|
||||
}
|
||||
|
||||
GST_ELEMENT_CLASS (parent_class)->change_state (element);
|
||||
{
|
||||
GstElementStateReturn bret;
|
||||
|
||||
bret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
|
||||
|
||||
if (bret != GST_STATE_SUCCESS)
|
||||
goto activate_failed;
|
||||
}
|
||||
|
||||
switch (transition) {
|
||||
case GST_STATE_PLAYING_TO_PAUSED:
|
||||
|
@ -1270,4 +1308,9 @@ start_failed:
|
|||
GST_DEBUG ("failed to start");
|
||||
return GST_STATE_FAILURE;
|
||||
}
|
||||
activate_failed:
|
||||
{
|
||||
GST_DEBUG ("element failed to change states -- activation problem?");
|
||||
return GST_STATE_FAILURE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,35 +56,37 @@ typedef struct _GstBaseSinkClass GstBaseSinkClass;
|
|||
struct _GstBaseSink {
|
||||
GstElement element;
|
||||
|
||||
/*< protected >*/
|
||||
GstPad *sinkpad;
|
||||
GstActivateMode pad_mode;
|
||||
|
||||
/*< protected >*/ /* with LOCK */
|
||||
guint64 offset;
|
||||
gboolean can_activate_pull;
|
||||
gboolean can_activate_push;
|
||||
|
||||
/*< protected >*/ /* with PREROLL_LOCK */
|
||||
GQueue *preroll_queue;
|
||||
gint preroll_queue_max_len;
|
||||
gint preroll_queued;
|
||||
gint buffers_queued;
|
||||
gint events_queued;
|
||||
gboolean eos;
|
||||
gboolean need_preroll;
|
||||
gboolean have_preroll;
|
||||
gboolean playing_async;
|
||||
|
||||
guint64 offset;
|
||||
gboolean has_loop;
|
||||
gboolean has_chain;
|
||||
|
||||
GstClock *clock;
|
||||
GstClockID clock_id;
|
||||
GstClockTime end_time;
|
||||
|
||||
/*< protected >*/ /* with STREAM_LOCK */
|
||||
gboolean have_newsegment;
|
||||
|
||||
gdouble segment_rate;
|
||||
gint64 segment_start;
|
||||
gint64 segment_stop;
|
||||
gint64 segment_base;
|
||||
|
||||
gboolean eos;
|
||||
gboolean need_preroll;
|
||||
gboolean have_preroll;
|
||||
gboolean playing_async;
|
||||
/*< private >*/ /* with LOCK */
|
||||
GstClock *clock;
|
||||
GstClockID clock_id;
|
||||
GstClockTime end_time;
|
||||
|
||||
/*< private >*/
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
|
|
|
@ -68,8 +68,6 @@ enum
|
|||
{
|
||||
PROP_0,
|
||||
PROP_BLOCKSIZE,
|
||||
PROP_HAS_LOOP,
|
||||
PROP_HAS_GETRANGE,
|
||||
PROP_NUM_BUFFERS,
|
||||
};
|
||||
|
||||
|
@ -129,7 +127,6 @@ static gboolean gst_base_src_stop (GstBaseSrc * basesrc);
|
|||
|
||||
static GstElementStateReturn gst_base_src_change_state (GstElement * element);
|
||||
|
||||
static void gst_base_src_set_dataflow_funcs (GstBaseSrc * this);
|
||||
static void gst_base_src_loop (GstPad * pad);
|
||||
static gboolean gst_base_src_check_get_range (GstPad * pad);
|
||||
static GstFlowReturn gst_base_src_get_range (GstPad * pad, guint64 offset,
|
||||
|
@ -161,16 +158,6 @@ gst_base_src_class_init (GstBaseSrcClass * klass)
|
|||
"Size in bytes to read per buffer", 1, G_MAXULONG, DEFAULT_BLOCKSIZE,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HAS_LOOP,
|
||||
g_param_spec_boolean ("has-loop", "Has loop function",
|
||||
"True if the element should expose a loop function", TRUE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HAS_GETRANGE,
|
||||
g_param_spec_boolean ("has-getrange", "Has getrange function",
|
||||
"True if the element should expose a getrange function", TRUE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_NUM_BUFFERS,
|
||||
g_param_spec_int ("num-buffers", "num-buffers",
|
||||
"Number of buffers to output before sending EOS", -1, G_MAXINT,
|
||||
|
@ -194,6 +181,9 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
|
|||
basesrc->num_buffers = DEFAULT_NUM_BUFFERS;
|
||||
basesrc->num_buffers_left = -1;
|
||||
|
||||
basesrc->can_activate_push = TRUE;
|
||||
basesrc->pad_mode = GST_ACTIVATE_NONE;
|
||||
|
||||
pad_template =
|
||||
gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src");
|
||||
g_return_if_fail (pad_template != NULL);
|
||||
|
@ -205,6 +195,7 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
|
|||
gst_pad_set_event_function (pad, gst_base_src_event_handler);
|
||||
gst_pad_set_query_function (pad, gst_base_src_query);
|
||||
gst_pad_set_checkgetrange_function (pad, gst_base_src_check_get_range);
|
||||
gst_pad_set_getrange_function (pad, gst_base_src_get_range);
|
||||
gst_pad_set_getcaps_function (pad, gst_base_src_getcaps);
|
||||
gst_pad_set_setcaps_function (pad, gst_base_src_setcaps);
|
||||
|
||||
|
@ -270,17 +261,6 @@ gst_base_src_is_live (GstBaseSrc * src)
|
|||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_base_src_set_dataflow_funcs (GstBaseSrc * this)
|
||||
{
|
||||
GST_DEBUG ("updating dataflow functions");
|
||||
|
||||
if (this->has_getrange)
|
||||
gst_pad_set_getrange_function (this->srcpad, gst_base_src_get_range);
|
||||
else
|
||||
gst_pad_set_getrange_function (this->srcpad, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_base_src_setcaps (GstPad * pad, GstCaps * caps)
|
||||
{
|
||||
|
@ -540,14 +520,6 @@ gst_base_src_set_property (GObject * object, guint prop_id,
|
|||
case PROP_BLOCKSIZE:
|
||||
src->blocksize = g_value_get_ulong (value);
|
||||
break;
|
||||
case PROP_HAS_LOOP:
|
||||
src->has_loop = g_value_get_boolean (value);
|
||||
gst_base_src_set_dataflow_funcs (src);
|
||||
break;
|
||||
case PROP_HAS_GETRANGE:
|
||||
src->has_getrange = g_value_get_boolean (value);
|
||||
gst_base_src_set_dataflow_funcs (src);
|
||||
break;
|
||||
case PROP_NUM_BUFFERS:
|
||||
src->num_buffers = g_value_get_int (value);
|
||||
break;
|
||||
|
@ -569,12 +541,6 @@ gst_base_src_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
case PROP_BLOCKSIZE:
|
||||
g_value_set_ulong (value, src->blocksize);
|
||||
break;
|
||||
case PROP_HAS_LOOP:
|
||||
g_value_set_boolean (value, src->has_loop);
|
||||
break;
|
||||
case PROP_HAS_GETRANGE:
|
||||
g_value_set_boolean (value, src->has_getrange);
|
||||
break;
|
||||
case PROP_NUM_BUFFERS:
|
||||
g_value_set_int (value, src->num_buffers);
|
||||
break;
|
||||
|
@ -1008,6 +974,10 @@ gst_base_src_activate_push (GstPad * pad, gboolean active)
|
|||
/* prepare subclass first */
|
||||
if (active) {
|
||||
GST_DEBUG_OBJECT (basesrc, "Activating in push mode");
|
||||
|
||||
if (!basesrc->can_activate_push)
|
||||
goto no_push_activation;
|
||||
|
||||
if (!gst_base_src_start (basesrc))
|
||||
goto error_start;
|
||||
|
||||
|
@ -1017,6 +987,11 @@ gst_base_src_activate_push (GstPad * pad, gboolean active)
|
|||
return gst_base_src_deactivate (basesrc, pad);
|
||||
}
|
||||
|
||||
no_push_activation:
|
||||
{
|
||||
GST_DEBUG_OBJECT (basesrc, "Subclass disabled push-mode activation");
|
||||
return FALSE;
|
||||
}
|
||||
error_start:
|
||||
{
|
||||
gst_base_src_stop (basesrc);
|
||||
|
|
|
@ -78,8 +78,8 @@ struct _GstBaseSrc {
|
|||
|
||||
/* MT-protected (with LOCK) */
|
||||
gint blocksize; /* size of buffers when operating push based */
|
||||
gboolean has_loop; /* some scheduling properties */
|
||||
gboolean has_getrange;
|
||||
gboolean can_activate_push; /* some scheduling properties */
|
||||
GstActivateMode pad_mode;
|
||||
gboolean seekable;
|
||||
gboolean random_access;
|
||||
|
||||
|
|
|
@ -64,16 +64,21 @@ enum
|
|||
#define DEFAULT_SYNC FALSE
|
||||
#define DEFAULT_SIGNAL_HANDOFFS FALSE
|
||||
#define DEFAULT_LAST_MESSAGE NULL
|
||||
#define DEFAULT_LAST_MESSAGE NULL
|
||||
#define DEFAULT_CAN_ACTIVATE_PUSH TRUE
|
||||
#define DEFAULT_CAN_ACTIVATE_PULL FALSE
|
||||
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_STATE_ERROR,
|
||||
ARG_SILENT,
|
||||
ARG_DUMP,
|
||||
ARG_SYNC,
|
||||
ARG_SIGNAL_HANDOFFS,
|
||||
ARG_LAST_MESSAGE,
|
||||
PROP_0,
|
||||
PROP_STATE_ERROR,
|
||||
PROP_SILENT,
|
||||
PROP_DUMP,
|
||||
PROP_SYNC,
|
||||
PROP_SIGNAL_HANDOFFS,
|
||||
PROP_LAST_MESSAGE,
|
||||
PROP_CAN_ACTIVATE_PUSH,
|
||||
PROP_CAN_ACTIVATE_PULL
|
||||
};
|
||||
|
||||
#define GST_TYPE_FAKE_SINK_STATE_ERROR (gst_fake_sink_state_error_get_type())
|
||||
|
@ -152,28 +157,38 @@ gst_fake_sink_class_init (GstFakeSinkClass * klass)
|
|||
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_fake_sink_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_fake_sink_get_property);
|
||||
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_STATE_ERROR,
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_STATE_ERROR,
|
||||
g_param_spec_enum ("state_error", "State Error",
|
||||
"Generate a state change error", GST_TYPE_FAKE_SINK_STATE_ERROR,
|
||||
DEFAULT_STATE_ERROR, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_LAST_MESSAGE,
|
||||
g_param_spec_string ("last_message", "Last Message",
|
||||
"The message describing current status", DEFAULT_LAST_MESSAGE,
|
||||
G_PARAM_READABLE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SYNC,
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SYNC,
|
||||
g_param_spec_boolean ("sync", "Sync", "Sync on the clock", DEFAULT_SYNC,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIGNAL_HANDOFFS,
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SIGNAL_HANDOFFS,
|
||||
g_param_spec_boolean ("signal-handoffs", "Signal handoffs",
|
||||
"Send a signal before unreffing the buffer", DEFAULT_SIGNAL_HANDOFFS,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT,
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SILENT,
|
||||
g_param_spec_boolean ("silent", "Silent",
|
||||
"Don't produce last_message events", DEFAULT_SILENT,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUMP,
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DUMP,
|
||||
g_param_spec_boolean ("dump", "Dump", "Dump received bytes to stdout",
|
||||
DEFAULT_DUMP, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass),
|
||||
PROP_CAN_ACTIVATE_PUSH,
|
||||
g_param_spec_boolean ("can-activate-push", "Can activate push",
|
||||
"Can activate in push mode", DEFAULT_CAN_ACTIVATE_PUSH,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass),
|
||||
PROP_CAN_ACTIVATE_PULL,
|
||||
g_param_spec_boolean ("can-activate-pull", "Can activate pull",
|
||||
"Can activate in pull mode", DEFAULT_CAN_ACTIVATE_PULL,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
/**
|
||||
* GstFakeSink::handoff:
|
||||
|
@ -218,21 +233,27 @@ gst_fake_sink_set_property (GObject * object, guint prop_id,
|
|||
sink = GST_FAKE_SINK (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_SILENT:
|
||||
case PROP_SILENT:
|
||||
sink->silent = g_value_get_boolean (value);
|
||||
break;
|
||||
case ARG_STATE_ERROR:
|
||||
case PROP_STATE_ERROR:
|
||||
sink->state_error = g_value_get_enum (value);
|
||||
break;
|
||||
case ARG_DUMP:
|
||||
case PROP_DUMP:
|
||||
sink->dump = g_value_get_boolean (value);
|
||||
break;
|
||||
case ARG_SYNC:
|
||||
case PROP_SYNC:
|
||||
sink->sync = g_value_get_boolean (value);
|
||||
break;
|
||||
case ARG_SIGNAL_HANDOFFS:
|
||||
case PROP_SIGNAL_HANDOFFS:
|
||||
sink->signal_handoffs = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_CAN_ACTIVATE_PUSH:
|
||||
GST_BASE_SINK (sink)->can_activate_push = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_CAN_ACTIVATE_PULL:
|
||||
GST_BASE_SINK (sink)->can_activate_pull = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -248,24 +269,30 @@ gst_fake_sink_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
sink = GST_FAKE_SINK (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_STATE_ERROR:
|
||||
case PROP_STATE_ERROR:
|
||||
g_value_set_enum (value, sink->state_error);
|
||||
break;
|
||||
case ARG_SILENT:
|
||||
case PROP_SILENT:
|
||||
g_value_set_boolean (value, sink->silent);
|
||||
break;
|
||||
case ARG_DUMP:
|
||||
case PROP_DUMP:
|
||||
g_value_set_boolean (value, sink->dump);
|
||||
break;
|
||||
case ARG_SYNC:
|
||||
case PROP_SYNC:
|
||||
g_value_set_boolean (value, sink->sync);
|
||||
break;
|
||||
case ARG_SIGNAL_HANDOFFS:
|
||||
case PROP_SIGNAL_HANDOFFS:
|
||||
g_value_set_boolean (value, sink->signal_handoffs);
|
||||
break;
|
||||
case ARG_LAST_MESSAGE:
|
||||
case PROP_LAST_MESSAGE:
|
||||
g_value_set_string (value, sink->last_message);
|
||||
break;
|
||||
case PROP_CAN_ACTIVATE_PUSH:
|
||||
g_value_set_boolean (value, GST_BASE_SINK (sink)->can_activate_push);
|
||||
break;
|
||||
case PROP_CAN_ACTIVATE_PULL:
|
||||
g_value_set_boolean (value, GST_BASE_SINK (sink)->can_activate_pull);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
|
|
@ -74,6 +74,8 @@ enum
|
|||
#define DEFAULT_SILENT FALSE
|
||||
#define DEFAULT_DUMP FALSE
|
||||
#define DEFAULT_PARENTSIZE 4096*10
|
||||
#define DEFAULT_CAN_ACTIVATE_PULL TRUE
|
||||
#define DEFAULT_CAN_ACTIVATE_PUSH TRUE
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -93,8 +95,8 @@ enum
|
|||
PROP_DUMP,
|
||||
PROP_PARENTSIZE,
|
||||
PROP_LAST_MESSAGE,
|
||||
PROP_HAS_LOOP,
|
||||
PROP_HAS_GETRANGE,
|
||||
PROP_CAN_ACTIVATE_PULL,
|
||||
PROP_CAN_ACTIVATE_PUSH,
|
||||
PROP_IS_LIVE
|
||||
};
|
||||
|
||||
|
@ -196,6 +198,7 @@ static void gst_fake_src_get_property (GObject * object, guint prop_id,
|
|||
|
||||
static gboolean gst_fake_src_start (GstBaseSrc * basesrc);
|
||||
static gboolean gst_fake_src_stop (GstBaseSrc * basesrc);
|
||||
static gboolean gst_fake_src_is_seekable (GstBaseSrc * basesrc);
|
||||
|
||||
static gboolean gst_fake_src_event_handler (GstBaseSrc * src, GstEvent * event);
|
||||
static GstFlowReturn gst_fake_src_create (GstBaseSrc * src, guint64 offset,
|
||||
|
@ -280,13 +283,15 @@ gst_fake_src_class_init (GstFakeSrcClass * klass)
|
|||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DUMP,
|
||||
g_param_spec_boolean ("dump", "Dump", "Dump produced bytes to stdout",
|
||||
DEFAULT_DUMP, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HAS_LOOP,
|
||||
g_param_spec_boolean ("has-loop", "Has loop function",
|
||||
"True if the element exposes a loop function", TRUE,
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass),
|
||||
PROP_CAN_ACTIVATE_PUSH,
|
||||
g_param_spec_boolean ("can-activate-push", "Can activate push",
|
||||
"Can activate in push mode", DEFAULT_CAN_ACTIVATE_PUSH,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HAS_GETRANGE,
|
||||
g_param_spec_boolean ("has-getrange", "Has getrange function",
|
||||
"True if the element exposes a getrange function", TRUE,
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass),
|
||||
PROP_CAN_ACTIVATE_PULL,
|
||||
g_param_spec_boolean ("can-activate-pull", "Can activate pull",
|
||||
"Can activate in pull mode", DEFAULT_CAN_ACTIVATE_PULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_IS_LIVE,
|
||||
g_param_spec_boolean ("is-live", "Is this a live source",
|
||||
|
@ -307,7 +312,7 @@ gst_fake_src_class_init (GstFakeSrcClass * klass)
|
|||
gst_marshal_VOID__OBJECT_OBJECT, G_TYPE_NONE, 2, GST_TYPE_BUFFER,
|
||||
GST_TYPE_PAD);
|
||||
|
||||
/*gstbase_src_class->is_seekable = GST_DEBUG_FUNCPTR (gst_fake_src_is_seekable); */
|
||||
gstbase_src_class->is_seekable = GST_DEBUG_FUNCPTR (gst_fake_src_is_seekable);
|
||||
gstbase_src_class->start = GST_DEBUG_FUNCPTR (gst_fake_src_start);
|
||||
gstbase_src_class->stop = GST_DEBUG_FUNCPTR (gst_fake_src_stop);
|
||||
gstbase_src_class->event = GST_DEBUG_FUNCPTR (gst_fake_src_event_handler);
|
||||
|
@ -430,13 +435,13 @@ gst_fake_src_set_property (GObject * object, guint prop_id,
|
|||
case PROP_DUMP:
|
||||
src->dump = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_HAS_LOOP:
|
||||
case PROP_CAN_ACTIVATE_PUSH:
|
||||
g_return_if_fail (!GST_FLAG_IS_SET (object, GST_BASE_SRC_STARTED));
|
||||
src->has_loop = g_value_get_boolean (value);
|
||||
GST_BASE_SRC (src)->can_activate_push = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_HAS_GETRANGE:
|
||||
case PROP_CAN_ACTIVATE_PULL:
|
||||
g_return_if_fail (!GST_FLAG_IS_SET (object, GST_BASE_SRC_STARTED));
|
||||
src->has_getrange = g_value_get_boolean (value);
|
||||
src->can_activate_pull = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_IS_LIVE:
|
||||
gst_base_src_set_live (basesrc, g_value_get_boolean (value));
|
||||
|
@ -502,11 +507,11 @@ gst_fake_src_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
case PROP_LAST_MESSAGE:
|
||||
g_value_set_string (value, src->last_message);
|
||||
break;
|
||||
case PROP_HAS_LOOP:
|
||||
g_value_set_boolean (value, src->has_loop);
|
||||
case PROP_CAN_ACTIVATE_PUSH:
|
||||
g_value_set_boolean (value, GST_BASE_SRC (src)->can_activate_push);
|
||||
break;
|
||||
case PROP_HAS_GETRANGE:
|
||||
g_value_set_boolean (value, src->has_getrange);
|
||||
case PROP_CAN_ACTIVATE_PULL:
|
||||
g_value_set_boolean (value, src->can_activate_pull);
|
||||
break;
|
||||
case PROP_IS_LIVE:
|
||||
g_value_set_boolean (value, gst_base_src_is_live (basesrc));
|
||||
|
@ -744,3 +749,11 @@ gst_fake_src_stop (GstBaseSrc * basesrc)
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_fake_src_is_seekable (GstBaseSrc * basesrc)
|
||||
{
|
||||
GstFakeSrc *src = GST_FAKE_SRC (basesrc);
|
||||
|
||||
return src->can_activate_pull;
|
||||
}
|
||||
|
|
|
@ -105,6 +105,7 @@ struct _GstFakeSrc {
|
|||
gboolean silent;
|
||||
gboolean signal_handoffs;
|
||||
gboolean dump;
|
||||
gboolean can_activate_pull;
|
||||
|
||||
guint64 bytes_sent;
|
||||
|
||||
|
|
|
@ -45,7 +45,10 @@ run_pipeline (GstElement * pipe, gchar * descr,
|
|||
|
||||
bus = gst_element_get_bus (pipe);
|
||||
g_assert (bus);
|
||||
gst_element_set_state (pipe, GST_STATE_PLAYING);
|
||||
if (gst_element_set_state (pipe, GST_STATE_PLAYING) != GST_STATE_SUCCESS) {
|
||||
g_critical ("Couldn't set pipeline to PLAYING");
|
||||
goto done;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
revent = gst_bus_poll (bus, GST_MESSAGE_ANY, GST_SECOND / 2);
|
||||
|
@ -67,6 +70,7 @@ run_pipeline (GstElement * pipe, gchar * descr,
|
|||
revent, tevent, descr);
|
||||
}
|
||||
|
||||
done:
|
||||
gst_element_set_state (pipe, GST_STATE_NULL);
|
||||
gst_object_unref (pipe);
|
||||
}
|
||||
|
@ -75,29 +79,25 @@ GST_START_TEST (test_2_elements)
|
|||
{
|
||||
gchar *s;
|
||||
|
||||
/* has-loop got unimplemented at some point, so these aren't actually testing
|
||||
* what they're supposed to -- a big ol' FIXME */
|
||||
|
||||
s = "fakesrc has-loop=false ! fakesink has-loop=true";
|
||||
s = "fakesrc can-activate-push=false ! fakesink can-activate-pull=true";
|
||||
run_pipeline (setup_pipeline (s), s,
|
||||
GST_MESSAGE_STATE_CHANGED, GST_MESSAGE_UNKNOWN);
|
||||
|
||||
s = "fakesrc has-loop=true ! fakesink has-loop=false";
|
||||
s = "fakesrc can-activate-push=true ! fakesink can-activate-pull=false";
|
||||
run_pipeline (setup_pipeline (s), s,
|
||||
GST_MESSAGE_STATE_CHANGED, GST_MESSAGE_UNKNOWN);
|
||||
|
||||
s = "fakesrc has-loop=false num-buffers=10 ! fakesink has-loop=true";
|
||||
s = "fakesrc can-activate-push=false num-buffers=10 ! fakesink can-activate-pull=true";
|
||||
run_pipeline (setup_pipeline (s), s,
|
||||
GST_MESSAGE_STATE_CHANGED, GST_MESSAGE_EOS);
|
||||
|
||||
s = "fakesrc has-loop=true num-buffers=10 ! fakesink has-loop=false";
|
||||
s = "fakesrc can-activate-push=true num-buffers=10 ! fakesink can-activate-pull=false";
|
||||
run_pipeline (setup_pipeline (s), s,
|
||||
GST_MESSAGE_STATE_CHANGED, GST_MESSAGE_EOS);
|
||||
|
||||
/* Should raise a critical, but doesn't with has-loop not working
|
||||
s = "fakesrc has-loop=false ! fakesink has-loop=false";
|
||||
ASSERT_CRITICAL (run_pipeline (setup_pipeline (s), s,
|
||||
GST_MESSAGE_STATE_CHANGED, GST_MESSAGE_UNKNOWN)); */
|
||||
s = "fakesrc can-activate-push=false ! fakesink can-activate-pull=false";
|
||||
ASSERT_CRITICAL (run_pipeline (setup_pipeline (s), s,
|
||||
GST_MESSAGE_STATE_CHANGED, GST_MESSAGE_UNKNOWN));
|
||||
}
|
||||
GST_END_TEST static void
|
||||
got_handoff (GstElement * sink, GstBuffer * buf, GstPad * pad, gpointer unused)
|
||||
|
|
Loading…
Reference in a new issue