diff --git a/include/vlc_stream_extractor.h b/include/vlc_stream_extractor.h new file mode 100644 index 0000000000..1fe13b49a5 --- /dev/null +++ b/include/vlc_stream_extractor.h @@ -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 */ diff --git a/modules/Makefile.am b/modules/Makefile.am index a291e336bb..57dc49ce58 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 0000000000..e69de29bb2 diff --git a/src/Makefile.am b/src/Makefile.am index 60f5fac505..ccc8dfb0a8 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 0000000000..523e17e087 --- /dev/null +++ b/src/input/stream_extractor.c @@ -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 +#include +#include +#include +#include +#include +#include +#include + +#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 */