+2005-11-29 Edward Hervey <edward@fluendo.com>
+
+ * gst/base/gstbasetransform.c: (gst_base_transform_class_init),
+ (gst_base_transform_event), (gst_base_transform_eventfunc):
+ The event virtual method is now properly implemented, with a default
+ handler
+ Sub classes should call the parent_class event method. They should
+ return FALSE if they had a problem handling the given event, or don't
+ want GstBaseTransform to send that even downstream
+ * gst/elements/gstidentity.c: (gst_identity_class_init),
+ (gst_identity_init), (gst_identity_event),
+ (gst_identity_transform_ip), (gst_identity_set_property),
+ (gst_identity_get_property):
+ * gst/elements/gstidentity.h:
+ Added the single-segment boolean property.
+ If set to TRUE, it will output a single segment of data, starting from
+ 0, will eat up all incoming newsegment, and modify the timestamp of the
+ buffers accordingly
+
2005-11-29 Tim-Philipp Müller <tim at centricular dot net>
* gst/gstghostpad.c: (gst_proxy_pad_get_target):
element, GstStateChange transition);
static gboolean gst_base_transform_event (GstPad * pad, GstEvent * event);
+static gboolean gst_base_transform_eventfunc (GstBaseTransform * trans,
+ GstEvent * event);
static GstFlowReturn gst_base_transform_getrange (GstPad * pad, guint64 offset,
guint length, GstBuffer ** buffer);
static GstFlowReturn gst_base_transform_chain (GstPad * pad,
GST_DEBUG_FUNCPTR (gst_base_transform_change_state);
klass->passthrough_on_same_caps = FALSE;
+ klass->event = GST_DEBUG_FUNCPTR (gst_base_transform_eventfunc);
}
static void
{
GstBaseTransform *trans;
GstBaseTransformClass *bclass;
- gboolean ret = FALSE;
+ gboolean ret = TRUE;
trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
if (bclass->event)
- bclass->event (trans, event);
+ ret = bclass->event (trans, event);
+
+ if (ret)
+ ret = gst_pad_event_default (pad, event);
+
+ gst_object_unref (trans);
+
+ return ret;
+}
+static gboolean
+gst_base_transform_eventfunc (GstBaseTransform * trans, GstEvent * event)
+{
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_FLUSH_START:
break;
default:
break;
}
- ret = gst_pad_event_default (pad, event);
- gst_object_unref (trans);
-
- return ret;
+ return TRUE;
}
static GstFlowReturn
#define DEFAULT_DROP_PROBABILITY 0.0
#define DEFAULT_DATARATE 0
#define DEFAULT_SILENT FALSE
+#define DEFAULT_SINGLE_SEGMENT FALSE
#define DEFAULT_DUMP FALSE
#define DEFAULT_SYNC FALSE
#define DEFAULT_CHECK_PERFECT FALSE
PROP_DROP_PROBABILITY,
PROP_DATARATE,
PROP_SILENT,
+ PROP_SINGLE_SEGMENT,
PROP_LAST_MESSAGE,
PROP_DUMP,
PROP_SYNC,
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SILENT,
g_param_spec_boolean ("silent", "silent", "silent", DEFAULT_SILENT,
G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SINGLE_SEGMENT,
+ g_param_spec_boolean ("single-segment", "Single Segment",
+ "Timestamp buffers and eat newsegments so as to appear as one segment",
+ DEFAULT_SINGLE_SEGMENT, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_LAST_MESSAGE,
g_param_spec_string ("last-message", "last-message", "last-message", NULL,
G_PARAM_READABLE));
identity->drop_probability = DEFAULT_DROP_PROBABILITY;
identity->datarate = DEFAULT_DATARATE;
identity->silent = DEFAULT_SILENT;
+ identity->single_segment = DEFAULT_SINGLE_SEGMENT;
identity->sync = DEFAULT_SYNC;
identity->check_perfect = DEFAULT_CHECK_PERFECT;
identity->dump = DEFAULT_DUMP;
gst_identity_event (GstBaseTransform * trans, GstEvent * event)
{
GstIdentity *identity;
+ gboolean ret = TRUE;
identity = GST_IDENTITY (trans);
g_object_notify (G_OBJECT (identity), "last_message");
}
- return TRUE;
+
+ if (identity->single_segment
+ && (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT)) {
+ if (trans->have_newsegment == FALSE) {
+ GstEvent *news;
+ GstFormat format;
+
+ gst_event_parse_new_segment (event, NULL, NULL, &format, NULL, NULL,
+ NULL);
+
+ /* This is the first newsegment, send out a (0, -1) newsegment */
+ news = gst_event_new_new_segment (TRUE, 1.0, format, 0, -1, 0);
+
+ if (!(gst_pad_event_default (trans->sinkpad, news)))
+ return FALSE;
+ }
+ }
+
+ GST_BASE_TRANSFORM_CLASS (parent_class)->event (trans, event);
+
+ if (identity->single_segment
+ && (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT)) {
+ /* eat up segments */
+ ret = FALSE;
+ }
+
+ return ret;
}
static void
{
GstFlowReturn ret = GST_FLOW_OK;
GstIdentity *identity = GST_IDENTITY (trans);
+ GstClockTime runtimestamp;
if (identity->check_perfect)
gst_identity_check_perfect (identity, buf);
g_signal_emit (G_OBJECT (identity), gst_identity_signals[SIGNAL_HANDOFF], 0,
buf);
+ runtimestamp = gst_segment_to_running_time (&trans->segment,
+ GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buf));
+
if (identity->sync) {
GstClock *clock;
GstClockReturn cret;
GstClockTime timestamp;
- timestamp = gst_segment_to_running_time (&trans->segment,
- GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buf));
- timestamp += GST_ELEMENT (identity)->base_time;
+ timestamp = runtimestamp + GST_ELEMENT (identity)->base_time;
/* save id if we need to unlock */
/* FIXME: actually unlock this somewhere in the state changes */
if (identity->sleep_time && ret == GST_FLOW_OK)
g_usleep (identity->sleep_time);
+ if (identity->single_segment && ret == GST_FLOW_OK)
+ GST_BUFFER_TIMESTAMP (buf) = runtimestamp;
+
return ret;
}
case PROP_SILENT:
identity->silent = g_value_get_boolean (value);
break;
+ case PROP_SINGLE_SEGMENT:
+ identity->single_segment = g_value_get_boolean (value);
+ break;
case PROP_DUMP:
identity->dump = g_value_get_boolean (value);
break;
case PROP_SILENT:
g_value_set_boolean (value, identity->silent);
break;
+ case PROP_SINGLE_SEGMENT:
+ g_value_set_boolean (value, identity->single_segment);
+ break;
case PROP_DUMP:
g_value_set_boolean (value, identity->dump);
break;
gboolean dump;
gboolean sync;
gboolean check_perfect;
+ gboolean single_segment;
GstClockTime prev_timestamp;
GstClockTime prev_duration;
guint64 prev_offset_end;
element, GstStateChange transition);
static gboolean gst_base_transform_event (GstPad * pad, GstEvent * event);
+static gboolean gst_base_transform_eventfunc (GstBaseTransform * trans,
+ GstEvent * event);
static GstFlowReturn gst_base_transform_getrange (GstPad * pad, guint64 offset,
guint length, GstBuffer ** buffer);
static GstFlowReturn gst_base_transform_chain (GstPad * pad,
GST_DEBUG_FUNCPTR (gst_base_transform_change_state);
klass->passthrough_on_same_caps = FALSE;
+ klass->event = GST_DEBUG_FUNCPTR (gst_base_transform_eventfunc);
}
static void
{
GstBaseTransform *trans;
GstBaseTransformClass *bclass;
- gboolean ret = FALSE;
+ gboolean ret = TRUE;
trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
if (bclass->event)
- bclass->event (trans, event);
+ ret = bclass->event (trans, event);
+
+ if (ret)
+ ret = gst_pad_event_default (pad, event);
+
+ gst_object_unref (trans);
+
+ return ret;
+}
+static gboolean
+gst_base_transform_eventfunc (GstBaseTransform * trans, GstEvent * event)
+{
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_FLUSH_START:
break;
default:
break;
}
- ret = gst_pad_event_default (pad, event);
- gst_object_unref (trans);
-
- return ret;
+ return TRUE;
}
static GstFlowReturn
#define DEFAULT_DROP_PROBABILITY 0.0
#define DEFAULT_DATARATE 0
#define DEFAULT_SILENT FALSE
+#define DEFAULT_SINGLE_SEGMENT FALSE
#define DEFAULT_DUMP FALSE
#define DEFAULT_SYNC FALSE
#define DEFAULT_CHECK_PERFECT FALSE
PROP_DROP_PROBABILITY,
PROP_DATARATE,
PROP_SILENT,
+ PROP_SINGLE_SEGMENT,
PROP_LAST_MESSAGE,
PROP_DUMP,
PROP_SYNC,
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SILENT,
g_param_spec_boolean ("silent", "silent", "silent", DEFAULT_SILENT,
G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SINGLE_SEGMENT,
+ g_param_spec_boolean ("single-segment", "Single Segment",
+ "Timestamp buffers and eat newsegments so as to appear as one segment",
+ DEFAULT_SINGLE_SEGMENT, G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_LAST_MESSAGE,
g_param_spec_string ("last-message", "last-message", "last-message", NULL,
G_PARAM_READABLE));
identity->drop_probability = DEFAULT_DROP_PROBABILITY;
identity->datarate = DEFAULT_DATARATE;
identity->silent = DEFAULT_SILENT;
+ identity->single_segment = DEFAULT_SINGLE_SEGMENT;
identity->sync = DEFAULT_SYNC;
identity->check_perfect = DEFAULT_CHECK_PERFECT;
identity->dump = DEFAULT_DUMP;
gst_identity_event (GstBaseTransform * trans, GstEvent * event)
{
GstIdentity *identity;
+ gboolean ret = TRUE;
identity = GST_IDENTITY (trans);
g_object_notify (G_OBJECT (identity), "last_message");
}
- return TRUE;
+
+ if (identity->single_segment
+ && (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT)) {
+ if (trans->have_newsegment == FALSE) {
+ GstEvent *news;
+ GstFormat format;
+
+ gst_event_parse_new_segment (event, NULL, NULL, &format, NULL, NULL,
+ NULL);
+
+ /* This is the first newsegment, send out a (0, -1) newsegment */
+ news = gst_event_new_new_segment (TRUE, 1.0, format, 0, -1, 0);
+
+ if (!(gst_pad_event_default (trans->sinkpad, news)))
+ return FALSE;
+ }
+ }
+
+ GST_BASE_TRANSFORM_CLASS (parent_class)->event (trans, event);
+
+ if (identity->single_segment
+ && (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT)) {
+ /* eat up segments */
+ ret = FALSE;
+ }
+
+ return ret;
}
static void
{
GstFlowReturn ret = GST_FLOW_OK;
GstIdentity *identity = GST_IDENTITY (trans);
+ GstClockTime runtimestamp;
if (identity->check_perfect)
gst_identity_check_perfect (identity, buf);
g_signal_emit (G_OBJECT (identity), gst_identity_signals[SIGNAL_HANDOFF], 0,
buf);
+ runtimestamp = gst_segment_to_running_time (&trans->segment,
+ GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buf));
+
if (identity->sync) {
GstClock *clock;
GstClockReturn cret;
GstClockTime timestamp;
- timestamp = gst_segment_to_running_time (&trans->segment,
- GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buf));
- timestamp += GST_ELEMENT (identity)->base_time;
+ timestamp = runtimestamp + GST_ELEMENT (identity)->base_time;
/* save id if we need to unlock */
/* FIXME: actually unlock this somewhere in the state changes */
if (identity->sleep_time && ret == GST_FLOW_OK)
g_usleep (identity->sleep_time);
+ if (identity->single_segment && ret == GST_FLOW_OK)
+ GST_BUFFER_TIMESTAMP (buf) = runtimestamp;
+
return ret;
}
case PROP_SILENT:
identity->silent = g_value_get_boolean (value);
break;
+ case PROP_SINGLE_SEGMENT:
+ identity->single_segment = g_value_get_boolean (value);
+ break;
case PROP_DUMP:
identity->dump = g_value_get_boolean (value);
break;
case PROP_SILENT:
g_value_set_boolean (value, identity->silent);
break;
+ case PROP_SINGLE_SEGMENT:
+ g_value_set_boolean (value, identity->single_segment);
+ break;
case PROP_DUMP:
g_value_set_boolean (value, identity->dump);
break;
gboolean dump;
gboolean sync;
gboolean check_perfect;
+ gboolean single_segment;
GstClockTime prev_timestamp;
GstClockTime prev_duration;
guint64 prev_offset_end;