diff options
Diffstat (limited to 'src/gsttools/gstvideoconnector.c')
-rw-r--r-- | src/gsttools/gstvideoconnector.c | 199 |
1 files changed, 185 insertions, 14 deletions
diff --git a/src/gsttools/gstvideoconnector.c b/src/gsttools/gstvideoconnector.c index 3e08fe53..ff3f9a36 100644 --- a/src/gsttools/gstvideoconnector.c +++ b/src/gsttools/gstvideoconnector.c @@ -67,26 +67,93 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY); + +#if GST_CHECK_VERSION(1,0,0) + +G_DEFINE_TYPE(GstVideoConnector, gst_video_connector, GST_TYPE_ELEMENT); +#else #define _do_init(bla) \ GST_DEBUG_CATEGORY_INIT (video_connector_debug, \ "video-connector", 0, "An identity like element for reconnecting video stream"); GST_BOILERPLATE_FULL (GstVideoConnector, gst_video_connector, GstElement, GST_TYPE_ELEMENT, _do_init); +#endif static void gst_video_connector_dispose (GObject * object); + +#if GST_CHECK_VERSION(1,0,0) +static GstFlowReturn gst_video_connector_chain (GstPad * pad, GstObject* parent, GstBuffer * buf); +#else static GstFlowReturn gst_video_connector_chain (GstPad * pad, GstBuffer * buf); static GstFlowReturn gst_video_connector_buffer_alloc (GstPad * pad, guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf); +#endif + static GstStateChangeReturn gst_video_connector_change_state (GstElement * element, GstStateChange transition); + +#if GST_CHECK_VERSION(1,0,0) +static gboolean gst_video_connector_handle_sink_event (GstPad * pad, GstObject* parent, + GstEvent * event); +#else static gboolean gst_video_connector_handle_sink_event (GstPad * pad, GstEvent * event); +#endif + +#if GST_CHECK_VERSION(1,0,0) +static GstPadProbeReturn gst_video_connector_new_buffer_probe(GstPad *pad, GstPadProbeInfo *info, gpointer object); +static GstPadProbeReturn gst_video_connector_new_event_probe(GstPad *pad, GstPadProbeInfo *info, gpointer object); +static GstPadProbeReturn gst_video_connector_new_query_probe(GstPad *pad, GstPadProbeInfo *info, gpointer object); +#else static gboolean gst_video_connector_new_buffer_probe(GstObject *pad, GstBuffer *buffer, guint * object); -static void gst_video_connector_resend_new_segment(GstElement * element, gboolean emitFailedSignal); static gboolean gst_video_connector_setcaps (GstPad *pad, GstCaps *caps); static GstCaps *gst_video_connector_getcaps (GstPad * pad); static gboolean gst_video_connector_acceptcaps (GstPad * pad, GstCaps * caps); +#endif + +static void gst_video_connector_resend_new_segment(GstElement * element, gboolean emitFailedSignal); + +#if GST_CHECK_VERSION(1,0,0) +static void +gst_video_connector_class_init (GstVideoConnectorClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_set_details_simple (gstelement_class, "Video Connector", + "Generic", + "An identity like element used for reconnecting video stream", + "Dmytro Poplavskiy <dmytro.poplavskiy@nokia.com>"); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&gst_video_connector_sink_factory)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&gst_video_connector_src_factory)); + + gst_video_connector_parent_class = g_type_class_peek_parent (klass); + + gobject_class->dispose = gst_video_connector_dispose; + gstelement_class->change_state = gst_video_connector_change_state; + klass->resend_new_segment = gst_video_connector_resend_new_segment; + + gst_video_connector_signals[SIGNAL_RESEND_NEW_SEGMENT] = + g_signal_new ("resend-new-segment", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GstVideoConnectorClass, resend_new_segment), NULL, NULL, + g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + + gst_video_connector_signals[SIGNAL_CONNECTION_FAILED] = + g_signal_new ("connection-failed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + GST_DEBUG_CATEGORY_INIT(video_connector_debug, "video-connector", 0, + "An identity like element for reconnecting video stream"); + +} + +#else static void gst_video_connector_base_init (gpointer g_class) @@ -128,18 +195,33 @@ gst_video_connector_class_init (GstVideoConnectorClass * klass) g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } +#endif + static void -gst_video_connector_init (GstVideoConnector *element, - GstVideoConnectorClass *g_class) +gst_video_connector_init (GstVideoConnector *element +#if GST_CHECK_VERSION(1,0,0) +#else + ,GstVideoConnectorClass *g_class +#endif + ) { +#if GST_CHECK_VERSION(1,0,0) +#else (void) g_class; +#endif element->sinkpad = gst_pad_new_from_static_template (&gst_video_connector_sink_factory, "sink"); gst_pad_set_chain_function(element->sinkpad, GST_DEBUG_FUNCPTR (gst_video_connector_chain)); +#if GST_CHECK_VERSION(1,0,0) + /* gstreamer 1.x uses QUERIES and EVENTS for allocation and caps handiling purposes */ + GST_OBJECT_FLAG_SET (element->sinkpad, GST_PAD_FLAG_PROXY_CAPS); + GST_OBJECT_FLAG_SET (element->sinkpad, GST_PAD_FLAG_PROXY_ALLOCATION); +#else gst_pad_set_event_function(element->sinkpad, GST_DEBUG_FUNCPTR (gst_video_connector_handle_sink_event)); + gst_pad_set_bufferalloc_function(element->sinkpad, GST_DEBUG_FUNCPTR (gst_video_connector_buffer_alloc)); gst_pad_set_setcaps_function(element->sinkpad, @@ -148,14 +230,23 @@ gst_video_connector_init (GstVideoConnector *element, GST_DEBUG_FUNCPTR(gst_video_connector_getcaps)); gst_pad_set_acceptcaps_function(element->sinkpad, GST_DEBUG_FUNCPTR(gst_video_connector_acceptcaps)); - +#endif gst_element_add_pad (GST_ELEMENT (element), element->sinkpad); element->srcpad = gst_pad_new_from_static_template (&gst_video_connector_src_factory, "src"); +#if GST_CHECK_VERSION(1,0,0) + gst_pad_add_probe(element->srcpad, GST_PAD_PROBE_TYPE_BUFFER, + gst_video_connector_new_buffer_probe, element, NULL); + gst_pad_add_probe(element->srcpad, GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM, + gst_video_connector_new_query_probe, element, NULL); + gst_pad_add_probe(element->sinkpad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, + gst_video_connector_new_event_probe, element, NULL); +#else gst_pad_add_buffer_probe(element->srcpad, G_CALLBACK(gst_video_connector_new_buffer_probe), element); +#endif gst_element_add_pad (GST_ELEMENT (element), element->srcpad); element->relinked = FALSE; @@ -183,9 +274,16 @@ gst_video_connector_dispose (GObject * object) gst_video_connector_reset (element); +#if GST_CHECK_VERSION(1,0,0) + G_OBJECT_CLASS (gst_video_connector_parent_class)->dispose (object); +#else G_OBJECT_CLASS (parent_class)->dispose (object); +#endif } +#if GST_CHECK_VERSION(1,0,0) +/* For gstreamer 1.x we handle it in ALLOCATION Query */ +#else // "When this function returns anything else than GST_FLOW_OK, // the buffer allocation failed and buf does not contain valid data." static GstFlowReturn @@ -229,6 +327,7 @@ gst_video_connector_buffer_alloc (GstPad * pad, guint64 offset, guint size, if (state == GST_STATE_NULL) { GST_DEBUG_OBJECT (element, "Downstream element is in NULL state"); // Downstream filter seems to be in the wrong state + return GST_FLOW_UNEXPECTED; } } @@ -301,6 +400,7 @@ static GstCaps *gst_video_connector_getcaps (GstPad * pad) return caps; } + static gboolean gst_video_connector_acceptcaps (GstPad * pad, GstCaps * caps) { GstVideoConnector *element; @@ -308,6 +408,7 @@ static gboolean gst_video_connector_acceptcaps (GstPad * pad, GstCaps * caps) return gst_pad_peer_accept_caps(element->srcpad, caps); } +#endif static void gst_video_connector_resend_new_segment(GstElement * element, gboolean emitFailedSignal) @@ -319,11 +420,39 @@ gst_video_connector_resend_new_segment(GstElement * element, gboolean emitFailed connector->failedSignalEmited = FALSE; } +#if GST_CHECK_VERSION(1,0,0) +static GstPadProbeReturn gst_video_connector_new_event_probe(GstPad *pad, GstPadProbeInfo *info, gpointer object) +{ + GstVideoConnector *connector = GST_VIDEO_CONNECTOR (object); + GstEvent *event = gst_pad_probe_info_get_event(info); + + GST_DEBUG_OBJECT(connector, "Event %"GST_PTR_FORMAT" received\n", event); + + return GST_PAD_PROBE_OK; +} + +static GstPadProbeReturn gst_video_connector_new_query_probe(GstPad *pad, GstPadProbeInfo *info, gpointer object) +{ + GstVideoConnector *connector = GST_VIDEO_CONNECTOR (object); + GstQuery *query = gst_pad_probe_info_get_query(info); + + GST_DEBUG_OBJECT(connector, "Query %"GST_PTR_FORMAT" received\n", query); + + return GST_PAD_PROBE_OK; +} +#endif +#if GST_CHECK_VERSION(1,0,0) +static GstPadProbeReturn gst_video_connector_new_buffer_probe(GstPad *pad, GstPadProbeInfo *info, gpointer object) +{ + (void) info; +#else static gboolean gst_video_connector_new_buffer_probe(GstObject *pad, GstBuffer *buffer, guint * object) { - (void) pad; (void) buffer; +#endif + (void) pad; + GstVideoConnector *element = GST_VIDEO_CONNECTOR (object); @@ -335,16 +464,23 @@ static gboolean gst_video_connector_new_buffer_probe(GstObject *pad, GstBuffer * if (element->relinked) GST_LOG_OBJECT(element, "rejected buffer because of new segment request"); - return !element->relinked; + return element->relinked ? GST_PAD_PROBE_DROP : GST_PAD_PROBE_OK; } - static GstFlowReturn +#if GST_CHECK_VERSION(1,0,0) +gst_video_connector_chain (GstPad * pad, GstObject* parent, GstBuffer * buf) +#else gst_video_connector_chain (GstPad * pad, GstBuffer * buf) +#endif { GstFlowReturn res; GstVideoConnector *element; +#if GST_CHECK_VERSION(1,0,0) + (void)parent; +#endif + element = GST_VIDEO_CONNECTOR (gst_pad_get_parent (pad)); do { @@ -356,20 +492,29 @@ gst_video_connector_chain (GstPad * pad, GstBuffer * buf) */ while (element->relinked) { element->relinked = FALSE; - +#if GST_CHECK_VERSION(1,0,0) + if (element->latest_buffer && GST_BUFFER_TIMESTAMP_IS_VALID(element->latest_buffer)) { + element->segment.position = GST_BUFFER_TIMESTAMP (element->latest_buffer); + } +#else gint64 pos = element->segment.last_stop; - if (element->latest_buffer && GST_BUFFER_TIMESTAMP_IS_VALID(element->latest_buffer)) { pos = GST_BUFFER_TIMESTAMP (element->latest_buffer); } +#endif //push a new segment and last buffer +#if GST_CHECK_VERSION(1,0,0) + GstEvent *ev = gst_event_new_segment (&element->segment); + +#else GstEvent *ev = gst_event_new_new_segment (TRUE, element->segment.rate, element->segment.format, pos, //start element->segment.stop, pos); +#endif GST_DEBUG_OBJECT (element, "Pushing new segment event"); if (!gst_pad_push_event (element->srcpad, ev)) { @@ -432,8 +577,11 @@ gst_video_connector_change_state (GstElement * element, GstStateChangeReturn result; connector = GST_VIDEO_CONNECTOR(element); +#if GST_CHECK_VERSION(1,0,0) + result = GST_ELEMENT_CLASS (gst_video_connector_parent_class)->change_state(element, transition); +#else result = GST_ELEMENT_CLASS (parent_class)->change_state(element, transition); - +#endif switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: gst_video_connector_reset (connector); @@ -448,9 +596,32 @@ gst_video_connector_change_state (GstElement * element, return result; } -static gboolean -gst_video_connector_handle_sink_event (GstPad * pad, GstEvent * event) +#if GST_CHECK_VERSION(1,0,0) +static gboolean gst_video_connector_handle_sink_event (GstPad * pad, GstObject* parent, + GstEvent * event) +{ + GstVideoConnector *element = GST_VIDEO_CONNECTOR (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEGMENT: + break; + case GST_EVENT_CAPS: + break; + default: + break; + } + + gst_object_unref (element); + return gst_pad_event_default (pad, parent, event); +} + +#else + +static gboolean gst_video_connector_handle_sink_event (GstPad * pad, + GstEvent * event) { + (void)parent; + if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) { GstVideoConnector *element = GST_VIDEO_CONNECTOR (gst_pad_get_parent (pad)); @@ -461,7 +632,6 @@ gst_video_connector_handle_sink_event (GstPad * pad, GstEvent * event) gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, &start, &stop, &time); - GST_LOG_OBJECT (element, "NEWSEGMENT update %d, rate %lf, applied rate %lf, " "format %d, " "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %" @@ -469,9 +639,10 @@ gst_video_connector_handle_sink_event (GstPad * pad, GstEvent * event) gst_segment_set_newsegment_full (&element->segment, update, rate, arate, format, start, stop, time); - gst_object_unref (element); } return gst_pad_event_default (pad, event); } + +#endif |