core: add stream_extractor module type
authorFilip Roséen <filip@atch.se>
Mon, 28 Nov 2016 01:58:29 +0000 (02:58 +0100)
committerThomas Guillem <thomas@gllm.fr>
Tue, 6 Dec 2016 14:57:19 +0000 (15:57 +0100)
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.

Signed-off-by: Thomas Guillem <thomas@gllm.fr>
include/vlc_stream_extractor.h [new file with mode: 0644]
modules/Makefile.am
modules/stream_extractor/Makefile.am [new file with mode: 0644]
src/Makefile.am
src/input/stream_extractor.c [new file with mode: 0644]

diff --git a/include/vlc_stream_extractor.h b/include/vlc_stream_extractor.h
new file mode 100644 (file)
index 0000000..1fe13b4
--- /dev/null
@@ -0,0 +1,96 @@
+/*****************************************************************************
+ * vlc_stream_extractor.h
+ *****************************************************************************
+ * Copyright (C) 2016 VLC authors and VideoLAN
+ *
+ * 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.
+ *****************************************************************************/
+
+#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 */
index a291e33..57dc49c 100644 (file)
@@ -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 (file)
index 0000000..e69de29
index 60f5fac..ccc8dfb 100644 (file)
@@ -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 (file)
index 0000000..523e17e
--- /dev/null
@@ -0,0 +1,196 @@
+/*****************************************************************************
+ * stream_extractor.c
+ *****************************************************************************
+ * Copyright (C) 2016 VLC authors and VideoLAN
+ *
+ * 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.
+ *****************************************************************************/
+
+#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 ) )
+    {
+        stream_CommonDelete( s );
+        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 */