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

Thomas Guillem thomas at gllm.fr
Mon Nov 28 18:03:42 CET 2016


You forgot to add copyright file headers.

On Mon, Nov 28, 2016, at 12:12, Rémi Denis-Courmont wrote:
> 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
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel


More information about the vlc-devel mailing list