mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-07 20:31:20 +00:00
fdsink: make fdsink seekable
Implement the same logic as filesink to implement seeking. Fixes #578908
This commit is contained in:
parent
bf2c345667
commit
1a6f82f4b0
1 changed files with 89 additions and 3 deletions
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue