[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