fdsink: make fdsink seekable

Implement the same logic as filesink to implement seeking.

Fixes #578908
This commit is contained in:
Benjamin Gaignard 2009-06-18 10:55:39 +02:00 committed by Wim Taymans
parent bf2c345667
commit 1a6f82f4b0

View file

@ -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