fdsink: Block in preroll_wait on unlock
authorOlivier Crête <olivier.crete@collabora.com>
Fri, 4 Nov 2016 22:46:45 +0000 (18:46 -0400)
committerOlivier Crête <olivier.crete@collabora.com>
Wed, 23 Nov 2016 16:58:43 +0000 (11:58 -0500)
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
plugins/elements/gstelements_private.h
plugins/elements/gstfdsink.c
plugins/elements/gstfdsink.h
plugins/elements/gstfilesink.c

index 08855c8..cba04b1 100644 (file)
@@ -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;
 
index 469b3b8..d6a8908 100644 (file)
@@ -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
 
index 47d243e..f4eb100 100644 (file)
@@ -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);
 
index 66a2340..c038ce0 100644 (file)
@@ -62,6 +62,7 @@ struct _GstFdSink {
   guint64 current_pos;
 
   gboolean seekable;
+  gboolean unlock; /* OBJECT LOCK */
 };
 
 struct _GstFdSinkClass {
index 1dfef07..9f0243b 100644 (file)
@@ -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