[gstreamer-bugs] [Bug 317438] New: Patch to fixe gst/speed/gstspeed.c
GStreamer (bugzilla.gnome.org)
bugzilla-daemon at bugzilla.gnome.org
Wed Sep 28 07:39:32 PDT 2005
Do not reply to this via email (we are currently unable to handle email
responses and they get discarded). You can add comments to this bug at
http://bugzilla.gnome.org/show_bug.cgi?id=317438
GStreamer | gst-plugins-bad | Ver: HEAD CVS
Summary: Patch to fixe gst/speed/gstspeed.c
Product: GStreamer
Version: HEAD CVS
Platform: Other
OS/Version: Linux
Status: UNCONFIRMED
Severity: normal
Priority: Normal
Component: gst-plugins-bad
AssignedTo: gstreamer-bugs at lists.sourceforge.net
ReportedBy: edgard.lima at indt.org.br
QAContact: gstreamer-bugs at lists.sourceforge.net
CC: all-bugs at bugzilla.gnome.org
#
# Please take a special look in the functions (speed_src_event,
# gst_speed_convert and speed_src_query) to see if it has been really fixed
#
# diff -urNaw gst-plugins-bad.orig gst-plugins-bad > gst-plugins-bad.patch
# the contents of gst-plugins-bad.patch follows below
#
diff -urNaw gst-plugins-bad.orig/ChangeLog gst-plugins-bad/ChangeLog
--- gst-plugins-bad.orig/ChangeLog 2005-09-26 12:19:38.000000000 -0300
+++ gst-plugins-bad/ChangeLog 2005-09-28 10:53:26.852942288 -0300
@@ -1,3 +1,13 @@
+2005-09-28 Edgard Lima <edgard.lima at indt.org.br>
+
+ * gst/speed/gstspeed.c: (speed_chain), (speed_setcaps),
+ (speed_parse_caps), (speed_src_event), (speed_sink_event),
+ (speed_src_query), (speed_init), (speed_set_property),
+ (speed_change_state), (gst_speed_convert):
+ Fixed speed - the previous version, 1.38, has been ported to 0.9
+ from a wrong version, 1.37 (from 1.36). That fix already includes
+ the changes done in 1.36.2.4.
+
2005-09-26 Christian Schaller <uraeus at gnome.org>
* configure.ac: add speed and rfb where needed
diff -urNaw gst-plugins-bad.orig/gst/speed/gstspeed.c
gst-plugins-bad/gst/speed/gstspeed.c
--- gst-plugins-bad.orig/gst/speed/gstspeed.c 2005-09-08 12:56:38.000000000 -0300
+++ gst-plugins-bad/gst/speed/gstspeed.c 2005-09-28 10:53:50.977274832 -0300
@@ -87,13 +87,15 @@
static GstFlowReturn speed_chain (GstPad * pad, GstBuffer * buf);
-static GstStateChangeReturn speed_change_state (GstElement * element,
- GstStateChange transition);
+static GstStateChangeReturn speed_change_state (GstElement * element,
GstStateChange transition);
+
+static gboolean speed_sink_event (GstPad * pad, GstEvent * event);
+static gboolean speed_src_event (GstPad * pad, GstEvent * event);
static GstElementClass *parent_class; /* NULL */
static gboolean
-gst_speed_setcaps (GstPad * pad, GstCaps * caps)
+speed_setcaps (GstPad * pad, GstCaps * caps)
{
GstSpeed *filter;
GstPad *otherpad;
@@ -103,10 +105,12 @@
g_return_val_if_fail (GST_IS_SPEED (filter), GST_PAD_LINK_REFUSED);
otherpad = (pad == filter->srcpad) ? filter->sinkpad : filter->srcpad;
- if (!speed_parse_caps (filter, caps))
- return GST_PAD_LINK_REFUSED;
+ if (!speed_parse_caps (filter, caps)) {
+ return FALSE;
+ }
return gst_pad_set_caps (otherpad, caps);
+
}
static gboolean
@@ -114,7 +118,7 @@
{
const gchar *mimetype;
GstStructure *structure;
- gboolean ret;
+ gint rate, chans, width, buffer_frames;
g_return_val_if_fail (filter != NULL, FALSE);
g_return_val_if_fail (caps != NULL, FALSE);
@@ -126,15 +130,24 @@
filter->format = GST_SPEED_FORMAT_FLOAT;
else if (strcmp (mimetype, "audio/x-raw-int") == 0)
filter->format = GST_SPEED_FORMAT_INT;
- else
+ else {
return FALSE;
+ }
- ret = gst_structure_get_int (structure, "rate", &filter->rate);
- ret &= gst_structure_get_int (structure, "channels", &filter->channels);
- ret &= gst_structure_get_int (structure, "width", &filter->width);
+ if (!gst_structure_get_int (structure, "rate", &rate)
+ || !gst_structure_get_int (structure, "width", &width)
+ || !gst_structure_get_int (structure, "channels", &chans)) {
+ return FALSE;
+ }
+
+ filter->rate = rate;
+ filter->width = width;
+ filter->channels = chans;
+ if (gst_structure_get_int (structure, "buffer-frames", &buffer_frames))
+ filter->buffer_frames = buffer_frames;
+ else
filter->buffer_frames = 0;
- gst_structure_get_int (structure, "buffer-frames", &filter->buffer_frames);
if (filter->format == GST_SPEED_FORMAT_FLOAT) {
filter->sample_size = filter->channels * filter->width / 8;
@@ -143,7 +156,7 @@
filter->sample_size = filter->channels * filter->width / 8;
}
- return ret;
+ return TRUE;
}
GType
@@ -182,7 +195,111 @@
}
static gboolean
+speed_src_event (GstPad * pad, GstEvent * event)
+{
+ GstSpeed *filter;
+ GstEvent *newevent;
+
+ filter = GST_SPEED (gst_pad_get_parent (pad));
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_SEEK:
+ {
+ gdouble rate;
+ GstFormat format;
+ GstSeekFlags flags;
+ GstSeekType start_type, stop_type;
+ gint64 start, stop;
+
+ gst_event_parse_seek (event, &rate, &format, &flags,
+ &start_type, &start, &stop_type, &stop);
+
+ newevent = gst_event_new_seek (rate, format, flags, start_type, start *
filter->speed, stop_type, stop);
+
+ gst_event_unref (event);
+ event = newevent;
+ return gst_pad_send_event (GST_PAD_PEER (filter->sinkpad), event);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return gst_pad_event_default (pad, event);
+}
+
+static gboolean
+gst_speed_convert (GstPad * pad, GstFormat src_format, gint64 src_value,
+ GstFormat * dest_format, gint64 * dest_value)
+{
+ gboolean res = TRUE;
+ guint scale = 1;
+ GstSpeed *filter;
+
+ if ( src_format == *dest_format ) {
+ *dest_value = src_value;
+ return TRUE;
+ }
+
+ filter = GST_SPEED (gst_pad_get_parent (pad));
+
+ switch (src_format) {
+ case GST_FORMAT_BYTES:
+ switch (*dest_format) {
+ case GST_FORMAT_DEFAULT:
+ if (filter->sample_size == 0)
+ return FALSE;
+ *dest_value = src_value / filter->sample_size;
+ break;
+ case GST_FORMAT_TIME:
+ {
+ gint byterate = filter->sample_size * filter->rate;
+
+ if (byterate == 0)
+ return FALSE;
+ *dest_value = src_value * GST_SECOND / byterate;
+ break;
+ }
+ default:
+ res = FALSE;
+ }
+ break;
+ case GST_FORMAT_DEFAULT:
+ switch (*dest_format) {
+ case GST_FORMAT_BYTES:
+ *dest_value = src_value * filter->sample_size;
+ break;
+ case GST_FORMAT_TIME:
+ if (filter->rate == 0)
+ return FALSE;
+ *dest_value = src_value * GST_SECOND / filter->rate;
+ break;
+ default:
+ res = FALSE;
+ }
+ break;
+ case GST_FORMAT_TIME:
+ switch (*dest_format) {
+ case GST_FORMAT_BYTES:
+ scale = filter->sample_size;
+ /* fallthrough */
+ case GST_FORMAT_DEFAULT:
+ *dest_value =
+ src_value * scale * filter->rate / GST_SECOND;
+ break;
+ default:
+ res = FALSE;
+ }
+ break;
+ default:
+ res = FALSE;
+ }
+ return res;
+}
+
+static gboolean
speed_src_query (GstPad * pad, GstQuery * query)
+
{
gboolean res = TRUE;
GstSpeed *filter;
@@ -192,7 +309,140 @@
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_POSITION:
{
+ GstFormat format;
+ GstFormat rformat;
+ gint64 cur, end;
+ GstPad *peer;
+
+ /* save requested format */
+ gst_query_parse_position (query, &format, NULL, NULL);
+
+ /* query peer for total length in bytes */
+ gst_query_set_position (query, GST_FORMAT_BYTES, -1, -1);
+
+ if ((peer = gst_pad_get_peer (filter->sinkpad)) == NULL)
+ goto error;
+
+ if (!gst_pad_query (peer, query)) {
+ GST_LOG_OBJECT (filter, "query on peer pad failed");
+ goto error;
+ }
+ gst_object_unref (peer);
+
+ /* get the returned format */
+ gst_query_parse_position (query, &rformat, NULL, &end);
+ if (rformat == GST_FORMAT_BYTES)
+ GST_LOG_OBJECT (filter, "peer pad returned total=%lld bytes",
+ end);
+ else if (rformat == GST_FORMAT_TIME)
+ GST_LOG_OBJECT (filter, "peer pad returned time=%lld", end);
+
+ /* Check if requested format is returned format */
+ /*
+ if (format == rformat) {
+ cur = (gint64) (((gdouble) cur) / filter->speed);
+ gst_query_set_position (query, format, cur, total);
+ return TRUE;
+ }
+ */
+
+ GstFormat conv_format = GST_FORMAT_TIME;
+
+ /* convert to time format */
+ if ( ! gst_speed_convert (pad, rformat, cur, &conv_format, &cur) ) {
+ return FALSE;
+ }
+ /* convert to time format */
+ if ( ! gst_speed_convert (pad, rformat, end, &conv_format, &end) ) {
+ return FALSE;
+ }
+
+ /* adjust for speed factor */
+ cur /= filter->speed;
+ end /= filter->speed;
+
+ /* convert to time format */
+ if ( ! gst_speed_convert (pad, conv_format, cur, &format, &cur) ) {
+ return FALSE;
+ }
+ /* convert to time format */
+ if ( ! gst_speed_convert (pad, conv_format, end, &format, &end) ) {
+ return FALSE;
+ }
+
+ gst_query_set_position (query, format, cur, end);
+
+ GST_LOG_OBJECT (filter,
+ "position query: peer returned total: %llu - we return %llu (format %u)",
+ end, cur, format);
+
+ break;
+ }
+ default:
+ res = FALSE;
+ break;
+ }
+
+ return res;
+
+error:
+
+ GST_DEBUG ("error handling query");
+ return FALSE;
+}
+
+#if 0
+speed_src_query (GstPad * pad, GstQueryType type,
+ GstFormat * format, gint64 * val)
+{
+ gboolean res = TRUE;
+ GstSpeed *filter;
+
+ filter = GST_SPEED (gst_pad_get_parent (pad));
+
+ switch (type) {
+ case GST_QUERY_POSITION:
+ {
+ switch (*format) {
+ case GST_FORMAT_BYTES:
+ case GST_FORMAT_DEFAULT:
+ case GST_FORMAT_TIME:
+ {
+ gint64 peer_value;
+ const GstFormat *peer_formats;
+
res = FALSE;
+
+ peer_formats = gst_pad_get_formats (GST_PAD_PEER (filter->sinkpad));
+
+ while (peer_formats && *peer_formats && !res) {
+
+ GstFormat peer_format = *peer_formats;
+
+ /* do the probe */
+ if (gst_pad_query (GST_PAD_PEER (filter->sinkpad), type,
+ &peer_format, &peer_value)) {
+ GstFormat conv_format;
+
+ /* convert to TIME */
+ conv_format = GST_FORMAT_TIME;
+ res = gst_pad_convert (filter->sinkpad,
+ peer_format, peer_value, &conv_format, val);
+
+ /* adjust for speed factor */
+ *val = (gint64) (((gdouble) * val) / filter->speed);
+
+ /* and to final format */
+ res &= gst_pad_convert (pad, GST_FORMAT_TIME, *val, format, val);
+ }
+ peer_formats++;
+ }
+ break;
+ }
+ default:
+ res = FALSE;
+ break;
+ }
break;
}
default:
@@ -201,6 +451,7 @@
}
return res;
}
+#endif
static void
speed_base_init (gpointer g_class)
@@ -237,24 +488,25 @@
filter->sinkpad =
gst_pad_new_from_template (gst_static_pad_template_get
(&gst_speed_sink_template), "sink");
- gst_pad_set_setcaps_function (filter->sinkpad, gst_speed_setcaps);
+ gst_pad_set_setcaps_function (filter->sinkpad, speed_setcaps);
gst_pad_set_chain_function (filter->sinkpad, speed_chain);
- gst_pad_set_getcaps_function (filter->sinkpad, gst_pad_proxy_getcaps);
gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
+ gst_pad_set_event_function (filter->sinkpad, speed_sink_event);
filter->srcpad =
gst_pad_new_from_template (gst_static_pad_template_get
(&gst_speed_src_template), "src");
- /*gst_pad_set_link_function (filter->srcpad, speed_link); */
- gst_pad_set_setcaps_function (filter->srcpad, gst_speed_setcaps);
- gst_pad_set_getcaps_function (filter->srcpad, gst_pad_proxy_getcaps);
+ gst_pad_set_setcaps_function (filter->srcpad, speed_setcaps);
gst_pad_set_query_type_function (filter->srcpad, speed_get_query_types);
gst_pad_set_query_function (filter->srcpad, speed_src_query);
gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
+ gst_pad_set_event_function (filter->srcpad, speed_src_event);
+
filter->offset = 0;
filter->timestamp = 0;
filter->sample_size = 0;
+
}
static inline guint
@@ -323,64 +575,103 @@
return j;
}
-static GstFlowReturn
-speed_chain (GstPad * pad, GstBuffer * buf)
+
+static gboolean speed_sink_event (GstPad * pad, GstEvent * event) {
+
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_NEWSEGMENT:
{
- GstBuffer *out_buf;
GstSpeed *filter;
- guint c, in_samples, out_samples, out_size;
- GstFlowReturn result = GST_FLOW_OK;
+ gint64 timestamp, offset;
+ gdouble rate;
+ GstFormat format;
+ gint64 start_value, stop_value, base;
+ GstEvent *newevent;
-/*
- g_return_if_fail (pad != NULL);
- g_return_if_fail (GST_IS_PAD (pad));
- g_return_if_fail (data != NULL);
-*/
filter = GST_SPEED (GST_OBJECT_PARENT (pad));
- /*g_return_if_fail (GST_IS_SPEED (filter)); */
+ g_return_val_if_fail (GST_IS_SPEED (filter), FALSE);
- if (GST_IS_EVENT (buf)) {
- switch (GST_EVENT_TYPE (GST_EVENT (buf))) {
- case GST_EVENT_NEWSEGMENT:
- { /*
- gint64 timestamp, offset;
- GstFormat format = GST_FORMAT_UNDEFINED;
- gint64 value, end_value;
+ gst_event_parse_newsegment (event, &rate, &format, &start_value,
&stop_value, &base);
- gst_event_parse_newsegment (GST_EVENT (buf),
NULL, &format, &value, &end_value, NULL);
if (format == GST_FORMAT_TIME) {
- filter->timestamp = timestamp;
- filter->offset = timestamp * filter->rate /
GST_SECOND;
+
+ g_assert (filter->speed > 0);
+
+ timestamp = start_value;
+
+ filter->timestamp = timestamp / filter->speed;
+ filter->offset = filter->timestamp * filter->rate / GST_SECOND;
+
+ newevent = gst_event_new_newsegment (rate, format, filter->timestamp,
stop_value, base);
+
+ } else if ( format == GST_FORMAT_BYTES ) {
+
+ g_assert (filter->speed > 0);
+ if ( filter->rate == 0 ) {
+ filter->rate = 1.0;
}
- if (format == GST_FORMAT_BYTES) {
- filter->offset = offset;
- filter->timestamp = offset * GST_SECOND /
filter->rate;
+
+ offset = start_value;
+
+ filter->offset = offset / filter->speed;
+ filter->timestamp = filter->offset * GST_SECOND / filter->rate;
+
+ newevent = gst_event_new_newsegment (rate, format, filter->offset,
stop_value, base);
+
}
- */
+ gst_event_unref (event);
+ event = newevent;
+
break;
}
default:
break;
}
- gst_pad_event_default (pad, GST_EVENT (buf));
- return GST_FLOW_OK;
+
+ return gst_pad_event_default (pad, event);
+
}
- out_size = ceil ((gfloat) GST_BUFFER_SIZE (buf) / filter->speed);
+static GstFlowReturn
+speed_chain (GstPad * pad, GstBuffer * in_buf)
+{
+ GstBuffer *out_buf;
+ GstSpeed *filter;
+ guint c, in_samples, out_samples, out_size;
+ GstFlowReturn result = GST_FLOW_OK;
+
+ g_return_val_if_fail (pad != NULL, GST_FLOW_ERROR);
+ g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
+
+ filter = GST_SPEED (GST_OBJECT_PARENT (pad));
+ g_return_val_if_fail (GST_IS_SPEED (filter), GST_FLOW_ERROR);
+
+
+ /* buffersize has to be aligned by samplesize */
+ out_size = ceil ((gfloat) GST_BUFFER_SIZE (in_buf) / filter->speed);
+ out_size = (filter->sample_size * (out_size + filter->sample_size - 1)) /
+ filter->sample_size;
+
result =
gst_pad_alloc_buffer (filter->srcpad, -1, out_size,
GST_PAD_CAPS (filter->srcpad), &out_buf);
- in_samples = GST_BUFFER_SIZE (buf) / filter->sample_size;
+ if ( result != GST_FLOW_OK ) {
+ return result;
+ }
+
+ in_samples = GST_BUFFER_SIZE (in_buf) / filter->sample_size;
out_samples = 0;
for (c = 0; c < filter->channels; ++c) {
if (filter->format == GST_SPEED_FORMAT_INT) {
- out_samples = speed_chain_int16 (filter, buf, out_buf, c, in_samples);
+ out_samples = speed_chain_int16 (filter, in_buf, out_buf, c, in_samples);
} else {
- out_samples = speed_chain_float32 (filter, buf, out_buf, c, in_samples);
+ out_samples =
+ speed_chain_float32 (filter, in_buf, out_buf, c, in_samples);
}
}
@@ -397,8 +688,8 @@
gst_pad_push (filter->srcpad, out_buf);
- return result;
- /*gst_buffer_unref (in_buf); */
+ return GST_FLOW_OK;
+
}
static void
@@ -414,6 +705,7 @@
filter->speed = g_value_get_float (value);
break;
default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
@@ -442,12 +734,9 @@
GstSpeed *speed = GST_SPEED (element);
switch (transition) {
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
speed->offset = 0;
speed->timestamp = 0;
- speed->sample_size = 0;
break;
default:
break;
------- You are receiving this mail because: -------
You are the assignee for the bug.
You are the QA contact for the bug.
More information about the Gstreamer-bugs
mailing list