gst/base/: Make basesrc negotiate.

Original commit message from CVS:
* gst/base/README:
* gst/base/gstbasesink.c: (gst_base_sink_preroll_queue_empty),
(gst_base_sink_handle_object), (gst_base_sink_loop),
(gst_base_sink_change_state):
* gst/base/gstbasesink.h:
* gst/base/gstbasesrc.c: (gst_base_src_class_init),
(gst_base_src_init), (gst_base_src_setcaps),
(gst_base_src_getcaps), (gst_base_src_loop),
(gst_base_src_default_negotiate), (gst_base_src_negotiate),
(gst_base_src_start), (gst_base_src_change_state):
* gst/base/gstbasesrc.h:
Make basesrc negotiate.
Handle the case where preroll fails in basesink.
Update README.
This commit is contained in:
Wim Taymans 2005-07-06 13:25:26 +00:00
parent 7ce828ba3a
commit 03aa950f7d
11 changed files with 445 additions and 24 deletions

View file

@ -1,3 +1,20 @@
2005-07-06 Wim Taymans <wim@fluendo.com>
* gst/base/README:
* gst/base/gstbasesink.c: (gst_base_sink_preroll_queue_empty),
(gst_base_sink_handle_object), (gst_base_sink_loop),
(gst_base_sink_change_state):
* gst/base/gstbasesink.h:
* gst/base/gstbasesrc.c: (gst_base_src_class_init),
(gst_base_src_init), (gst_base_src_setcaps),
(gst_base_src_getcaps), (gst_base_src_loop),
(gst_base_src_default_negotiate), (gst_base_src_negotiate),
(gst_base_src_start), (gst_base_src_change_state):
* gst/base/gstbasesrc.h:
Make basesrc negotiate.
Handle the case where preroll fails in basesink.
Update README.
2005-07-06 Wim Taymans <wim@fluendo.com>
* gst/gstpad.c: (gst_pad_fixate_caps), (gst_pad_accept_caps):

View file

@ -20,7 +20,9 @@ GstBaseTransform
Base class for simple tranform filters
- one sinkpad and one srcpad
- formats the same on sink and source pad.
- possible formats on sink and source pad implemented
with custom transform_caps function. By default uses
same format on sink and source.
- handles state changes
- does flushing
- push mode
@ -34,3 +36,7 @@ GstBaseSrc
- handles state changes
- pull/push mode
- handles seeking/query
GstPushSrc
Base class for push based source elements

View file

@ -447,7 +447,6 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
{
gint length;
gboolean have_event;
guint t;
GST_PREROLL_LOCK (pad);
/* push object on the queue */
@ -484,16 +483,21 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
/* if it's a buffer, we need to call the preroll method */
if (GST_IS_BUFFER (obj)) {
GstBaseSinkClass *bclass;
GstFlowReturn pres;
bclass = GST_BASESINK_GET_CLASS (basesink);
if (bclass->preroll)
bclass->preroll (basesink, GST_BUFFER (obj));
if ((pres =
bclass->preroll (basesink, GST_BUFFER (obj))) != GST_FLOW_OK)
goto preroll_failed;
}
}
length = basesink->preroll_queued;
GST_DEBUG ("prerolled length %d", length);
if (length == 1) {
guint t;
basesink->have_preroll = TRUE;
/* we are prerolling */
GST_PREROLL_UNLOCK (pad);
@ -575,6 +579,36 @@ flushing:
GST_DEBUG ("pad is flushing");
return GST_FLOW_WRONG_STATE;
}
preroll_failed:
{
guint t;
GST_DEBUG ("preroll failed");
basesink->have_preroll = FALSE;
gst_base_sink_preroll_queue_flush (basesink, pad);
GST_PREROLL_UNLOCK (pad);
/* have to release STREAM_LOCK as we cannot take the STATE_LOCK
* inside the STREAM_LOCK */
t = GST_STREAM_UNLOCK_FULL (pad);
GST_DEBUG ("released stream lock %d times", t);
if (t == 0) {
GST_WARNING ("STREAM_LOCK should have been locked !!");
g_warning ("STREAM_LOCK should have been locked !!");
}
/* now we abort our state */
GST_STATE_LOCK (basesink);
GST_DEBUG ("abort state %p >", basesink);
gst_element_abort_state (GST_ELEMENT (basesink));
GST_STATE_UNLOCK (basesink);
/* reacquire stream lock, pad could be flushing now */
if (t > 0)
GST_STREAM_LOCK_FULL (pad, t);
return GST_FLOW_ERROR;
}
}
static gboolean
@ -859,8 +893,10 @@ gst_base_sink_loop (GstPad * pad)
return;
paused:
gst_pad_pause_task (pad);
return;
{
gst_pad_pause_task (pad);
return;
}
}
static gboolean
@ -940,9 +976,15 @@ gst_base_sink_change_state (GstElement * element)
GstElementStateReturn ret = GST_STATE_SUCCESS;
GstBaseSink *basesink = GST_BASESINK (element);
GstElementState transition = GST_STATE_TRANSITION (element);
GstBaseSinkClass *bclass;
bclass = GST_BASESINK_GET_CLASS (basesink);
switch (transition) {
case GST_STATE_NULL_TO_READY:
if (bclass->start)
if (!bclass->start (basesink))
goto start_failed;
break;
case GST_STATE_READY_TO_PAUSED:
/* need to complete preroll before this state change completes, there
@ -1013,10 +1055,21 @@ gst_base_sink_change_state (GstElement * element)
case GST_STATE_PAUSED_TO_READY:
break;
case GST_STATE_READY_TO_NULL:
if (bclass->stop)
if (!bclass->stop (basesink)) {
GST_WARNING ("failed to stop");
}
break;
default:
break;
}
return ret;
/* ERRORS */
start_failed:
{
GST_DEBUG ("failed to start");
return GST_STATE_FAILURE;
}
}

