From 5216322d39448ed61c86bb1b3dd9c8c5e6feccf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Fri, 4 Nov 2016 18:46:45 -0400 Subject: [PATCH] fdsink: Block in preroll_wait on unlock The correct behaviour of anything stuck in the ->render() function between ->unlock() and ->unlock_stop() is to call gst_base_sink_wait_preroll() and only return an error if this returns an error, otherwise, it must continue where it left off! https://bugzilla.gnome.org/show_bug.cgi?id=773912 --- plugins/elements/gstelements_private.c | 17 +++++++++++----- plugins/elements/gstelements_private.h | 2 +- plugins/elements/gstfdsink.c | 27 +++++++++++++++++++++++--- plugins/elements/gstfdsink.h | 1 + plugins/elements/gstfilesink.c | 2 +- 5 files changed, 39 insertions(+), 10 deletions(-) diff --git a/plugins/elements/gstelements_private.c b/plugins/elements/gstelements_private.c index 08855c8623..cba04b1b7f 100644 --- a/plugins/elements/gstelements_private.c +++ b/plugins/elements/gstelements_private.c @@ -193,7 +193,7 @@ fill_vectors (struct iovec *vecs, GstMapInfo * maps, guint n, GstBuffer * buf) GstFlowReturn gst_writev_buffers (GstObject * sink, gint fd, GstPoll * fdset, GstBuffer ** buffers, guint num_buffers, guint8 * mem_nums, - guint total_mem_num, guint64 * total_written, guint64 * cur_pos) + guint total_mem_num, guint64 * bytes_written, guint64 skip) { struct iovec *vecs; GstMapInfo *map_infos; @@ -218,6 +218,13 @@ gst_writev_buffers (GstObject * sink, gint fd, GstPoll * fdset, guint n_vecs = total_mem_num; left = size; + + if (skip) { + ret = skip; + errno = 0; + goto skip_first; + } + do { #ifndef HAVE_WIN32 if (fdset != NULL) { @@ -239,12 +246,12 @@ gst_writev_buffers (GstObject * sink, gint fd, GstPoll * fdset, ret = gst_writev (fd, vecs, n_vecs, left); if (ret > 0) { - if (total_written) - *total_written += ret; - if (cur_pos) - *cur_pos += ret; + if (bytes_written) + *bytes_written += ret; } + skip_first: + if (ret == left) break; diff --git a/plugins/elements/gstelements_private.h b/plugins/elements/gstelements_private.h index 469b3b83c2..d6a89081f1 100644 --- a/plugins/elements/gstelements_private.h +++ b/plugins/elements/gstelements_private.h @@ -34,7 +34,7 @@ G_GNUC_INTERNAL GstFlowReturn gst_writev_buffers (GstObject * sink, gint fd, GstPoll * fdset, GstBuffer ** buffers, guint num_buffers, guint8 * mem_nums, guint total_mem_num, - guint64 * total_written, guint64 * cur_pos); + guint64 * bytes_written, guint64 skip); G_END_DECLS diff --git a/plugins/elements/gstfdsink.c b/plugins/elements/gstfdsink.c index 47d243e45f..f4eb100735 100644 --- a/plugins/elements/gstfdsink.c +++ b/plugins/elements/gstfdsink.c @@ -243,9 +243,28 @@ static GstFlowReturn gst_fd_sink_render_buffers (GstFdSink * sink, GstBuffer ** buffers, guint num_buffers, guint8 * mem_nums, guint total_mems) { - return gst_writev_buffers (GST_OBJECT_CAST (sink), sink->fd, sink->fdset, - buffers, num_buffers, mem_nums, total_mems, &sink->bytes_written, - &sink->current_pos); + GstFlowReturn ret; + guint64 skip = 0; + + for (;;) { + guint64 bytes_written = 0; + + ret = gst_writev_buffers (GST_OBJECT_CAST (sink), sink->fd, sink->fdset, + buffers, num_buffers, mem_nums, total_mems, &bytes_written, skip); + + sink->bytes_written += bytes_written; + sink->current_pos += bytes_written; + skip += bytes_written; + + if (!sink->unlock) + break; + + ret = gst_base_sink_wait_preroll (GST_BASE_SINK (sink)); + if (ret != GST_FLOW_OK) + return ret; + } + + return ret; } static GstFlowReturn @@ -403,6 +422,7 @@ gst_fd_sink_unlock (GstBaseSink * basesink) GST_LOG_OBJECT (fdsink, "Flushing"); GST_OBJECT_LOCK (fdsink); + fdsink->unlock = TRUE; gst_poll_set_flushing (fdsink->fdset, TRUE); GST_OBJECT_UNLOCK (fdsink); @@ -416,6 +436,7 @@ gst_fd_sink_unlock_stop (GstBaseSink * basesink) GST_LOG_OBJECT (fdsink, "No longer flushing"); GST_OBJECT_LOCK (fdsink); + fdsink->unlock = FALSE; gst_poll_set_flushing (fdsink->fdset, FALSE); GST_OBJECT_UNLOCK (fdsink); diff --git a/plugins/elements/gstfdsink.h b/plugins/elements/gstfdsink.h index 66a234093d..c038ce07b1 100644 --- a/plugins/elements/gstfdsink.h +++ b/plugins/elements/gstfdsink.h @@ -62,6 +62,7 @@ struct _GstFdSink { guint64 current_pos; gboolean seekable; + gboolean unlock; /* OBJECT LOCK */ }; struct _GstFdSinkClass { diff --git a/plugins/elements/gstfilesink.c b/plugins/elements/gstfilesink.c index 1dfef07a2c..9f0243bd71 100644 --- a/plugins/elements/gstfilesink.c +++ b/plugins/elements/gstfilesink.c @@ -662,7 +662,7 @@ gst_file_sink_render_buffers (GstFileSink * sink, GstBuffer ** buffers, num_buffers, total_mems, sink->current_pos); return gst_writev_buffers (GST_OBJECT_CAST (sink), fileno (sink->file), NULL, - buffers, num_buffers, mem_nums, total_mems, NULL, &sink->current_pos); + buffers, num_buffers, mem_nums, total_mems, &sink->current_pos, 0); } static GstFlowReturn