demux: avi: PTSToByte remove useless casts and change type
[vlc.git] / src / input / stream_extractor.c
blobe32d73e968a08a0136ee3d3d9fc1071e2761ce2b
1 /*****************************************************************************
2 * stream_extractor.c
3 *****************************************************************************
4 * Copyright (C) 2016 VLC authors and VideoLAN
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
21 #ifndef STREAM_EXTRACTOR_H
22 #define STREAM_EXTRACTOR_H
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
28 #include <vlc_common.h>
29 #include <vlc_stream.h>
30 #include <vlc_stream_extractor.h>
31 #include <vlc_modules.h>
32 #include <vlc_url.h>
33 #include <vlc_memstream.h>
34 #include <libvlc.h>
35 #include <assert.h>
37 #include "stream.h"
38 #include "mrl_helpers.h"
40 /**
41 * \defgroup stream_extractor_Internals Stream Extractor Internals
42 * \ingroup stream_extractor
43 * \internal
44 * @{
45 * \file
46 **/
48 struct stream_extractor_private {
49 union {
50 stream_extractor_t extractor;
51 stream_directory_t directory;
54 /**
55 * Callback to handle initialization
57 * \ref pf_init will be called after successful module probing to initialize
58 * the relevant members of the underlying stream-extractor object, as well
59 * as the wrapping stream.
60 **/
61 int (*pf_init)( struct stream_extractor_private*, stream_t* );
63 /**
64 * Callback to handle clean-up
66 * \ref pf_clean, unless NULL, will be called when the stream-extractor is to
67 * be destroyed, and shall be used to clean-up resources (acquired during
68 * initialization, see \ref pf_init).
70 void (*pf_clean)( struct stream_extractor_private* );
72 stream_t* wrapper; /**< the wrapping \ref stream_t used to access the
73 underlying stream-extractor */
75 stream_t* source; /**< the source stream consumed by the stream-extractor */
76 module_t* module; /**< the stream-extractor module */
78 vlc_object_t* object; /**< the underlying stream-extractor object */
81 /**
82 * Create an MRL for a specific sub-entry
84 * This internal function is used to create an MRL that refers to \subentry
85 * within \ref base, see \ref mrl_helpers for further information.
86 **/
88 static char*
89 StreamExtractorCreateMRL( char const* base, char const* subentry )
91 struct vlc_memstream buffer;
92 char* escaped;
94 if( mrl_EscapeFragmentIdentifier( &escaped, subentry ) )
95 return NULL;
97 if( vlc_memstream_open( &buffer ) )
99 free( escaped );
100 return NULL;
103 vlc_memstream_puts( &buffer, base );
105 if( !strstr( base, "#" ) )
106 vlc_memstream_putc( &buffer, '#' );
108 vlc_memstream_printf( &buffer, "!/%s", escaped );
110 free( escaped );
111 return vlc_memstream_close( &buffer ) ? NULL : buffer.ptr;
115 * Release the private data associated with a stream-extractor
116 * \param priv pointer to the private section
118 static void se_Release( struct stream_extractor_private* priv )
120 if( priv->pf_clean )
121 priv->pf_clean( priv );
123 if( priv->module )
125 module_unneed( priv->object, priv->module );
127 if( priv->source )
128 vlc_stream_Delete( priv->source );
131 vlc_object_release( priv->object );
135 * \name Callbacks to forward work to the underlying stream-extractor
137 * @{
140 static void
141 se_StreamDelete( stream_t* stream )
143 se_Release( stream->p_sys );
146 static ssize_t
147 se_StreamRead( stream_t* stream, void* buf, size_t len )
149 struct stream_extractor_private* priv = stream->p_sys;
150 return priv->extractor.pf_read( &priv->extractor, buf, len );
153 static block_t*
154 se_StreamBlock( stream_t* stream, bool* eof )
156 struct stream_extractor_private* priv = stream->p_sys;
157 return priv->extractor.pf_block( &priv->extractor, eof );
160 static int
161 se_StreamSeek( stream_t* stream, uint64_t offset )
163 struct stream_extractor_private* priv = stream->p_sys;
164 return priv->extractor.pf_seek( &priv->extractor, offset );
167 static int
168 se_ReadDir( stream_t* stream, input_item_node_t* node )
170 struct stream_extractor_private* priv = stream->p_sys;
171 return priv->directory.pf_readdir( &priv->directory, node );
174 static int
175 se_StreamControl( stream_t* stream, int req, va_list args )
177 struct stream_extractor_private* priv = stream->p_sys;
178 return priv->extractor.pf_control( &priv->extractor, req, args );
181 static int
182 se_DirControl( stream_t* stream, int req, va_list args )
184 (void)stream;
185 (void)args;
187 if( req == STREAM_IS_DIRECTORY )
188 return VLC_SUCCESS;
190 return VLC_EGENERIC;
194 * @}
198 * \name stream-extractor resource handlers
199 * \ingroup stream_extractor
200 * @{
203 static int
204 se_InitStream( struct stream_extractor_private* priv, stream_t* s )
206 if( priv->extractor.pf_read ) s->pf_read = se_StreamRead;
207 else s->pf_block = se_StreamBlock;
209 s->pf_seek = se_StreamSeek;
210 s->pf_control = se_StreamControl;
211 s->psz_url = StreamExtractorCreateMRL( priv->extractor.source->psz_url,
212 priv->extractor.identifier );
213 if( unlikely( !s->psz_url ) )
214 return VLC_ENOMEM;
216 return VLC_SUCCESS;
219 static void
220 se_CleanStream( struct stream_extractor_private* priv )
222 free( (char*)priv->extractor.identifier );
225 static int
226 se_InitDirectory( struct stream_extractor_private* priv, stream_t* s )
228 stream_directory_t* directory = &priv->directory;
230 s->pf_readdir = se_ReadDir;
231 s->pf_control = se_DirControl;
232 s->psz_url = strdup( directory->source->psz_url );
234 if( unlikely( !s->psz_url ) )
235 return VLC_EGENERIC;
237 return VLC_SUCCESS;
241 * @}
245 * Create the public stream_t that wraps a stream-extractor
247 * This initializes the relevant data-members of the public stream_t which is
248 * used to read from the underlying stream-extractor.
250 * \param priv the private section of the stream_extractor_t
251 * \param source the source stream which the stream_extractor_t should
252 * will read from
253 * \return VLC_SUCCESS on success, an error-code on failure.
255 static int
256 se_AttachWrapper( struct stream_extractor_private* priv, stream_t* source )
258 stream_t* s = vlc_stream_CommonNew( source->obj.parent, se_StreamDelete );
260 if( unlikely( !s ) )
261 return VLC_ENOMEM;
263 if( priv->pf_init( priv, s ) )
265 stream_CommonDelete( s );
266 return VLC_EGENERIC;
269 priv->wrapper = s;
270 priv->wrapper->p_input = source->p_input;
271 priv->wrapper->p_sys = priv;
273 priv->source = source;
275 if( priv->wrapper->pf_read )
276 priv->wrapper = stream_FilterChainNew( priv->wrapper, "cache_read" );
277 else if( priv->wrapper->pf_block )
278 priv->wrapper = stream_FilterChainNew( priv->wrapper, "cache_block" );
280 return VLC_SUCCESS;
283 static int
284 StreamExtractorAttach( stream_t** source, char const* identifier,
285 char const* module_name )
287 const bool extractor = identifier != NULL;
288 char const* capability = extractor ? "stream_extractor"
289 : "stream_directory";
291 struct stream_extractor_private* priv = vlc_custom_create(
292 (*source)->obj.parent, sizeof( *priv ), capability );
294 if( unlikely( !priv ) )
295 return VLC_ENOMEM;
297 if( extractor )
299 priv->object = VLC_OBJECT( &priv->extractor );
301 priv->pf_init = se_InitStream;
302 priv->pf_clean = se_CleanStream;
304 priv->extractor.source = *source;
305 priv->extractor.identifier = strdup( identifier );
307 if( unlikely( !priv->extractor.identifier ) )
308 goto error;
310 else
312 priv->object = VLC_OBJECT( &priv->directory );
314 priv->pf_init = se_InitDirectory;
315 priv->pf_clean = NULL;
317 priv->directory.source = *source;
320 priv->module = module_need( priv->object, capability, module_name, true );
322 if( !priv->module || se_AttachWrapper( priv, *source ) )
323 goto error;
325 *source = priv->wrapper;
326 return VLC_SUCCESS;
328 error:
329 se_Release( priv );
330 return VLC_EGENERIC;
334 vlc_stream_directory_Attach( stream_t** source, char const* module_name )
336 return StreamExtractorAttach( source, NULL, module_name );
340 vlc_stream_extractor_Attach( stream_t** source, char const* identifier,
341 char const* module_name )
343 return StreamExtractorAttach( source, identifier, module_name );
347 stream_extractor_AttachParsed( stream_t** source, char const* data,
348 char const** out_extra )
350 vlc_array_t identifiers;
352 if( mrl_FragmentSplit( &identifiers, out_extra, data ) )
353 return VLC_EGENERIC;
355 size_t count = vlc_array_count( &identifiers );
356 size_t idx = 0;
358 while( idx < count )
360 char* id = vlc_array_item_at_index( &identifiers, idx );
362 if( vlc_stream_extractor_Attach( source, id, NULL ) )
363 break;
365 ++idx;
368 for( size_t i = 0; i < count; ++i )
369 free( vlc_array_item_at_index( &identifiers, i ) );
370 vlc_array_clear( &identifiers );
372 return idx == count ? VLC_SUCCESS : VLC_EGENERIC;
375 char*
376 vlc_stream_extractor_CreateMRL( stream_directory_t* directory,
377 char const* subentry )
379 return StreamExtractorCreateMRL( directory->source->psz_url, subentry );
383 * @}
386 #endif /* include-guard */