Browse Source

stream_extractor: store and forward volume information

Also propagates missing volume information to directories listing.
Until now it was assumed archives only had direcoty info in the first
volume.
pull/162/head
François Cartegnie 3 years ago
committed by Steve Lhomme
parent
commit
9856c789ec
  1. 12
      include/vlc_stream_extractor.h
  2. 2
      modules/gui/skins2/src/theme_loader.cpp
  3. 2
      modules/lua/libs/stream.c
  4. 30
      src/input/input.c
  5. 30
      src/input/mrl_helpers.h
  6. 57
      src/input/stream_extractor.c

12
include/vlc_stream_extractor.h

@ -64,6 +64,8 @@ typedef struct stream_extractor_t {
int (*pf_control)(struct stream_extractor_t*, int request, va_list args);
/** @} */
char ** volumes;
size_t volumes_count;
char const* identifier; /**< the name of the entity to be extracted */
stream_t* source; /**< the source stream to be consumed */
void* p_sys; /**< private opaque handle to be used by the module */
@ -84,6 +86,8 @@ typedef struct stream_directory_t {
int (*pf_readdir)(struct stream_directory_t*, input_item_node_t* );
/** @} */
char ** volumes;
size_t volumes_count;
stream_t* source; /**< the source stream to be consumed */
void* p_sys; /**< private opaque handle to be used by the module */
@ -146,6 +150,8 @@ VLC_API char* vlc_stream_extractor_CreateMRL( stream_directory_t *extractor,
* \param identifier (if present) NULL or a c-style string referring to the
* desired entity
* \param module_name NULL or an explicit stream-extractor module name
* \param volumes media additional volumes MRLs
* \param volumes_count number of additional volumes
*
* \return VLC_SUCCESS if a stream-extractor was successfully
* attached, an error-code on failure.
@ -155,10 +161,12 @@ VLC_API char* vlc_stream_extractor_CreateMRL( stream_directory_t *extractor,
VLC_API int vlc_stream_extractor_Attach( stream_t** source,
char const* identifier,
char const* module_name );
char const* module_name,
const char **volumes, size_t volumes_count );
VLC_API int vlc_stream_directory_Attach( stream_t** source,
char const* module_name );
char const* module_name,
const char **volumes, size_t volumes_count );
/**
* @}
*/

2
modules/gui/skins2/src/theme_loader.cpp

@ -227,7 +227,7 @@ bool ThemeLoader::unarchive( const std::string& fileName, const std::string &tem
}
stream_t* stream = input.get();
if( vlc_stream_directory_Attach( &stream, NULL ) )
if( vlc_stream_directory_Attach( &stream, NULL, NULL, 0 ) )
{
msg_Err( getIntf(), "unable to attach stream_directory, treat as XML!" );
}

2
modules/lua/libs/stream.c

@ -110,7 +110,7 @@ static int vlclua_directory_stream_new( lua_State *L )
stream_t *p_stream = vlc_stream_NewURL( p_this, psz_url );
if( !p_stream )
return vlclua_error( L );
if( vlc_stream_directory_Attach( &p_stream, NULL ) != VLC_SUCCESS )
if( vlc_stream_directory_Attach( &p_stream, NULL, NULL, 0 ) != VLC_SUCCESS )
{
vlc_stream_Delete( p_stream );
return vlclua_error( L );

30
src/input/input.c

@ -2552,7 +2552,9 @@ InputStreamHandleAnchor( input_thread_t *p_input, input_source_t *source,
return VLC_EGENERIC;
}
if( vlc_stream_directory_Attach( stream, NULL ) )
if( vlc_stream_directory_Attach( stream, NULL,
(const char **) mrli.volumes.pp_elems,
mrli.volumes.i_count ) )
msg_Dbg( p_input, "attachment of directory-extractor failed for %s",
(*stream)->psz_url );
@ -2701,6 +2703,7 @@ static int InputSourceInit( input_source_t *in, input_thread_t *p_input,
}
}
char *psz_newanchor = NULL;
if( strcasecmp( psz_access, "concat" ) )
{ /* Autodetect extra files if none specified */
int count;
@ -2708,28 +2711,16 @@ static int InputSourceInit( input_source_t *in, input_thread_t *p_input,
TAB_INIT( count, tab );
InputGetExtraFiles( p_input, &count, &tab, &psz_access, psz_mrl );
if( count > 0 )
{
char *list = NULL;
for( int i = 0; i < count; i++ )
{
char *str;
if( asprintf( &str, "%s,%s", list ? list : psz_mrl,
tab[i] ) < 0 )
break;
free( tab[i] );
free( list );
list = str;
}
var_Create( p_input, "concat-list", VLC_VAR_STRING );
if( likely(list != NULL) )
char *psz = mrl_AppendAnchorFragment( psz_newanchor ? psz_newanchor : psz_anchor, tab[i] );
if( psz )
{
var_SetString( p_input, "concat-list", list );
free( list );
free( psz_newanchor );
psz_newanchor = psz;
}
free( tab[i] );
}
TAB_CLEAN( count, tab );
}
@ -2746,12 +2737,13 @@ static int InputSourceInit( input_source_t *in, input_thread_t *p_input,
if( es_out )
in->p_demux = InputDemuxNew( p_input, es_out, in, url,
psz_demux, psz_anchor );
psz_demux, psz_newanchor ? psz_newanchor : psz_anchor );
free( url );
}
else
in->p_demux = NULL;
free( psz_newanchor );
free( psz_demux_var );
free( psz_dup );

30
src/input/mrl_helpers.h

@ -89,6 +89,36 @@ mrl_EscapeFragmentIdentifier( char const* payload )
return mstream.ptr;
}
static inline char *
mrl_AppendAnchorFragment( const char *anchor, char const *payload )
{
struct vlc_memstream mstream;
if( vlc_memstream_open( &mstream ) )
return NULL;
if( anchor )
vlc_memstream_puts( &mstream, anchor );
else
vlc_memstream_putc( &mstream, '#' );
char *escaped = mrl_EscapeFragmentIdentifier( payload );
if( escaped == NULL )
{
if( !vlc_memstream_close( &mstream ) )
free( mstream.ptr );
return NULL;
}
vlc_memstream_puts( &mstream, "!+" );
vlc_memstream_puts( &mstream, escaped );
free( escaped );
if( vlc_memstream_close( &mstream ) )
return NULL;
return mstream.ptr;
}
struct mrl_info
{
vlc_array_t identifiers;

57
src/input/stream_extractor.c

@ -218,7 +218,8 @@ se_InitStream( struct stream_extractor_private* priv, stream_t* s )
s->pf_control = se_StreamControl;
s->psz_url = StreamExtractorCreateMRL( priv->extractor.source->psz_url,
priv->extractor.identifier,
NULL, 0 );
(char const **) priv->extractor.volumes,
priv->extractor.volumes_count );
if( unlikely( !s->psz_url ) )
return VLC_ENOMEM;
@ -226,9 +227,20 @@ se_InitStream( struct stream_extractor_private* priv, stream_t* s )
}
static void
se_CleanStream( struct stream_extractor_private* priv )
se_CleanStreamExtractor( struct stream_extractor_private* priv )
{
free( (char*)priv->extractor.identifier );
for( size_t i=0; i<priv->extractor.volumes_count; i++ )
free( priv->extractor.volumes[i] );
free( priv->extractor.volumes );
}
static void
se_CleanStreamDirectory( struct stream_extractor_private* priv )
{
for( size_t i=0; i<priv->directory.volumes_count; i++ )
free( priv->directory.volumes[i] );
free( priv->directory.volumes );
}
static int
@ -288,7 +300,7 @@ se_AttachWrapper( struct stream_extractor_private* priv, stream_t* source )
static int
StreamExtractorAttach( stream_t** source, char const* identifier,
char const* module_name )
char const* module_name, const char **volumes, size_t volumes_count )
{
const bool extractor = identifier != NULL;
char const* capability = extractor ? "stream_extractor"
@ -300,27 +312,49 @@ StreamExtractorAttach( stream_t** source, char const* identifier,
if( unlikely( !priv ) )
return VLC_ENOMEM;
char ***dst_volumes;
size_t * dst_volumes_count;
if( extractor )
{
priv->object = VLC_OBJECT( &priv->extractor );
priv->pf_init = se_InitStream;
priv->pf_clean = se_CleanStream;
priv->pf_clean = se_CleanStreamExtractor;
priv->extractor.source = *source;
priv->extractor.identifier = strdup( identifier );
if( unlikely( !priv->extractor.identifier ) )
goto error;
dst_volumes = &priv->extractor.volumes;
dst_volumes_count = &priv->extractor.volumes_count;
}
else
{
priv->object = VLC_OBJECT( &priv->directory );
priv->pf_init = se_InitDirectory;
priv->pf_clean = NULL;
priv->pf_clean = se_CleanStreamDirectory;
priv->directory.source = *source;
dst_volumes = &priv->directory.volumes;
dst_volumes_count = &priv->directory.volumes_count;
}
if( volumes_count )
{
*dst_volumes = malloc(volumes_count * sizeof(char *));
if( unlikely(!*dst_volumes) )
goto error;
for( *dst_volumes_count=0; *dst_volumes_count<volumes_count; (*dst_volumes_count)++ )
{
(*dst_volumes)[*dst_volumes_count] = strdup(volumes[*dst_volumes_count]);
if( unlikely(!(*dst_volumes)[*dst_volumes_count]) )
goto error;
}
}
priv->module = module_need( priv->object, capability, module_name, true );
@ -337,16 +371,17 @@ error:
}
int
vlc_stream_directory_Attach( stream_t** source, char const* module_name )
vlc_stream_directory_Attach( stream_t** source, char const* module_name,
const char **volumes, size_t volumes_count )
{
return StreamExtractorAttach( source, NULL, module_name );
return StreamExtractorAttach( source, NULL, module_name, volumes, volumes_count );
}
int
vlc_stream_extractor_Attach( stream_t** source, char const* identifier,
char const* module_name )
char const* module_name, const char **volumes, size_t volumes_count )
{
return StreamExtractorAttach( source, identifier, module_name );
return StreamExtractorAttach( source, identifier, module_name, volumes, volumes_count );
}
int
@ -359,7 +394,9 @@ stream_extractor_AttachParsed( stream_t** source, const struct mrl_info *mrli )
{
char* id = vlc_array_item_at_index( &mrli->identifiers, idx );
if( vlc_stream_extractor_Attach( source, id, NULL ) )
if( vlc_stream_extractor_Attach( source, id, NULL,
(char const **) mrli->volumes.pp_elems,
mrli->volumes.i_count ) )
break;
++idx;

Loading…
Cancel
Save