[vlc-devel] [RFC 03/10] core: add stream_extractor module type
Thomas Guillem
thomas at gllm.fr
Mon Nov 28 18:12:50 CET 2016
On Mon, Nov 28, 2016, at 03:22, Filip Roséen 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 ) )
Leak of s in the error path here.
> + 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
More information about the vlc-devel
mailing list