[vlc-devel] [RFC 03/10] core: add stream_extractor module type

Rémi Denis-Courmont remi at remlab.net
Mon Nov 28 12:12:58 CET 2016


On November 28, 2016 4:22:22 AM GMT+02:00, "Filip Roséen" <filip at atch.se> wrote:
>These changes introduces a new module type named stream_extractor. The
>added documentation should explain when such module should be used,
>but in short it allows for extraction of data within a stream,
>effectively resulting in a new stream that refers to the extracted
>data.
>
>Interaction with the stream-extractor shall never happen directly,
>instead the module-backend is written in a way so that it exposes a
>stream_t to the public.
>
>    [ access ] -> [ stream_t ] -> [ stream consumer ]
>                   '- [ stream extractor ]
>
>Future changes are necessary in order to make modules of this type
>usable in practice, but has been split into individual commits so that
>the changes are easier to follow.
>---
> include/vlc_stream_extractor.h       |  76 +++++++++++++++
> modules/Makefile.am                  |   1 +
> modules/stream_extractor/Makefile.am |   0
> src/Makefile.am                      |   2 +
>src/input/stream_extractor.c         | 173
>+++++++++++++++++++++++++++++++++++
> 5 files changed, 252 insertions(+)
> create mode 100644 include/vlc_stream_extractor.h
> create mode 100644 modules/stream_extractor/Makefile.am
> create mode 100644 src/input/stream_extractor.c
>
>diff --git a/include/vlc_stream_extractor.h
>b/include/vlc_stream_extractor.h
>new file mode 100644
>index 0000000..f01dc9b
>--- /dev/null
>+++ b/include/vlc_stream_extractor.h
>@@ -0,0 +1,76 @@
>+#ifndef VLC_STREAM_EXTRACTOR_H
>+#define VLC_STREAM_EXTRACTOR_H
>+
>+#ifdef __cplusplus
>+extern "C" {
>+#endif
>+
>+/**
>+ * \defgroup stream_extractor Stream Extractor
>+ * \ingroup input
>+ *
>+ * If a stream can be viewed as a directory, such as when opening a
>+ * compressed archive, a \em stream-extractor is used to get access to
>+ * the entities inside said stream.
>+ *
>+ * A \em stream-extractor can do one of two things;
>+ *
>+ *  - either it lists the logical entries within a stream, or;
>+ *  - it extracts the data associated with one of those entries based
>+ *    on a unique identifier.
>+ *
>+ * @{
>+ *
>+ **/
>+struct stream_extractor_t {
>+    VLC_COMMON_MEMBERS;
>+
>+    union {
>+        /**
>+         * Callbacks for entity extraction
>+         *
>+         * The following callbacks shall be populated if the
>stream_extractor is
>+         * used to extract a specific entity from the source-stream.
>Each
>+         * callback shall behave as those, with the same name,
>specified in \ref
>+         * stream_t.
>+         *
>+         **/
>+        struct {
>+            ssize_t  (*pf_read)(struct stream_extractor_t *, void
>*buf, size_t len);
>+            block_t* (*pf_block)(struct stream_extractor_t *, bool
>*eof);
>+            int      (*pf_seek)(struct stream_extractor_t *,
>uint64_t);
>+            int      (*pf_control)(struct stream_extractor_t *, int
>i_query, va_list);
>+
>+        } stream;
>+
>+        /**
>+         * Callbacks for stream directory listing
>+         *
>+         * These callbacks are used when a stream is to be treated as
>a
>+         * directory, it shall behave as those, with the same name,
>specified
>+         * in \ref stream_t.
>+         *
>+         **/
>+        struct {
>+            int (*pf_readdir)(struct stream_extractor_t *,
>input_item_node_t *);
>+
>+        } directory;
>+
>+    };
>+
>+    void* p_sys; /**< Private data pointer */
>+    stream_t* source; /**< The source stream */
>+    char* identifier; /**< name of requested entity to extract, or
>NULL
>+                       **  when requested to list directories */
>+};
>+
>+typedef struct stream_extractor_t stream_extractor_t;
>+
>+/**
>+ * @}
>+ */
>+
>+#ifdef __cplusplus
>+} /* extern "C" */
>+#endif
>+#endif /* include-guard */
>diff --git a/modules/Makefile.am b/modules/Makefile.am
>index a291e33..57dc49c 100644
>--- a/modules/Makefile.am
>+++ b/modules/Makefile.am
>@@ -42,6 +42,7 @@ include packetizer/Makefile.am
> include services_discovery/Makefile.am
> include spu/Makefile.am
> include stream_filter/Makefile.am
>+include stream_extractor/Makefile.am
> include text_renderer/Makefile.am
> include video_chroma/Makefile.am
> include video_filter/Makefile.am
>diff --git a/modules/stream_extractor/Makefile.am
>b/modules/stream_extractor/Makefile.am
>new file mode 100644
>index 0000000..e69de29
>diff --git a/src/Makefile.am b/src/Makefile.am
>index 60f5fac..ccc8dfb 100644
>--- a/src/Makefile.am
>+++ b/src/Makefile.am
>@@ -87,6 +87,7 @@ pluginsinclude_HEADERS = \
> 	../include/vlc_sout.h \
> 	../include/vlc_spu.h \
> 	../include/vlc_stream.h \
>+	../include/vlc_stream_extractor.h \
> 	../include/vlc_strings.h \
> 	../include/vlc_subpicture.h \
> 	../include/vlc_text_style.h \
>@@ -257,6 +258,7 @@ libvlccore_la_SOURCES = \
> 	input/stats.c \
> 	input/stream.c \
> 	input/stream_fifo.c \
>+	input/stream_extractor.c \
> 	input/stream_filter.c \
> 	input/stream_memory.c \
> 	input/subtitles.c \
>diff --git a/src/input/stream_extractor.c
>b/src/input/stream_extractor.c
>new file mode 100644
>index 0000000..a926363
>--- /dev/null
>+++ b/src/input/stream_extractor.c
>@@ -0,0 +1,173 @@
>+#ifndef STREAM_EXTRACTOR_H
>+#define STREAM_EXTRACTOR_H
>+
>+#ifdef HAVE_CONFIG_H
>+#  include "config.h"
>+#endif
>+
>+#include <vlc_common.h>
>+#include <vlc_stream.h>
>+#include <vlc_stream_extractor.h>
>+#include <vlc_modules.h>
>+#include <vlc_url.h>
>+#include <vlc_memstream.h>
>+#include <libvlc.h>
>+#include <assert.h>
>+
>+#include "stream.h"
>+
>+/**
>+ * \defgroup stream_extractor_Private Stream Extractor Private
>+ * \ingroup stream_extractor
>+ * \internal
>+ * @{
>+ * \file
>+ **/
>+
>+struct stream_extractor_private {
>+    stream_extractor_t public;
>+    stream_t* stream;
>+    module_t* module;
>+
>+    vlc_object_t* owner;
>+};
>+
>+/**
>+ * Release the private data associated with a stream-extractor
>+ *
>+ * \param priv pointer to the private section
>+ */
>+static void se_Release( struct stream_extractor_private* priv )
>+{
>+    free( priv->public.identifier );
>+
>+    if( priv->module )
>+    {
>+        module_unneed( &priv->public, priv->module );
>+        vlc_stream_Delete( priv->public.source );
>+    }
>+
>+    vlc_object_release( &priv->public );
>+}
>+
>+/**
>+ * \defgroup stream_extractor_Callbacks Stream Extractor Callbacks
>+ * \ingroup stream_extractor
>+ * @{
>+ *   \file
>+ *   These functions simply forwards the relevant stream-request to
>+ *   the underlying stream-extractor. They are a basic form of
>+ *   type-erasure in that the outside world sees a stream_t, but the
>+ *   work is actually done by a stream_extractor_t.
>+ */
>+
>+static void
>+se_StreamDelete( stream_t* stream )
>+{
>+    se_Release( stream->p_sys );
>+}
>+
>+static ssize_t
>+se_StreamRead( stream_t* stream, void* buf, size_t len )
>+{
>+    struct stream_extractor_private* priv = stream->p_sys;
>+    stream_extractor_t* extractor = &priv->public;
>+    return extractor->stream.pf_read( extractor, buf, len );
>+}
>+
>+static block_t*
>+se_StreamBlock( stream_t* stream, bool* eof )
>+{
>+    struct stream_extractor_private* priv = stream->p_sys;
>+    stream_extractor_t* extractor = &priv->public;
>+    return extractor->stream.pf_block( extractor, eof );
>+}
>+
>+static int
>+se_StreamSeek( stream_t* stream, uint64_t offset )
>+{
>+    struct stream_extractor_private* priv = stream->p_sys;
>+    stream_extractor_t* extractor = &priv->public;
>+    return extractor->stream.pf_seek( extractor, offset );
>+}
>+
>+static int
>+se_StreamReadDir( stream_t* stream, input_item_node_t* node )
>+{
>+    struct stream_extractor_private* priv = stream->p_sys;
>+    stream_extractor_t* extractor = &priv->public;
>+    return extractor->directory.pf_readdir( extractor, node );
>+}
>+
>+static int
>+se_StreamControl( stream_t* stream, int req, va_list args )
>+{
>+    struct stream_extractor_private* priv = stream->p_sys;
>+    stream_extractor_t* extractor = &priv->public;
>+
>+    if( extractor->identifier )
>+        return extractor->stream.pf_control( extractor, req, args );
>+
>+    if( req ==  STREAM_IS_DIRECTORY )
>+    {
>+        *va_arg( args, bool* ) = true;
>+        return VLC_SUCCESS;
>+    }
>+
>+    return VLC_EGENERIC;
>+}
>+/**
>+ * @}
>+ **/
>+
>+/**
>+ * Initialize the public stream_t for a stream_extractor_t
>+ *
>+ * This function simply initializes the relevant data-members of the
>+ * public stream_t which is a handle to the internal
>+ * stream_extractor_t.
>+ *
>+ * \param obj the private section of the stream_extractor_t
>+ * \param source the source stream which the stream_extractor_t should
>+ *        will read from
>+ * \return VLC_SUCCESS on success, an error-code on failure.
>+ **/
>+static int
>+se_InitStream( struct stream_extractor_private* priv, stream_t* source
>)
>+{
>+    stream_t* s = vlc_stream_CommonNew( priv->public.obj.parent,
>+                                        se_StreamDelete );
>+    if( unlikely( !s ) )
>+        return VLC_EGENERIC;
>+
>+    if( priv->public.identifier )
>+    {
>+        if( priv->public.stream.pf_read ) s->pf_read = se_StreamRead;
>+        else                              s->pf_block =
>se_StreamBlock;
>+
>+        s->pf_seek = se_StreamSeek;
>+        s->psz_url = NULL;
>+    }
>+    else
>+    {
>+        s->pf_readdir = se_StreamReadDir;
>+        s->psz_url = source->psz_url ? strdup( source->psz_url ) :
>NULL;
>+    }
>+
>+
>+    if( source->psz_url && unlikely( !s->psz_url ) )
>+        return VLC_EGENERIC;
>+
>+    priv->stream = s;
>+    priv->stream->pf_control = se_StreamControl;
>+    priv->stream->p_input = source->p_input;
>+    priv->stream->p_sys = priv;
>+
>+    return VLC_SUCCESS;
>+}
>+
>+/**
>+ * @}
>+ **/
>+
>+#endif /* include-guard */
>-- 
>2.10.2
>
>_______________________________________________
>vlc-devel mailing list
>To unsubscribe or modify your subscription options:
>https://mailman.videolan.org/listinfo/vlc-devel

VLC already relies on anonymous unions (nominally a C11 feature, but supported by compilers for a long time). Don't feel obliged to name them.
-- 
Rémi Denis-Courmont


More information about the vlc-devel mailing list