summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorBenjamin Gaignard <benjamin at gaignard.net>2009-06-18 10:55:39 +0200
committerWim Taymans <wim.taymans@collabora.co.uk>2009-06-18 10:55:39 +0200
commit1a6f82f4b01c4f71baf9416c6544426c432dbb9b (patch)
treee83349895430ada98c1c4d2f3fefddf47e31ab9e /plugins
parentbf2c34566748edff0acd4c0e15a1b656c8c7302e (diff)
fdsink: make fdsink seekable
Implement the same logic as filesink to implement seeking. Fixes #578908
Diffstat (limited to 'plugins')
-rw-r--r--plugins/elements/gstfdsink.c92
1 files changed, 89 insertions, 3 deletions
diff --git a/plugins/elements/gstfdsink.c b/plugins/elements/gstfdsink.c
index ace6777183..9cd84a3bc8 100644
--- a/plugins/elements/gstfdsink.c
+++ b/plugins/elements/gstfdsink.c
@@ -120,6 +120,9 @@ static gboolean gst_fd_sink_start (GstBaseSink * basesink);
static gboolean gst_fd_sink_stop (GstBaseSink * basesink);
static gboolean gst_fd_sink_unlock (GstBaseSink * basesink);
static gboolean gst_fd_sink_unlock_stop (GstBaseSink * basesink);
+static gboolean gst_fd_sink_event (GstBaseSink * sink, GstEvent * event);
+
+static gboolean gst_fd_sink_do_seek (GstFdSink * fdsink, guint64 new_offset);
static void
gst_fd_sink_base_init (gpointer g_class)
@@ -153,7 +156,7 @@ gst_fd_sink_class_init (GstFdSinkClass * klass)
gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_fd_sink_stop);
gstbasesink_class->unlock = GST_DEBUG_FUNCPTR (gst_fd_sink_unlock);
gstbasesink_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_fd_sink_unlock_stop);
- gstbasesink_class->event = NULL;
+ gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_fd_sink_event);
g_object_class_install_property (gobject_class, ARG_FD,
g_param_spec_int ("fd", "fd", "An open file descriptor to write to",
@@ -171,6 +174,7 @@ gst_fd_sink_init (GstFdSink * fdsink, GstFdSinkClass * klass)
fdsink->fd = 1;
fdsink->uri = g_strdup_printf ("fd://%d", fdsink->fd);
fdsink->bytes_written = 0;
+ fdsink->current_pos = 0;
GST_BASE_SINK (fdsink)->sync = TRUE;
}
@@ -200,8 +204,7 @@ gst_fd_sink_query (GstPad * pad, GstQuery * query)
switch (format) {
case GST_FORMAT_DEFAULT:
case GST_FORMAT_BYTES:
- gst_query_set_position (query, GST_FORMAT_BYTES,
- fdsink->bytes_written);
+ gst_query_set_position (query, GST_FORMAT_BYTES, fdsink->current_pos);
return TRUE;
default:
return FALSE;
@@ -274,6 +277,7 @@ again:
size -= written;
data += written;
fdsink->bytes_written += written;
+ fdsink->current_pos += written;
GST_DEBUG_OBJECT (fdsink, "wrote %d bytes, %d left", written, size);
@@ -374,6 +378,9 @@ gst_fd_sink_start (GstBaseSink * basesink)
gst_poll_add_fd (fdsink->fdset, &fd);
gst_poll_fd_ctl_write (fdsink->fdset, &fd, TRUE);
+ fdsink->bytes_written = 0;
+ fdsink->current_pos = 0;
+
return TRUE;
/* ERRORS */
@@ -501,6 +508,85 @@ gst_fd_sink_get_property (GObject * object, guint prop_id, GValue * value,
}
}
+static gboolean
+gst_fd_sink_do_seek (GstFdSink * fdsink, guint64 new_offset)
+{
+ off_t result;
+
+ result = lseek (fdsink->fd, new_offset, SEEK_SET);
+
+ if (result == -1)
+ goto seek_failed;
+
+ fdsink->current_pos = new_offset;
+
+ GST_DEBUG_OBJECT (fdsink, "File desciptor \"%d\" to seek to position %lld",
+ fdsink->fd, fdsink->current_pos);
+
+ return TRUE;
+
+ /* ERRORS */
+seek_failed:
+ {
+ GST_DEBUG_OBJECT (fdsink,
+ "File desciptor \"%d\" failed to seek to position %lld", fdsink->fd,
+ new_offset);
+ return FALSE;
+ }
+}
+
+static gboolean
+gst_fd_sink_event (GstBaseSink * sink, GstEvent * event)
+{
+ GstEventType type;
+ GstFdSink *fdsink;
+
+ fdsink = GST_FD_SINK (sink);
+
+ type = GST_EVENT_TYPE (event);
+
+ switch (type) {
+ case GST_EVENT_NEWSEGMENT:
+ {
+ gint64 start, stop, pos;
+ GstFormat format;
+ gst_event_parse_new_segment (event, NULL, NULL, &format, &start,
+ &stop, &pos);
+
+ if (format == GST_FORMAT_BYTES) {
+ /* only try to seek and fail when we are going to a different
+ * position */
+ if (fdsink->current_pos != start) {
+ /* FIXME, the seek should be performed on the pos field, start/stop are
+ * just boundaries for valid bytes offsets. We should also fill the file
+ * with zeroes if the new position extends the current EOF (sparse streams
+ * and segment accumulation). */
+ if (!gst_fd_sink_do_seek (fdsink, (guint64) start))
+ goto seek_failed;
+ }
+ } else {
+ GST_DEBUG_OBJECT (fdsink,
+ "Ignored NEWSEGMENT event of format %u (%s)", (guint) format,
+ gst_format_get_name (format));
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ return TRUE;
+
+seek_failed:
+ {
+ GST_ELEMENT_ERROR (fdsink, RESOURCE, SEEK,
+ (_("Error while seeking in file \"%d\"."), fdsink->fd),
+ GST_ERROR_SYSTEM);
+ return FALSE;
+ }
+
+}
+
/*** GSTURIHANDLER INTERFACE *************************************************/
static GstURIType