vlc | branch: master | Rémi Denis-Courmont <r...@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 _______________________________________________ vlc-commits mailing list vlc-commits@videolan.org https://mailman.videolan.org/listinfo/vlc-commits