[vlc-commits] input: add FIFO stream type

Rémi Denis-Courmont git at videolan.org
Thu Jun 30 20:28:24 CEST 2016


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Thu Jun 30 20:05:55 2016 +0300| [59f33100902c13c58e8bf02367acc8aa99d9870e] | committer: Rémi Denis-Courmont

input: add FIFO stream type

This provides an anonymous pipe as a stream_t. The read side is a
normal non-seekable stream_t. The write side uses dedicated functions.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=59f33100902c13c58e8bf02367acc8aa99d9870e
---

 include/vlc_stream.h    |   61 +++++++++++++
 src/Makefile.am         |    1 +
 src/input/stream_fifo.c |  216 +++++++++++++++++++++++++++++++++++++++++++++++
 src/libvlccore.sym      |    4 +
 4 files changed, 282 insertions(+)

diff --git a/include/vlc_stream.h b/include/vlc_stream.h
index 06df123..b2f0f0c 100644
--- a/include/vlc_stream.h
+++ b/include/vlc_stream.h
@@ -237,6 +237,67 @@ VLC_API stream_t * stream_MemoryNew(vlc_object_t *p_obj, uint8_t *p_buffer, uint
 VLC_API stream_t * stream_UrlNew(vlc_object_t *p_this, const char *psz_url );
 #define stream_UrlNew( a, b ) stream_UrlNew( VLC_OBJECT(a), b )
 
+/**
+ * \defgroup stream_fifo FIFO stream
+ * In-memory anonymous pipe
+  @{
+ */
+
+/**
+ * Creates a FIFO stream.
+ *
+ * Creates a non-seekable byte stream object whose byte stream is generated
+ * by another thread in the process. This is the LibVLC equivalent of an
+ * anonymous pipe/FIFO.
+ *
+ * On the reader side, the normal stream functions are used,
+ * e.g. stream_Read() and stream_Delete().
+ *
+ * The created stream object is automatically destroyed when both the reader
+ * and the writer sides have been closed, with stream_Delete() and
+ * vlc_stream_fifo_Close() respectively.
+ *
+ * \param parent parent VLC object for the stream
+ * \return a stream object or NULL on memory error.
+ */
+VLC_API stream_t *vlc_stream_fifo_New(vlc_object_t *parent);
+
+/**
+ * Writes a block to a FIFO stream.
+ *
+ * \param s FIFO stream created by vlc_stream_fifo_New()
+ * \param block data block to write to the stream
+ * \return 0 on success. -1 if the reader end has already been closed
+ * (errno is then set to EPIPE, and the block is deleted).
+ *
+ * \bug No congestion control is performed. If the reader end is not keeping
+ * up with the writer end, buffers will accumulate in memory.
+ */
+VLC_API int vlc_stream_fifo_Queue(stream_t *s, block_t *block);
+
+/**
+ * Writes data to a FIFO stream.
+ *
+ * This is a convenience helper for vlc_stream_fifo_Queue().
+ * \param s FIFO stream created by vlc_stream_fifo_New()
+ * \param buf start address of data to write
+ * \param len length of data to write in bytes
+ * \return len on success, or -1 on error (errno is set accordingly)
+ */
+VLC_API ssize_t vlc_stream_fifo_Write(stream_t *s, const void *buf,
+                                      size_t len);
+
+/**
+ * Terminates a FIFO stream.
+ *
+ * Marks the end of the FIFO stream and releases any underlying resources.
+ * \param s FIFO stream created by vlc_stream_fifo_New()
+ */
+VLC_API void vlc_stream_fifo_Close(stream_t *s);
+
+/**
+ * @}
+ */
 
 /**
  * Try to add a stream filter to an open stream.
diff --git a/src/Makefile.am b/src/Makefile.am
index e825fb4..2720564 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -381,6 +381,7 @@ SOURCES_libvlc_common = \
 	input/stats.c \
 	input/stream.c \
 	input/stream_demux.c \
+	input/stream_fifo.c \
 	input/stream_filter.c \
 	input/stream_memory.c \
 	input/subtitles.c \
diff --git a/src/input/stream_fifo.c b/src/input/stream_fifo.c
new file mode 100644
index 0000000..f468bd1
--- /dev/null
+++ b/src/input/stream_fifo.c
@@ -0,0 +1,216 @@
+/*****************************************************************************
+ * stream_fifo.c
+ *****************************************************************************
+ * Copyright (C) 2016 Rémi Denis-Courmont
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <vlc_common.h>
+#include <vlc_block.h>
+#include <vlc_stream.h>
+
+#include "stream.h"
+
+struct stream_sys_t
+{
+    vlc_fifo_t *fifo;
+    block_t *block;
+    bool eof;
+};
+
+static void vlc_stream_fifo_Destroy(stream_t *s)
+{
+    stream_sys_t *sys = s->p_sys;
+    vlc_fifo_t *fifo = sys->fifo;
+    block_t *block;
+    bool closed;
+
+    if (sys->block != NULL)
+        block_Release(sys->block);
+
+    vlc_fifo_Lock(fifo);
+    block = vlc_fifo_DequeueAllUnlocked(fifo);
+    closed = sys->eof;
+    sys->eof = true;
+    vlc_fifo_Unlock(fifo);
+
+    block_ChainRelease(block);
+
+    if (closed)
+    {   /* Destroy shared state if write end is already closed */
+        block_FifoRelease(fifo);
+        free(sys);
+    }
+}
+
+static ssize_t vlc_stream_fifo_Read(stream_t *s, void *buf, size_t len)
+{
+    stream_sys_t *sys = s->p_sys;
+    block_t *block = sys->block;
+
+    while (block == NULL)
+    {
+        vlc_fifo_t *fifo = sys->fifo;
+
+        vlc_fifo_Lock(fifo);
+        while (vlc_fifo_IsEmpty(fifo))
+        {
+            if (sys->eof)
+            {
+                vlc_fifo_Unlock(fifo);
+                return 0;
+            }
+            vlc_fifo_Wait(fifo);
+        }
+        block = vlc_fifo_DequeueUnlocked(fifo);
+        vlc_fifo_Unlock(fifo);
+        assert(block != NULL);
+    }
+
+    if (len > block->i_buffer)
+        len = block->i_buffer;
+
+    if (likely(len > 0))
+        memcpy(buf, block->p_buffer, len);
+
+    block->p_buffer += len;
+    block->i_buffer -= len;
+
+    if (block->i_buffer == 0)
+    {
+        block_Release(block);
+        block = NULL;
+    }
+
+    sys->block = block;
+    return len;
+}
+
+static int vlc_stream_fifo_Control(stream_t *s, int query, va_list ap)
+{
+    (void) s;
+
+    switch (query)
+    {
+        case STREAM_CAN_SEEK:
+        case STREAM_CAN_FASTSEEK:
+        case STREAM_CAN_PAUSE:
+        case STREAM_CAN_CONTROL_PACE:
+            *va_arg(ap, bool *) = false;
+            break;
+
+        case STREAM_GET_PTS_DELAY:
+            *va_arg(ap, int64_t *) = DEFAULT_PTS_DELAY;
+            break;
+
+        default:
+            return VLC_EGENERIC;
+    }
+    return VLC_SUCCESS;
+}
+
+stream_t *vlc_stream_fifo_New(vlc_object_t *parent)
+{
+    stream_sys_t *sys = malloc(sizeof (*sys));
+    if (unlikely(sys == NULL))
+        return NULL;
+
+    sys->fifo = block_FifoNew();
+    if (unlikely(sys->fifo == NULL))
+    {
+        free(sys);
+        return NULL;
+    }
+
+    sys->block = NULL;
+    sys->eof = false;
+
+    stream_t *s = stream_CommonNew(parent, vlc_stream_fifo_Destroy);
+    if (unlikely(s == NULL))
+    {
+        block_FifoRelease(sys->fifo);
+        free(sys);
+        return NULL;
+    }
+
+    s->pf_read = vlc_stream_fifo_Read;
+    s->pf_seek = NULL;
+    s->pf_control= vlc_stream_fifo_Control;
+    s->p_sys = sys;
+    return vlc_object_hold(s);
+}
+
+int vlc_stream_fifo_Queue(stream_t *s, block_t *block)
+{
+    stream_sys_t *sys = s->p_sys;
+    vlc_fifo_t *fifo = sys->fifo;
+
+    vlc_fifo_Lock(fifo);
+    if (likely(!sys->eof))
+    {
+        vlc_fifo_QueueUnlocked(fifo, block);
+        block = NULL;
+    }
+    vlc_fifo_Unlock(fifo);
+
+    if (unlikely(block != NULL))
+    {
+        block_Release(block);
+        errno = EPIPE;
+        return -1;
+    }
+    return 0;
+}
+
+ssize_t vlc_stream_fifo_Write(stream_t *s, const void *buf, size_t len)
+{
+    block_t *block = block_Alloc(len);
+    if (unlikely(block == NULL))
+        return -1;
+
+    memcpy(block->p_buffer, buf, len);
+    return vlc_stream_fifo_Queue(s, block) ? -1 : (ssize_t)len;
+}
+
+void vlc_stream_fifo_Close(stream_t *s)
+{
+    stream_sys_t *sys = s->p_sys;
+    vlc_fifo_t *fifo = sys->fifo;
+    bool closed;
+
+    vlc_fifo_Lock(fifo);
+    closed = sys->eof;
+    sys->eof = true;
+    vlc_fifo_Signal(fifo);
+    vlc_fifo_Unlock(fifo);
+
+    if (closed)
+    {   /* Destroy shared state if read end is already closed */
+        block_FifoRelease(fifo);
+        free(sys);
+    }
+
+    vlc_object_release(s);
+}
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index 6000b17..c2f270b 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -412,6 +412,10 @@ stream_UrlNew
 stream_vaControl
 stream_ReadDir
 stream_FilterDefaultReadDir
+vlc_stream_fifo_New
+vlc_stream_fifo_Queue
+vlc_stream_fifo_Write
+vlc_stream_fifo_Close
 vlc_strfinput
 vlc_strftime
 subpicture_Delete



More information about the vlc-commits mailing list