View file

@ -87,6 +87,10 @@ struct _GstBaseSinkClass {
void (*get_times) (GstBaseSink *sink, GstBuffer *buffer,
GstClockTime *start, GstClockTime *end);
/* start and stop processing, ideal for opening/closing the resource */
gboolean (*start) (GstBaseSink *sink);
gboolean (*stop) (GstBaseSink *sink);
/* unlock any pending access to the resource. subclasses should unlock
* any function ASAP. */
gboolean (*unlock) (GstBaseSink *sink);

View file

@ -81,6 +81,8 @@ gst_base_src_get_type (void)
}
return base_src_type;
}
static GstCaps *gst_base_src_getcaps (GstPad * pad);
static gboolean gst_base_src_setcaps (GstPad * pad, GstCaps * caps);
static gboolean gst_base_src_activate_push (GstPad * pad, gboolean active);
static gboolean gst_base_src_activate_pull (GstPad * pad, gboolean active);
@ -95,6 +97,7 @@ static gboolean gst_base_src_query (GstPad * pad, GstQuery * query);
#if 0
static const GstEventMask *gst_base_src_get_event_mask (GstPad * pad);
#endif
static gboolean gst_base_src_default_negotiate (GstBaseSrc * basesrc);
static gboolean gst_base_src_unlock (GstBaseSrc * basesrc);
static gboolean gst_base_src_get_size (GstBaseSrc * basesrc, guint64 * size);
@ -146,6 +149,8 @@ gst_base_src_class_init (GstBaseSrcClass * klass)
gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_base_src_change_state);
klass->negotiate = gst_base_src_default_negotiate;
}
static void
@ -154,6 +159,10 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
GstPad *pad;
GstPadTemplate *pad_template;
basesrc->is_live = FALSE;
basesrc->live_lock = g_mutex_new ();
basesrc->live_cond = g_cond_new ();
pad_template =
gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src");
g_return_if_fail (pad_template != NULL);
@ -164,12 +173,9 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
gst_pad_set_activatepull_function (pad, gst_base_src_activate_pull);
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);
basesrc->is_live = FALSE;
basesrc->live_lock = g_mutex_new ();
basesrc->live_cond = g_cond_new ();
gst_pad_set_getcaps_function (pad, gst_base_src_getcaps);
gst_pad_set_setcaps_function (pad, gst_base_src_setcaps);
/* hold ref to pad */
basesrc->srcpad = pad;
@ -214,6 +220,46 @@ gst_base_src_set_dataflow_funcs (GstBaseSrc * this)
gst_pad_set_getrange_function (this->srcpad, NULL);
}
static gboolean
gst_base_src_setcaps (GstPad * pad, GstCaps * caps)
{
GstBaseSrcClass *bclass;
GstBaseSrc *bsrc;
gboolean res = TRUE;
bsrc = GST_BASE_SRC (GST_PAD_PARENT (pad));
bclass = GST_BASE_SRC_GET_CLASS (bsrc);
if (bclass->set_caps)
res = bclass->set_caps (bsrc, caps);
return res;
}
static GstCaps *
gst_base_src_getcaps (GstPad * pad)
{
GstBaseSrcClass *bclass;
GstBaseSrc *bsrc;
GstCaps *caps = NULL;
bsrc = GST_BASE_SRC (GST_PAD_PARENT (pad));
bclass = GST_BASE_SRC_GET_CLASS (bsrc);
if (bclass->get_caps)
caps = bclass->get_caps (bsrc);
if (caps == NULL) {
GstPadTemplate *pad_template;
pad_template =
gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src");
if (pad_template != NULL) {
caps = gst_caps_ref (gst_pad_template_get_caps (pad_template));
}
}
return caps;
}
static gboolean
gst_base_src_query (GstPad * pad, GstQuery * query)
{
@ -565,6 +611,9 @@ gst_base_src_loop (GstPad * pad)
if (ret != GST_FLOW_OK)
goto eos;
if (buf == NULL)
goto error;
src->offset += GST_BUFFER_SIZE (buf);
ret = gst_pad_push (pad, buf);
@ -586,6 +635,13 @@ pause:
gst_pad_pause_task (pad);
return;
}
error:
{
GST_DEBUG_OBJECT (src, "got error, pausing task");
gst_pad_pause_task (pad);
gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
return;
}
}
static gboolean
@ -645,6 +701,74 @@ gst_base_src_is_seekable (GstBaseSrc * basesrc)
return basesrc->seekable;
}
static gboolean
gst_base_src_default_negotiate (GstBaseSrc * basesrc)
{
GstCaps *thiscaps;
GstCaps *caps = NULL;
GstCaps *peercaps = NULL;
gboolean result = FALSE;
thiscaps = gst_pad_get_caps (GST_BASE_SRC_PAD (basesrc));
GST_DEBUG ("caps of src: %" GST_PTR_FORMAT, thiscaps);
if (thiscaps == NULL || gst_caps_is_any (thiscaps))
goto no_nego_needed;
peercaps = gst_pad_peer_get_caps (GST_BASE_SRC_PAD (basesrc));
GST_DEBUG ("caps of peer: %" GST_PTR_FORMAT, peercaps);
if (peercaps) {
GstCaps *icaps;
icaps = gst_caps_intersect (thiscaps, peercaps);
GST_DEBUG ("intersect: %" GST_PTR_FORMAT, icaps);
gst_caps_unref (thiscaps);
gst_caps_unref (peercaps);
if (icaps) {
caps = gst_caps_copy_nth (icaps, 0);
gst_caps_unref (icaps);
}
} else {
caps = thiscaps;
}
if (caps) {
caps = gst_caps_make_writable (caps);
gst_pad_fixate_caps (GST_BASE_SRC_PAD (basesrc), caps);
GST_DEBUG ("fixated to: %" GST_PTR_FORMAT, caps);
if (gst_caps_is_any (caps)) {
gst_caps_unref (caps);
result = TRUE;
} else if (gst_caps_is_fixed (caps)) {
gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), caps);
gst_caps_unref (caps);
result = TRUE;
}
}
return result;
no_nego_needed:
{
GST_DEBUG ("no negotiation needed");
if (thiscaps)
gst_caps_unref (thiscaps);
return TRUE;
}
}
static gboolean
gst_base_src_negotiate (GstBaseSrc * basesrc)
{
GstBaseSrcClass *bclass;
gboolean result = FALSE;
bclass = GST_BASE_SRC_GET_CLASS (basesrc);
if (bclass->negotiate)
result = bclass->negotiate (basesrc);
return result;
}
static gboolean
gst_base_src_start (GstBaseSrc * basesrc)
{
@ -694,9 +818,13 @@ gst_base_src_start (GstBaseSrc * basesrc)
caps = gst_type_find_helper (basesrc->srcpad, basesrc->size);
gst_pad_set_caps (basesrc->srcpad, caps);
gst_caps_unref (caps);
}
#endif
if (!gst_base_src_negotiate (basesrc))
goto could_not_negotiate;
return TRUE;
/* ERROR */
@ -705,6 +833,12 @@ could_not_start:
GST_DEBUG_OBJECT (basesrc, "could not start");
return FALSE;
}
could_not_negotiate:
{
GST_DEBUG_OBJECT (basesrc, "could not negotiate, stopping");
gst_base_src_stop (basesrc);
return FALSE;
}
}
static gboolean
@ -823,8 +957,10 @@ gst_base_src_change_state (GstElement * element)
break;
case GST_STATE_PAUSED_TO_PLAYING:
GST_LIVE_LOCK (element);
basesrc->live_running = TRUE;
GST_LIVE_SIGNAL (element);
if (basesrc->is_live) {
basesrc->live_running = TRUE;
GST_LIVE_SIGNAL (element);
}
GST_LIVE_UNLOCK (element);
break;
default:

