diff options
author | Benjamin Gaignard <benjamin at gaignard.net> | 2009-06-18 10:55:39 +0200 |
---|---|---|
committer | Wim Taymans <wim.taymans@collabora.co.uk> | 2009-06-18 10:55:39 +0200 |
commit | 1a6f82f4b01c4f71baf9416c6544426c432dbb9b (patch) | |
tree | e83349895430ada98c1c4d2f3fefddf47e31ab9e /plugins | |
parent | bf2c34566748edff0acd4c0e15a1b656c8c7302e (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.c | 92 |
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 |