From: Wim Taymans Date: Wed, 6 Jul 2005 13:25:26 +0000 (+0000) Subject: gst/base/: Make basesrc negotiate. X-Git-Tag: RELEASE-0_9_2~289 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=03aa950f7dc959af588c45bdf2c00e291879de61;p=platform%2Fupstream%2Fgstreamer.git 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. --- diff --git a/ChangeLog b/ChangeLog index ccf4497..3c76cd9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,22 @@ 2005-07-06 Wim Taymans + * 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 + * gst/gstpad.c: (gst_pad_fixate_caps), (gst_pad_accept_caps): Implement the fixate function. Clean up acceptcaps. diff --git a/gst/base/README b/gst/base/README index 2633218..8047beb 100644 --- a/gst/base/README +++ b/gst/base/README @@ -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 diff --git a/gst/base/gstbasesink.c b/gst/base/gstbasesink.c index f0aa9f8..78befff 100644 --- a/gst/base/gstbasesink.c +++ b/gst/base/gstbasesink.c @@ -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; + } } diff --git a/gst/base/gstbasesink.h b/gst/base/gstbasesink.h index e0d0f8a..336de29 100644 --- a/gst/base/gstbasesink.h +++ b/gst/base/gstbasesink.h @@ -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); diff --git a/gst/base/gstbasesrc.c b/gst/base/gstbasesrc.c index 333a947..9ebb8db 100644 --- a/gst/base/gstbasesrc.c +++ b/gst/base/gstbasesrc.c @@ -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; @@ -215,6 +221,46 @@ gst_base_src_set_dataflow_funcs (GstBaseSrc * this) } 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) { gboolean b; @@ -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 @@ -646,6 +702,74 @@ gst_base_src_is_seekable (GstBaseSrc * basesrc) } 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) { GstBaseSrcClass *bclass; @@ -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: diff --git a/gst/base/gstbasesrc.h b/gst/base/gstbasesrc.h index 3ebb4f5..a6d641d 100644 --- a/gst/base/gstbasesrc.h +++ b/gst/base/gstbasesrc.h @@ -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); diff --git a/libs/gst/base/README b/libs/gst/base/README index 2633218..8047beb 100644 --- a/libs/gst/base/README +++ b/libs/gst/base/README @@ -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 diff --git a/libs/gst/base/gstbasesink.c b/libs/gst/base/gstbasesink.c index f0aa9f8..78befff 100644 --- a/libs/gst/base/gstbasesink.c +++ b/libs/gst/base/gstbasesink.c @@ -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; + } } diff --git a/libs/gst/base/gstbasesink.h b/libs/gst/base/gstbasesink.h index e0d0f8a..336de29 100644 --- a/libs/gst/base/gstbasesink.h +++ b/libs/gst/base/gstbasesink.h @@ -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); diff --git a/libs/gst/base/gstbasesrc.c b/libs/gst/base/gstbasesrc.c index 333a947..9ebb8db 100644 --- a/libs/gst/base/gstbasesrc.c +++ b/libs/gst/base/gstbasesrc.c @@ -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; @@ -215,6 +221,46 @@ gst_base_src_set_dataflow_funcs (GstBaseSrc * this) } 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) { gboolean b; @@ -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 @@ -646,6 +702,74 @@ gst_base_src_is_seekable (GstBaseSrc * basesrc) } 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) { GstBaseSrcClass *bclass; @@ -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: diff --git a/libs/gst/base/gstbasesrc.h b/libs/gst/base/gstbasesrc.h index 3ebb4f5..a6d641d 100644 --- a/libs/gst/base/gstbasesrc.h +++ b/libs/gst/base/gstbasesrc.h @@ -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);