View file

@ -113,6 +113,9 @@ struct _GstBaseSrcClass {
/* notify the subclass of new caps */
gboolean (*set_caps) (GstBaseSrc *src, GstCaps *caps);
/* decide on caps */
gboolean (*negotiate) (GstBaseSrc *src);
/* start and stop processing, ideal for opening/closing the resource */
gboolean (*start) (GstBaseSrc *src);
gboolean (*stop) (GstBaseSrc *src);

View file

@ -20,7 +20,9 @@ GstBaseTransform
Base class for simple tranform filters
- one sinkpad and one srcpad
- formats the same on sink and source pad.
- possible formats on sink and source pad implemented
with custom transform_caps function. By default uses
same format on sink and source.
- handles state changes
- does flushing
- push mode
@ -34,3 +36,7 @@ GstBaseSrc
- handles state changes
- pull/push mode
- handles seeking/query
GstPushSrc
Base class for push based source elements

View file

@ -447,7 +447,6 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
{
gint length;
gboolean have_event;
guint t;
GST_PREROLL_LOCK (pad);
/* push object on the queue */
@ -484,16 +483,21 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
/* if it's a buffer, we need to call the preroll method */
if (GST_IS_BUFFER (obj)) {
GstBaseSinkClass *bclass;
GstFlowReturn pres;
bclass = GST_BASESINK_GET_CLASS (basesink);
if (bclass->preroll)
bclass->preroll (basesink, GST_BUFFER (obj));
if ((pres =
bclass->preroll (basesink, GST_BUFFER (obj))) != GST_FLOW_OK)
goto preroll_failed;
}
}
length = basesink->preroll_queued;
GST_DEBUG ("prerolled length %d", length);
if (length == 1) {
guint t;
basesink->have_preroll = TRUE;
/* we are prerolling */
GST_PREROLL_UNLOCK (pad);
@ -575,6 +579,36 @@ flushing:
GST_DEBUG ("pad is flushing");
return GST_FLOW_WRONG_STATE;
}
preroll_failed:
{
guint t;
GST_DEBUG ("preroll failed");
basesink->have_preroll = FALSE;
gst_base_sink_preroll_queue_flush (basesink, pad);
GST_PREROLL_UNLOCK (pad);
/* have to release STREAM_LOCK as we cannot take the STATE_LOCK
* inside the STREAM_LOCK */
t = GST_STREAM_UNLOCK_FULL (pad);
GST_DEBUG ("released stream lock %d times", t);
if (t == 0) {
GST_WARNING ("STREAM_LOCK should have been locked !!");
g_warning ("STREAM_LOCK should have been locked !!");
}
/* now we abort our state */
GST_STATE_LOCK (basesink);
GST_DEBUG ("abort state %p >", basesink);
gst_element_abort_state (GST_ELEMENT (basesink));
GST_STATE_UNLOCK (basesink);
/* reacquire stream lock, pad could be flushing now */
if (t > 0)
GST_STREAM_LOCK_FULL (pad, t);
return GST_FLOW_ERROR;
}
}
static gboolean
@ -859,8 +893,10 @@ gst_base_sink_loop (GstPad * pad)
return;
paused:
gst_pad_pause_task (pad);
return;
{
gst_pad_pause_task (pad);
return;
}
}
static gboolean
@ -940,9 +976,15 @@ gst_base_sink_change_state (GstElement * element)
GstElementStateReturn ret = GST_STATE_SUCCESS;
GstBaseSink *basesink = GST_BASESINK (element);
GstElementState transition = GST_STATE_TRANSITION (element);
GstBaseSinkClass *bclass;
bclass = GST_BASESINK_GET_CLASS (basesink);
switch (transition) {
case GST_STATE_NULL_TO_READY:
if (bclass->start)
if (!bclass->start (basesink))
goto start_failed;
break;
case GST_STATE_READY_TO_PAUSED:
/* need to complete preroll before this state change completes, there
@ -1013,10 +1055,21 @@ gst_base_sink_change_state (GstElement * element)
case GST_STATE_PAUSED_TO_READY:
break;
case GST_STATE_READY_TO_NULL:
if (bclass->stop)
if (!bclass->stop (basesink)) {
GST_WARNING ("failed to stop");
}
break;
default:
break;
}
return ret;
/* ERRORS */
start_failed:
{
GST_DEBUG ("failed to start");
return GST_STATE_FAILURE;
}
}

