diff --git a/configure.ac b/configure.ac index 08a1788e1e..50e1ebed81 100644 --- a/configure.ac +++ b/configure.ac @@ -313,7 +313,7 @@ dnl Make sure you have a space before and after all plugins GST_PLUGINS_NONPORTED=" aiff \ cdxaparse \ dccp faceoverlay \ - fieldanalysis freeverb freeze frei0r \ + fieldanalysis freeverb frei0r \ hdvparse inter ivfparse jp2kdecimator \ kate librfb \ mpegpsmux mve mxf mythtv nsf nuvdemux \ diff --git a/gst/freeze/gstfreeze.c b/gst/freeze/gstfreeze.c index f4022b86a6..7c2e633d97 100644 --- a/gst/freeze/gstfreeze.c +++ b/gst/freeze/gstfreeze.c @@ -33,8 +33,6 @@ #include "config.h" #endif -#include - #include "gstfreeze.h" GST_DEBUG_CATEGORY_STATIC (freeze_debug); @@ -63,24 +61,27 @@ static void gst_freeze_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_freeze_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static GstFlowReturn gst_freeze_chain (GstPad * pad, GstBuffer * buffer); +static GstFlowReturn gst_freeze_chain (GstPad * pad, GstObject * parent, + GstBuffer * buffer); static GstStateChangeReturn gst_freeze_change_state (GstElement * element, GstStateChange transition); -static GstFlowReturn gst_freeze_play (GstPad * pad, GstBuffer * buff); -static void gst_freeze_loop (GstPad * pad); -static gboolean gst_freeze_sink_activate (GstPad * sinkpad); -static gboolean gst_freeze_sink_activate_pull (GstPad * sinkpad, - gboolean active); -static gboolean gst_freeze_sink_event (GstPad * pad, GstEvent * event); +static GstFlowReturn gst_freeze_play (GstFreeze * freeze, GstBuffer * buff); +static void gst_freeze_loop (GstFreeze * freeze); +static gboolean gst_freeze_sink_activate (GstPad * sinkpad, GstObject * parent); +static gboolean gst_freeze_sink_activate_mode (GstPad * sinkpad, + GstObject * parent, GstPadMode mode, gboolean active); +static gboolean gst_freeze_sink_event (GstPad * pad, GstObject * parent, + GstEvent * event); static void gst_freeze_clear_buffer (GstFreeze * freeze); static void gst_freeze_buffer_free (gpointer data, gpointer user_data); -GST_BOILERPLATE (GstFreeze, gst_freeze, GstElement, GST_TYPE_ELEMENT); +G_DEFINE_TYPE (GstFreeze, gst_freeze, GST_TYPE_ELEMENT); static void -gst_freeze_base_init (gpointer klass) +gst_freeze_class_init (GstFreezeClass * klass) { + GObjectClass *object_class = G_OBJECT_CLASS (klass); GstElementClass *element_class = GST_ELEMENT_CLASS (klass); gst_element_class_set_details_simple (element_class, "Stream freezer", @@ -94,14 +95,6 @@ gst_freeze_base_init (gpointer klass) gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&gst_freeze_src_template)); -} - -static void -gst_freeze_class_init (GstFreezeClass * klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - element_class->change_state = gst_freeze_change_state; object_class->set_property = gst_freeze_set_property; object_class->get_property = gst_freeze_get_property; @@ -118,28 +111,30 @@ gst_freeze_class_init (GstFreezeClass * klass) } static void -gst_freeze_init (GstFreeze * freeze, GstFreezeClass * klass) +gst_freeze_init (GstFreeze * freeze) { freeze->sinkpad = gst_pad_new_from_static_template (&gst_freeze_sink_template, "sink"); - gst_element_add_pad (GST_ELEMENT (freeze), freeze->sinkpad); gst_pad_set_activate_function (freeze->sinkpad, gst_freeze_sink_activate); - gst_pad_set_activatepull_function (freeze->sinkpad, - gst_freeze_sink_activate_pull); + gst_pad_set_activatemode_function (freeze->sinkpad, + gst_freeze_sink_activate_mode); gst_pad_set_chain_function (freeze->sinkpad, gst_freeze_chain); - gst_pad_set_getcaps_function (freeze->sinkpad, gst_pad_proxy_getcaps); + GST_PAD_SET_PROXY_CAPS (freeze->sinkpad); + GST_PAD_SET_PROXY_ALLOCATION (freeze->sinkpad); gst_pad_set_event_function (freeze->sinkpad, gst_freeze_sink_event); + gst_element_add_pad (GST_ELEMENT (freeze), freeze->sinkpad); freeze->srcpad = gst_pad_new_from_static_template (&gst_freeze_src_template, "src"); + GST_PAD_SET_PROXY_CAPS (freeze->srcpad); + GST_PAD_SET_PROXY_ALLOCATION (freeze->srcpad); + GST_PAD_SET_PROXY_SCHEDULING (freeze->srcpad); gst_element_add_pad (GST_ELEMENT (freeze), freeze->srcpad); - gst_pad_set_getcaps_function (freeze->srcpad, gst_pad_proxy_getcaps); freeze->timestamp_offset = 0; freeze->running_time = 0; freeze->current = NULL; freeze->max_buffers = 1; - freeze->on_flush = FALSE; freeze->buffers = g_queue_new (); } @@ -152,7 +147,7 @@ gst_freeze_dispose (GObject * object) g_queue_free (freeze->buffers); - G_OBJECT_CLASS (parent_class)->dispose (object); + G_OBJECT_CLASS (gst_freeze_parent_class)->dispose (object); } static void @@ -188,9 +183,11 @@ gst_freeze_get_property (GObject * object, guint prop_id, } static GstFlowReturn -gst_freeze_chain (GstPad * pad, GstBuffer * buffer) +gst_freeze_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) { - return gst_freeze_play (pad, buffer); + GstFreeze *freeze = GST_FREEZE (parent); + + return gst_freeze_play (freeze, buffer); } @@ -198,73 +195,35 @@ static GstStateChangeReturn gst_freeze_change_state (GstElement * element, GstStateChange transition) { GstFreeze *freeze = GST_FREEZE (element); - GstStateChangeReturn return_val = GST_STATE_CHANGE_SUCCESS; switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: - break; - case GST_STATE_CHANGE_NULL_TO_READY: - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: freeze->timestamp_offset = freeze->running_time = 0; break; default: break; } - if (GST_ELEMENT_CLASS (parent_class)->change_state) - return_val = - GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - case GST_STATE_CHANGE_READY_TO_NULL: - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - freeze->timestamp_offset = freeze->running_time = 0; - break; - default: - break; - } - - return return_val; + return GST_ELEMENT_CLASS (gst_freeze_parent_class)->change_state (element, + transition); } static GstFlowReturn -gst_freeze_play (GstPad * pad, GstBuffer * buff) +gst_freeze_play (GstFreeze * freeze, GstBuffer * buf) { - GstFreeze *freeze; GstFlowReturn ret = GST_FLOW_OK; + GstBuffer *outbuf; - freeze = GST_FREEZE (gst_pad_get_parent (pad)); - - if (freeze->on_flush) { - g_object_unref (freeze); - return GST_FLOW_FLUSHING; - } - - /* If it is working in push mode this function will be called by "_chain" - and buff will never be NULL. In pull mode this function will be called - by _loop and buff will be NULL */ - if (!buff) { - ret = - gst_pad_pull_range (GST_PAD (freeze->sinkpad), freeze->offset, 4096, - &buff); - if (ret != GST_FLOW_OK) { - gst_object_unref (freeze); - return ret; - } - - freeze->offset += GST_BUFFER_SIZE (buff); - - } + if (freeze->current == NULL) + freeze->timestamp_offset = GST_BUFFER_TIMESTAMP (buf); if (g_queue_get_length (freeze->buffers) < freeze->max_buffers || freeze->max_buffers == 0) { - g_queue_push_tail (freeze->buffers, buff); + g_queue_push_tail (freeze->buffers, buf); GST_DEBUG_OBJECT (freeze, "accepted buffer %u", g_queue_get_length (freeze->buffers) - 1); } else { - gst_buffer_unref (buff); + gst_buffer_unref (buf); } @@ -280,43 +239,72 @@ gst_freeze_play (GstPad * pad, GstBuffer * buff) freeze->current = g_queue_peek_head (freeze->buffers); } - GST_BUFFER_TIMESTAMP (freeze->current) = freeze->timestamp_offset + + outbuf = gst_buffer_copy (freeze->current); + + GST_BUFFER_TIMESTAMP (outbuf) = freeze->timestamp_offset + freeze->running_time; freeze->running_time += GST_BUFFER_DURATION (freeze->current); - gst_buffer_ref (freeze->current); - ret = gst_pad_push (freeze->srcpad, freeze->current); - - gst_object_unref (freeze); + ret = gst_pad_push (freeze->srcpad, outbuf); return ret; } static void -gst_freeze_loop (GstPad * pad) +gst_freeze_loop (GstFreeze * freeze) { - gst_freeze_play (pad, NULL); + GstBuffer *buf; + GstFlowReturn ret; + + ret = gst_pad_pull_range (freeze->sinkpad, freeze->offset, 4096, &buf); + if (ret != GST_FLOW_OK) + return; + + freeze->offset += gst_buffer_get_size (buf); + + gst_freeze_play (freeze, buf); } static gboolean -gst_freeze_sink_activate (GstPad * sinkpad) +gst_freeze_sink_activate (GstPad * sinkpad, GstObject * parent) { - if (gst_pad_check_pull_range (sinkpad)) { - return gst_pad_activate_pull (sinkpad, TRUE); - } else { - return gst_pad_activate_push (sinkpad, TRUE); - } + GstQuery *query; + GstPadMode mode; + + query = gst_query_new_scheduling (); + + if (!gst_pad_peer_query (sinkpad, query)) + goto no_valid_mode; + + if (gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL)) + mode = GST_PAD_MODE_PULL; + else if (gst_query_has_scheduling_mode (query, GST_PAD_MODE_PUSH)) + mode = GST_PAD_MODE_PUSH; + else + goto no_valid_mode; + + gst_query_unref (query); + + return gst_pad_activate_mode (sinkpad, mode, TRUE); + +no_valid_mode: + return FALSE; } static gboolean -gst_freeze_sink_activate_pull (GstPad * sinkpad, gboolean active) +gst_freeze_sink_activate_mode (GstPad * sinkpad, GstObject * parent, + GstPadMode mode, gboolean active) { + GstFreeze *freeze = GST_FREEZE (parent); gboolean result; + if (mode != GST_PAD_MODE_PULL) + return TRUE; + if (active) { /* if we have a scheduler we can start the task */ result = gst_pad_start_task (sinkpad, - (GstTaskFunction) gst_freeze_loop, sinkpad, NULL); + (GstTaskFunction) gst_freeze_loop, freeze, NULL); } else { result = gst_pad_stop_task (sinkpad); } @@ -341,11 +329,10 @@ gst_freeze_clear_buffer (GstFreeze * freeze) } static gboolean -gst_freeze_sink_event (GstPad * pad, GstEvent * event) +gst_freeze_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) { + GstFreeze *freeze = GST_FREEZE (parent); gboolean ret = TRUE; - GstFreeze *freeze = GST_FREEZE (gst_pad_get_parent (pad)); - switch (GST_EVENT_TYPE (event)) { case GST_EVENT_EOS: @@ -353,17 +340,15 @@ gst_freeze_sink_event (GstPad * pad, GstEvent * event) gst_pad_get_name (GST_PAD (freeze->sinkpad))); gst_event_unref (event); break; - case GST_EVENT_NEWSEGMENT: - /* FALL TROUGH */ + case GST_EVENT_STREAM_START: case GST_EVENT_FLUSH_STOP: gst_freeze_clear_buffer (freeze); /* FALL TROUGH */ default: - ret = gst_pad_event_default (GST_PAD (freeze->sinkpad), event); + ret = gst_pad_event_default (GST_PAD (freeze->sinkpad), parent, event); break; } - gst_object_unref (freeze); return ret; } @@ -382,12 +367,3 @@ GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, freeze, "Stream freezer", plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN); - -/* - * Local variables: - * mode: c - * file-style: k&r - * c-basic-offset: 2 - * arch-tag: fb0ee62b-cf74-46c0-8e62-93b58bacc0ed - * End: - */ diff --git a/gst/freeze/gstfreeze.h b/gst/freeze/gstfreeze.h index 47cead72dc..92b186fe84 100644 --- a/gst/freeze/gstfreeze.h +++ b/gst/freeze/gstfreeze.h @@ -59,11 +59,3 @@ GType gst_freeze_get_type (void); G_END_DECLS #endif -/* - * Local variables: - * mode: c - * file-style: k&r - * c-basic-offset: 2 - * arch-tag: 559a2214-86a1-4c2f-b497-bdcc5f82acf1 - * End: - */