diff options
Diffstat (limited to 'plugins/elements/gstidentity.c')
-rw-r--r-- | plugins/elements/gstidentity.c | 214 |
1 files changed, 113 insertions, 101 deletions
diff --git a/plugins/elements/gstidentity.c b/plugins/elements/gstidentity.c index 460660f..50afaec 100644 --- a/plugins/elements/gstidentity.c +++ b/plugins/elements/gstidentity.c @@ -32,10 +32,10 @@ #endif #include <stdlib.h> +#include <string.h> #include "../../gst/gst-i18n-lib.h" #include "gstidentity.h" -#include <gst/gstmarshal.h> static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, @@ -63,7 +63,7 @@ enum #define DEFAULT_ERROR_AFTER -1 #define DEFAULT_DROP_PROBABILITY 0.0 #define DEFAULT_DATARATE 0 -#define DEFAULT_SILENT FALSE +#define DEFAULT_SILENT TRUE #define DEFAULT_SINGLE_SEGMENT FALSE #define DEFAULT_DUMP FALSE #define DEFAULT_SYNC FALSE @@ -107,10 +107,10 @@ static gboolean gst_identity_sink_event (GstBaseTransform * trans, GstEvent * event); static GstFlowReturn gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf); -static GstFlowReturn gst_identity_prepare_output_buffer (GstBaseTransform * - trans, GstBuffer * in_buf, GstBuffer ** out_buf); static gboolean gst_identity_start (GstBaseTransform * trans); static gboolean gst_identity_stop (GstBaseTransform * trans); +static GstStateChangeReturn gst_identity_change_state (GstElement * element, + GstStateChange transition); static guint gst_identity_signals[LAST_SIGNAL] = { 0 }; @@ -125,41 +125,9 @@ gst_identity_finalize (GObject * object) g_free (identity->last_message); -#if !GLIB_CHECK_VERSION(2,26,0) - g_static_rec_mutex_free (&identity->notify_lock); -#endif - G_OBJECT_CLASS (parent_class)->finalize (object); } -/* fixme: do something about this */ -static void -marshal_VOID__MINIOBJECT (GClosure * closure, GValue * return_value, - guint n_param_values, const GValue * param_values, gpointer invocation_hint, - gpointer marshal_data) -{ - typedef void (*marshalfunc_VOID__MINIOBJECT) (gpointer obj, gpointer arg1, - gpointer data2); - register marshalfunc_VOID__MINIOBJECT callback; - register GCClosure *cc = (GCClosure *) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 2); - - if (G_CCLOSURE_SWAP_DATA (closure)) { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } else { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = - (marshalfunc_VOID__MINIOBJECT) (marshal_data ? marshal_data : - cc->callback); - - callback (data1, g_value_get_boxed (param_values + 1), data2); -} - static void gst_identity_class_init (GstIdentityClass * klass) { @@ -254,11 +222,12 @@ gst_identity_class_init (GstIdentityClass * klass) gst_identity_signals[SIGNAL_HANDOFF] = g_signal_new ("handoff", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstIdentityClass, handoff), NULL, NULL, - marshal_VOID__MINIOBJECT, G_TYPE_NONE, 1, GST_TYPE_BUFFER); + g_cclosure_marshal_generic, G_TYPE_NONE, 1, + GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE); gobject_class->finalize = gst_identity_finalize; - gst_element_class_set_details_simple (gstelement_class, + gst_element_class_set_static_metadata (gstelement_class, "Identity", "Generic", "Pass data without modification", "Erik Walthinsen <omega@cse.ogi.edu>"); @@ -267,11 +236,12 @@ gst_identity_class_init (GstIdentityClass * klass) gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&sinktemplate)); + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_identity_change_state); + gstbasetrans_class->sink_event = GST_DEBUG_FUNCPTR (gst_identity_sink_event); gstbasetrans_class->transform_ip = GST_DEBUG_FUNCPTR (gst_identity_transform_ip); - gstbasetrans_class->prepare_output_buffer = - GST_DEBUG_FUNCPTR (gst_identity_prepare_output_buffer); gstbasetrans_class->start = GST_DEBUG_FUNCPTR (gst_identity_start); gstbasetrans_class->stop = GST_DEBUG_FUNCPTR (gst_identity_stop); } @@ -293,29 +263,13 @@ gst_identity_init (GstIdentity * identity) identity->last_message = NULL; identity->signal_handoffs = DEFAULT_SIGNAL_HANDOFFS; -#if !GLIB_CHECK_VERSION(2,26,0) - g_static_rec_mutex_init (&identity->notify_lock); -#endif - gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM_CAST (identity), TRUE); } static void gst_identity_notify_last_message (GstIdentity * identity) { - /* FIXME: this hacks around a bug in GLib/GObject: doing concurrent - * g_object_notify() on the same object might lead to crashes, see - * http://bugzilla.gnome.org/show_bug.cgi?id=166020#c60 and follow-ups. - * So we really don't want to do a g_object_notify() here for out-of-band - * events with the streaming thread possibly also doing a g_object_notify() - * for an in-band buffer or event. This is fixed in GLib >= 2.26 */ -#if !GLIB_CHECK_VERSION(2,26,0) - g_static_rec_mutex_lock (&identity->notify_lock); - g_object_notify ((GObject *) identity, "last-message"); - g_static_rec_mutex_unlock (&identity->notify_lock); -#else g_object_notify_by_pspec ((GObject *) identity, pspec_last_message); -#endif } static gboolean @@ -328,20 +282,22 @@ gst_identity_sink_event (GstBaseTransform * trans, GstEvent * event) if (!identity->silent) { const GstStructure *s; + const gchar *tstr; gchar *sstr; GST_OBJECT_LOCK (identity); g_free (identity->last_message); + tstr = gst_event_type_get_name (GST_EVENT_TYPE (event)); if ((s = gst_event_get_structure (event))) sstr = gst_structure_to_string (s); else sstr = g_strdup (""); identity->last_message = - g_strdup_printf ("event ******* (%s:%s) E (type: %d, %s) %p", - GST_DEBUG_PAD_NAME (trans->sinkpad), GST_EVENT_TYPE (event), sstr, - event); + g_strdup_printf ("event ******* (%s:%s) E (type: %s (%d), %s) %p", + GST_DEBUG_PAD_NAME (trans->sinkpad), tstr, GST_EVENT_TYPE (event), + sstr, event); g_free (sstr); GST_OBJECT_UNLOCK (identity); @@ -361,7 +317,7 @@ gst_identity_sink_event (GstBaseTransform * trans, GstEvent * event) gst_segment_init (&segment, segment.format); news = gst_event_new_segment (&segment); - gst_pad_event_default (trans->sinkpad, news); + gst_pad_event_default (trans->sinkpad, GST_OBJECT_CAST (trans), news); } } @@ -372,39 +328,28 @@ gst_identity_sink_event (GstBaseTransform * trans, GstEvent * event) identity->prev_offset = identity->prev_offset_end = GST_BUFFER_OFFSET_NONE; } - - if (identity->single_segment && (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT)) { + if (identity->single_segment && GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) { /* eat up segments */ gst_event_unref (event); ret = TRUE; } else { + if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_START) { + GST_OBJECT_LOCK (identity); + if (identity->clock_id) { + GST_DEBUG_OBJECT (identity, "unlock clock wait"); + gst_clock_id_unschedule (identity->clock_id); + gst_clock_id_unref (identity->clock_id); + identity->clock_id = NULL; + } + GST_OBJECT_UNLOCK (identity); + } + ret = GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, event); } return ret; } -static GstFlowReturn -gst_identity_prepare_output_buffer (GstBaseTransform * trans, - GstBuffer * in_buf, GstBuffer ** out_buf) -{ - GstIdentity *identity = GST_IDENTITY (trans); - - /* only bother if we may have to alter metadata */ - if (identity->datarate > 0 || identity->single_segment) { - if (gst_buffer_is_writable (in_buf)) - /* reuse */ - *out_buf = in_buf; - else { - /* copy */ - *out_buf = gst_buffer_copy (in_buf); - } - } else - *out_buf = in_buf; - - return GST_FLOW_OK; -} - static void gst_identity_check_perfect (GstIdentity * identity, GstBuffer * buf) { @@ -559,19 +504,41 @@ static void gst_identity_update_last_message_for_buffer (GstIdentity * identity, const gchar * action, GstBuffer * buf, gsize size) { - gchar ts_str[64], dur_str[64]; + gchar dts_str[64], pts_str[64], dur_str[64]; + gchar flag_str[100]; GST_OBJECT_LOCK (identity); + { + const char *flag_list[15] = { + "", "", "", "", "live", "decode-only", "discont", "resync", "corrupted", + "marker", "header", "gap", "droppable", "delta-unit", "in-caps" + }; + int i; + char *end = flag_str; + end[0] = '\0'; + for (i = 0; i < G_N_ELEMENTS (flag_list); i++) { + if (GST_MINI_OBJECT_CAST (buf)->flags & (1 << i)) { + strcpy (end, flag_list[i]); + end += strlen (end); + end[0] = ' '; + end[1] = '\0'; + end++; + } + } + } + g_free (identity->last_message); - identity->last_message = g_strdup_printf ("%s ******* (%s:%s)i " - "(%" G_GSIZE_FORMAT " bytes, timestamp: %s, duration: %s, offset: %" - G_GINT64_FORMAT ", " "offset_end: % " G_GINT64_FORMAT ", flags: %d) %p", - action, GST_DEBUG_PAD_NAME (GST_BASE_TRANSFORM_CAST (identity)->sinkpad), - size, print_pretty_time (ts_str, sizeof (ts_str), - GST_BUFFER_TIMESTAMP (buf)), print_pretty_time (dur_str, - sizeof (dur_str), GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf), - GST_BUFFER_OFFSET_END (buf), GST_BUFFER_FLAGS (buf), buf); + identity->last_message = g_strdup_printf ("%s ******* (%s:%s) " + "(%" G_GSIZE_FORMAT " bytes, dts: %s, pts:%s, duration: %s, offset: %" + G_GINT64_FORMAT ", " "offset_end: % " G_GINT64_FORMAT + ", flags: %d %s) %p", action, + GST_DEBUG_PAD_NAME (GST_BASE_TRANSFORM_CAST (identity)->sinkpad), size, + print_pretty_time (dts_str, sizeof (dts_str), GST_BUFFER_DTS (buf)), + print_pretty_time (pts_str, sizeof (pts_str), GST_BUFFER_PTS (buf)), + print_pretty_time (dur_str, sizeof (dur_str), GST_BUFFER_DURATION (buf)), + GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf), + GST_BUFFER_FLAGS (buf), flag_str, buf); GST_OBJECT_UNLOCK (identity); @@ -584,10 +551,9 @@ gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf) GstFlowReturn ret = GST_FLOW_OK; GstIdentity *identity = GST_IDENTITY (trans); GstClockTime runtimestamp = G_GINT64_CONSTANT (0); - guint8 *data; gsize size; - data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ); + size = gst_buffer_get_size (buf); if (identity->check_perfect) gst_identity_check_perfect (identity, buf); @@ -614,7 +580,11 @@ gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf) } if (identity->dump) { - gst_util_dump_mem (data, size); + GstMapInfo info; + + gst_buffer_map (buf, &info, GST_MAP_READ); + gst_util_dump_mem (info.data, info.size); + gst_buffer_unmap (buf, &info); } if (!identity->silent) { @@ -647,7 +617,6 @@ gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf) timestamp = runtimestamp + GST_ELEMENT (identity)->base_time; /* save id if we need to unlock */ - /* FIXME: actually unlock this somewhere in the state changes */ identity->clock_id = gst_clock_new_single_shot_id (clock, timestamp); GST_OBJECT_UNLOCK (identity); @@ -659,7 +628,7 @@ gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf) identity->clock_id = NULL; } if (cret == GST_CLOCK_UNSCHEDULED) - ret = GST_FLOW_UNEXPECTED; + ret = GST_FLOW_EOS; } GST_OBJECT_UNLOCK (identity); } @@ -676,8 +645,6 @@ gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf) GST_BUFFER_OFFSET_END (buf) = GST_CLOCK_TIME_NONE; } - gst_buffer_unmap (buf, data, size); - return ret; /* ERRORS */ @@ -685,7 +652,6 @@ error_after: { GST_ELEMENT_ERROR (identity, CORE, FAILED, (_("Failed after iterations as requested.")), (NULL)); - gst_buffer_unmap (buf, data, size); return GST_FLOW_ERROR; } dropped: @@ -694,7 +660,6 @@ dropped: gst_identity_update_last_message_for_buffer (identity, "dropping", buf, size); } - gst_buffer_unmap (buf, data, size); /* return DROPPED to basetransform. */ return GST_BASE_TRANSFORM_FLOW_DROPPED; } @@ -749,6 +714,10 @@ gst_identity_set_property (GObject * object, guint prop_id, G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } + if (identity->datarate > 0 || identity->single_segment) + gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (identity), FALSE); + else + gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (identity), TRUE); } static void @@ -837,3 +806,46 @@ gst_identity_stop (GstBaseTransform * trans) return TRUE; } + +static GstStateChangeReturn +gst_identity_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret; + GstIdentity *identity = GST_IDENTITY (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + GST_OBJECT_LOCK (identity); + if (identity->clock_id) { + GST_DEBUG_OBJECT (identity, "unlock clock wait"); + gst_clock_id_unschedule (identity->clock_id); + gst_clock_id_unref (identity->clock_id); + identity->clock_id = NULL; + } + GST_OBJECT_UNLOCK (identity); + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_NULL: + break; + default: + break; + } + + return ret; +} |