View file

@ -87,6 +87,10 @@ struct _GstBaseSinkClass {
void (*get_times) (GstBaseSink *sink, GstBuffer *buffer,
GstClockTime *start, GstClockTime *end);
/* start and stop processing, ideal for opening/closing the resource */
gboolean (*start) (GstBaseSink *sink);
gboolean (*stop) (GstBaseSink *sink);
/* unlock any pending access to the resource. subclasses should unlock
* any function ASAP. */
gboolean (*unlock) (GstBaseSink *sink);

View file

@ -81,6 +81,8 @@ gst_base_src_get_type (void)
}
return base_src_type;
}
static GstCaps *gst_base_src_getcaps (GstPad * pad);
static gboolean gst_base_src_setcaps (GstPad * pad, GstCaps * caps);
static gboolean gst_base_src_activate_push (GstPad * pad, gboolean active);
static gboolean gst_base_src_activate_pull (GstPad * pad, gboolean active);
@ -95,6 +97,7 @@ static gboolean gst_base_src_query (GstPad * pad, GstQuery * query);
#if 0
static const GstEventMask *gst_base_src_get_event_mask (GstPad * pad);
#endif
static gboolean gst_base_src_default_negotiate (GstBaseSrc * basesrc);
static gboolean gst_base_src_unlock (GstBaseSrc * basesrc);
static gboolean gst_base_src_get_size (GstBaseSrc * basesrc, guint64 * size);
@ -146,6 +149,8 @@ gst_base_src_class_init (GstBaseSrcClass * klass)
gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_base_src_change_state);
klass->negotiate = gst_base_src_default_negotiate;
}
static void
@ -154,6 +159,10 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
GstPad *pad;
GstPadTemplate *pad_template;
basesrc->is_live = FALSE;
basesrc->live_lock = g_mutex_new ();
basesrc->live_cond = g_cond_new ();
pad_template =
gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src");
g_return_if_fail (pad_template != NULL);
@ -164,12 +173,9 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
gst_pad_set_activatepull_function (pad, gst_base_src_activate_pull);
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);
basesrc->is_live = FALSE;
basesrc->live_lock = g_mutex_new ();
basesrc->live_cond = g_cond_new ();
gst_pad_set_getcaps_function (pad, gst_base_src_getcaps);
gst_pad_set_setcaps_function (pad, gst_base_src_setcaps);
/* hold ref to pad */
basesrc->srcpad = pad;
@ -214,6 +220,46 @@ gst_base_src_set_dataflow_funcs (GstBaseSrc * this)
gst_pad_set_getrange_function (this->srcpad, NULL);
}
static gboolean
gst_base_src_setcaps (GstPad * pad, GstCaps * caps)
{
GstBaseSrcClass *bclass;
GstBaseSrc *bsrc;
gboolean res = TRUE;
bsrc = GST_BASE_SRC (GST_PAD_PARENT (pad));
bclass = GST_BASE_SRC_GET_CLASS (bsrc);
if (bclass->set_caps)
res = bclass->set_caps (bsrc, caps);
return res;
}
static GstCaps *
gst_base_src_getcaps (GstPad * pad)
{
GstBaseSrcClass *bclass;
GstBaseSrc *bsrc;
GstCaps *caps = NULL;
bsrc = GST_BASE_SRC (GST_PAD_PARENT (pad));
bclass = GST_BASE_SRC_GET_CLASS (bsrc);
if (bclass->get_caps)
caps = bclass->get_caps (bsrc);
if (caps == NULL) {
GstPadTemplate *pad_template;
pad_template =
gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src");
if (pad_template != NULL) {
caps = gst_caps_ref (gst_pad_template_get_caps (pad_template));
}
}
return caps;
}
static gboolean
gst_base_src_query (GstPad * pad, GstQuery * query)
{
@ -565,6 +611,9 @@ gst_base_src_loop (GstPad * pad)
if (ret != GST_FLOW_OK)
goto eos;
if (buf == NULL)
goto error;
src->offset += GST_BUFFER_SIZE (buf);
ret = gst_pad_push (pad, buf);
@ -586,6 +635,13 @@ pause:
gst_pad_pause_task (pad);
return;
}
error:
{
GST_DEBUG_OBJECT (src, "got error, pausing task");
gst_pad_pause_task (pad);
gst_pad_push_event (pad, gst_event_new (GST_EVENT_EOS));
return;
}
}
static gboolean
@ -645,6 +701,74 @@ gst_base_src_is_seekable (GstBaseSrc * basesrc)
return basesrc->seekable;
}
static gboolean
gst_base_src_default_negotiate (GstBaseSrc * basesrc)
{
GstCaps *thiscaps;
GstCaps *caps = NULL;
GstCaps *peercaps = NULL;
gboolean result = FALSE;
thiscaps = gst_pad_get_caps (GST_BASE_SRC_PAD (basesrc));
GST_DEBUG ("caps of src: %" GST_PTR_FORMAT, thiscaps);
if (thiscaps == NULL || gst_caps_is_any (thiscaps))
goto no_nego_needed;
peercaps = gst_pad_peer_get_caps (GST_BASE_SRC_PAD (basesrc));
GST_DEBUG ("caps of peer: %" GST_PTR_FORMAT, peercaps);
if (peercaps) {
GstCaps *icaps;
icaps = gst_caps_intersect (thiscaps, peercaps);
GST_DEBUG ("intersect: %" GST_PTR_FORMAT, icaps);
gst_caps_unref (thiscaps);
gst_caps_unref (peercaps);
if (icaps) {
caps = gst_caps_copy_nth (icaps, 0);
gst_caps_unref (icaps);
}
} else {
caps = thiscaps;
}
if (caps) {
caps = gst_caps_make_writable (caps);
gst_pad_fixate_caps (GST_BASE_SRC_PAD (basesrc), caps);
GST_DEBUG ("fixated to: %" GST_PTR_FORMAT, caps);
if (gst_caps_is_any (caps)) {
gst_caps_unref (caps);
result = TRUE;
} else if (gst_caps_is_fixed (caps)) {
gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), caps);
gst_caps_unref (caps);
result = TRUE;
}
}
return result;
no_nego_needed:
{
GST_DEBUG ("no negotiation needed");
if (thiscaps)
gst_caps_unref (thiscaps);
return TRUE;
}
}
static gboolean
gst_base_src_negotiate (GstBaseSrc * basesrc)
{
GstBaseSrcClass *bclass;
gboolean result = FALSE;
bclass = GST_BASE_SRC_GET_CLASS (basesrc);
if (bclass->negotiate)
result = bclass->negotiate (basesrc);
return result;
}
static gboolean
gst_base_src_start (GstBaseSrc * basesrc)
{
@ -694,9 +818,13 @@ gst_base_src_start (GstBaseSrc * basesrc)
caps = gst_type_find_helper (basesrc->srcpad, basesrc->size);
gst_pad_set_caps (basesrc->srcpad, caps);
gst_caps_unref (caps);
}
#endif
if (!gst_base_src_negotiate (basesrc))
goto could_not_negotiate;
return TRUE;
/* ERROR */
@ -705,6 +833,12 @@ could_not_start:
GST_DEBUG_OBJECT (basesrc, "could not start");
return FALSE;
}
could_not_negotiate:
{
GST_DEBUG_OBJECT (basesrc, "could not negotiate, stopping");
gst_base_src_stop (basesrc);
return FALSE;
}
}
static gboolean
@ -823,8 +957,10 @@ gst_base_src_change_state (GstElement * element)
break;
case GST_STATE_PAUSED_TO_PLAYING:
GST_LIVE_LOCK (element);
basesrc->live_running = TRUE;
GST_LIVE_SIGNAL (element);
if (basesrc->is_live) {
basesrc->live_running = TRUE;
GST_LIVE_SIGNAL (element);
}
GST_LIVE_UNLOCK (element);
break;
default:

View file

@ -113,6 +113,9 @@ struct _GstBaseSrcClass {
/* notify the subclass of new caps */
gboolean (*set_caps) (GstBaseSrc *src, GstCaps *caps);
/* decide on caps */
gboolean (*negotiate) (GstBaseSrc *src);
/* start and stop processing, ideal for opening/closing the resource */
gboolean (*start) (GstBaseSrc *src);
gboolean (*stop) (GstBaseSrc *src);