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

Filip Roséen filip at atch.se
Mon Nov 28 03:22:22 CET 2016


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



More information about the vlc-devel mailing list