Use decoder_GetInputAttachment to get attachment from a decoder module.
You need to release the memory with vlc_input_attachment_Delete.
Untested...
modules/playlist/* cosmetic.
* @}
*/
+VLC_EXPORT( input_attachment_t *, decoder_GetInputAttachment, ( decoder_t *, const char *psz_name ) );
+
#endif /* _VLC_CODEC_H */
typedef struct seekpoint_t seekpoint_t;
typedef struct info_t info_t;
typedef struct info_category_t info_category_t;
+typedef struct input_attachment_t input_attachment_t;
/* Format */
typedef struct audio_format_t audio_format_t;
return dup;
}
+/*****************************************************************************
+ * Attachments
+ *****************************************************************************/
+struct input_attachment_t
+{
+ char *psz_name;
+ char *psz_mime;
+ char *psz_description;
+ int i_data;
+ void *p_data;
+};
+static inline input_attachment_t *vlc_input_attachment_New( const char *psz_name,
+ const char *psz_mime,
+ const char *psz_description,
+ const void *p_data,
+ int i_data )
+{
+ input_attachment_t *a =
+ (input_attachment_t*)malloc( sizeof(input_attachment_t) );
+ if( !a )
+ return NULL;
+ a->psz_name = strdup( psz_name ? psz_name : "" );
+ a->psz_mime = strdup( psz_mime ? psz_mime : "" );
+ a->psz_description = strdup( psz_description ? psz_description : "" );
+ a->i_data = i_data;
+ a->p_data = NULL;
+ if( i_data > 0 )
+ {
+ a->p_data = malloc( i_data );
+ if( a->p_data && p_data )
+ memcpy( a->p_data, p_data, i_data );
+ }
+ return a;
+}
+static inline input_attachment_t *vlc_input_attachment_Duplicate( const input_attachment_t *a )
+{
+ return vlc_input_attachment_New( a->psz_name, a->psz_mime, a->psz_description,
+ a->p_data, a->i_data );
+}
+static inline void vlc_input_attachment_Delete( input_attachment_t *a )
+{
+ if( !a )
+ return;
+ free( a->psz_name );
+ free( a->psz_mime );
+ free( a->psz_description );
+ if( a->p_data )
+ free( a->p_data );
+ free( a );
+}
/*****************************************************************************
* input defines/constants.
*****************************************************************************/
INPUT_DEL_BOOKMARK, /* arg1= seekpoint_t * res=can fail */
INPUT_SET_BOOKMARK, /* arg1= int res=can fail */
+ /* Attachments */
+ INPUT_GET_ATTACHMENTS, /* arg1=input_attachment_t***, arg2=int* res=can fail */
+ INPUT_GET_ATTACHMENT, /* arg1=input_attachment_t**, arg2=char* res=can fail */
+
/* On the fly input slave */
INPUT_ADD_SLAVE /* arg1= char * */
};
#include "ebml/StdIOCallback.h"
#include "matroska/KaxAttachments.h"
+#include "matroska/KaxAttached.h"
#include "matroska/KaxBlock.h"
#include "matroska/KaxBlockData.h"
#include "matroska/KaxChapters.h"
bool Preload( );
bool PreloadFamily( const matroska_segment_c & segment );
void ParseInfo( KaxInfo *info );
+ void ParseAttachments( KaxAttachments *attachments );
void ParseChapters( KaxChapters *chapters );
void ParseSeekHead( KaxSeekHead *seekhead );
void ParseTracks( KaxTracks *tracks );
} event_thread_t;
+
+class attachment_c
+{
+public:
+ attachment_c()
+ :p_data(NULL)
+ ,i_size(0)
+ {}
+ virtual ~attachment_c()
+ {
+ if( p_data ) free( p_data );
+ }
+
+ std::string psz_file_name;
+ std::string psz_mime_type;
+ void *p_data;
+ int i_size;
+};
+
class demux_sys_t
{
public:
delete opened_segments[i];
for ( i=0; i<used_segments.size(); i++ )
delete used_segments[i];
+ for ( i=0; i<stored_attachments.size(); i++ )
+ delete stored_attachments[i];
if( meta ) vlc_meta_Delete( meta );
while( titles.size() )
size_t i_current_title;
std::vector<matroska_stream_c*> streams;
+ std::vector<attachment_c*> stored_attachments;
std::vector<matroska_segment_c*> opened_segments;
std::vector<virtual_segment_c*> used_segments;
virtual_segment_c *p_current_segment;
size_t i_idx;
vlc_meta_t *p_meta;
+ input_attachment_t ***ppp_attach;
+ int *pi_int;
+ int i;
switch( i_query )
{
+ case DEMUX_GET_ATTACHMENTS:
+ ppp_attach = (input_attachment_t***)va_arg( args, input_attachment_t*** );
+ pi_int = (int*)va_arg( args, int * );
+
+ if( p_sys->stored_attachments.size() <= 0 )
+ return VLC_EGENERIC;
+
+ *pi_int = p_sys->stored_attachments.size();
+ *ppp_attach = (input_attachment_t**)malloc( sizeof(input_attachment_t**) *
+ p_sys->stored_attachments.size() );
+ for( i = 0; i < p_sys->stored_attachments.size(); i++ )
+ {
+ attachment_c *a = p_sys->stored_attachments[i];
+ *(ppp_attach)[i] = vlc_input_attachment_New( a->psz_file_name.c_str(), a->psz_mime_type.c_str(), NULL,
+ a->p_data, a->i_size );
+ }
+ return VLC_SUCCESS;
+
case DEMUX_GET_META:
p_meta = (vlc_meta_t*)va_arg( args, vlc_meta_t* );
vlc_meta_Merge( p_meta, p_sys->meta );
}
}
+/*****************************************************************************
+ * ParseAttachments:
+ *****************************************************************************/
+void matroska_segment_c::ParseAttachments( KaxAttachments *attachments )
+{
+ EbmlElement *el;
+ int i_upper_level = 0;
+
+ attachments->Read( es, attachments->Generic().Context, i_upper_level, el, true );
+
+ KaxAttached *attachedFile = FindChild<KaxAttached>( *attachments );
+
+ while( attachedFile && ( attachedFile->GetSize() > 0 ) )
+ {
+ std::string psz_mime_type = GetChild<KaxMimeType>( *attachedFile );
+ KaxFileName &file_name = GetChild<KaxFileName>( *attachedFile );
+ KaxFileData &img_data = GetChild<KaxFileData>( *attachedFile );
+
+ attachment_c *new_attachment = new attachment_c();
+
+ if( new_attachment )
+ {
+ new_attachment->psz_file_name = ToUTF8( UTFstring( file_name ) );
+ new_attachment->psz_mime_type = psz_mime_type;
+ new_attachment->i_size = img_data.GetSize();
+ new_attachment->p_data = malloc( img_data.GetSize() );
+
+ if( new_attachment->p_data )
+ {
+ memcpy( new_attachment->p_data, img_data.GetBuffer(), img_data.GetSize() );
+ sys.stored_attachments.push_back( new_attachment );
+ }
+ }
+
+ attachedFile = &GetNextChild<KaxAttached>( *attachments, *attachedFile );
+ }
+}
+
/*****************************************************************************
* ParseChapters:
*****************************************************************************/
}
else if( MKV_IS_ID( el, KaxAttachments ) )
{
- msg_Dbg( &sys.demuxer, "| + Attachments FIXME (but probably never supported)" );
+ msg_Dbg( &sys.demuxer, "| + Attachments" );
+ ParseAttachments( static_cast<KaxAttachments*>( el ) );
}
else if( MKV_IS_ID( el, KaxChapters ) )
{
// skip over possible leading empty lines and empty spaces
p_peek = (uint8_t *)SkipBlanks((char *)p_peek, 6);
- if( POKE( p_peek, "<asx", 4 ) || isExtension( p_demux, ".asx" ) ||
- isExtension( p_demux, ".wax" ) || isExtension( p_demux, ".wvx" ) ||
- isDemux( p_demux, "asx-open" ) )
+ if( POKE( p_peek, "<asx", 4 ) || demux2_IsPathExtension( p_demux, ".asx" ) ||
+ demux2_IsPathExtension( p_demux, ".wax" ) || demux2_IsPathExtension( p_demux, ".wvx" ) ||
+ demux2_IsForced( p_demux, "asx-open" ) )
{
;
}
int i_peek;
vlc_bool_t b_valid = VLC_FALSE;
- if( !isExtension( p_demux, ".conf" ) && !p_demux->b_force )
+ if( !demux2_IsPathExtension( p_demux, ".conf" ) && !p_demux->b_force )
return VLC_EGENERIC;
/* Check if this really is a channels file */
CHECK_PEEK( p_peek, 8 );
if(! ( POKE( p_peek, "#EXTM3U", 7 ) || POKE( p_peek, "RTSPtext", 8 ) ||
- isExtension( p_demux, ".m3u" ) || isExtension( p_demux, ".vlc" ) ||
+ demux2_IsPathExtension( p_demux, ".m3u" ) || demux2_IsPathExtension( p_demux, ".vlc" ) ||
/* A .ram file can contain a single rtsp link */
- isExtension( p_demux, ".ram" ) || isExtension( p_demux, ".rm" ) ||
- isDemux( p_demux, "m3u" ) ) )
+ demux2_IsPathExtension( p_demux, ".ram" ) || demux2_IsPathExtension( p_demux, ".rm" ) ||
+ demux2_IsForced( p_demux, "m3u" ) ) )
return VLC_EGENERIC;
STANDARD_DEMUX_INIT_MSG( "found valid M3U playlist" );
CHECK_PEEK( p_peek, 10 );
if( POKE( p_peek, "[playlist]", 10 ) || POKE( p_peek, "[Reference]", 10 ) ||
- isExtension( p_demux, ".pls" ) || isDemux( p_demux, "pls" ) )
+ demux2_IsPathExtension( p_demux, ".pls" ) || demux2_IsForced( p_demux, "pls" ) )
{
;
}
{
demux_t *p_demux = (demux_t *)p_this;
- if( !isDemux( p_demux, "podcast" ) )
+ if( !demux2_IsForced( p_demux, "podcast" ) )
return VLC_EGENERIC;
STANDARD_DEMUX_INIT_MSG( "using podcast reader" );
{
demux_t *p_demux = (demux_t *)p_this;
- if( !isDemux( p_demux, "shout-winamp" ) )
+ if( !demux2_IsForced( p_demux, "shout-winamp" ) )
return VLC_EGENERIC;
STANDARD_DEMUX_INIT_MSG( "using shoutcast playlist reader" );
}
return VLC_SUCCESS;
+ case INPUT_GET_ATTACHMENTS: /* arg1=input_attachment_t***, arg2=int* res=can fail */
+ {
+ input_attachment_t ***ppp_attachment = (input_attachment_t***)va_arg( args, input_attachment_t *** );
+ int *pi_attachment = (int*)va_arg( args, int * );
+ int i;
+
+ vlc_mutex_lock( &p_input->p->input.p_item->lock );
+ if( p_input->p->i_attachment <= 0 )
+ {
+ vlc_mutex_unlock( &p_input->p->input.p_item->lock );
+ *ppp_attachment = NULL;
+ *pi_attachment = 0;
+ return VLC_EGENERIC;
+ }
+ *pi_attachment = p_input->p->i_attachment;
+ *ppp_attachment = malloc( sizeof(input_attachment_t**) * p_input->p->i_attachment );
+ for( i = 0; i < p_input->p->i_attachment; i++ )
+ (*ppp_attachment)[i] = vlc_input_attachment_Duplicate( p_input->p->attachment[i] );
+
+ vlc_mutex_unlock( &p_input->p->input.p_item->lock );
+ return VLC_EGENERIC;
+ }
+
+ case INPUT_GET_ATTACHMENT: /* arg1=input_attachment_t**, arg2=char* res=can fail */
+ {
+ input_attachment_t **pp_attachment = (input_attachment_t**)va_arg( args, input_attachment_t ** );
+ const char *psz_name = (const char*)va_arg( args, const char * );
+ int i;
+
+ vlc_mutex_lock( &p_input->p->input.p_item->lock );
+ for( i = 0; i < p_input->p->i_attachment; i++ )
+ {
+ if( !strcmp( p_input->p->attachment[i]->psz_name, psz_name ) )
+ {
+ *pp_attachment = vlc_input_attachment_Duplicate( p_input->p->attachment[i] );
+ vlc_mutex_unlock( &p_input->p->input.p_item->lock );
+ return VLC_SUCCESS;
+ }
+ }
+ *pp_attachment = NULL;
+ vlc_mutex_unlock( &p_input->p->input.p_item->lock );
+ return VLC_EGENERIC;
+ }
+
+
default:
msg_Err( p_input, "unknown query in input_vaControl" );
return VLC_EGENERIC;
block_fifo_t *p_fifo;
};
+/* decoder_GetInputAttachment:
+ */
+input_attachment_t *decoder_GetInputAttachment( decoder_t *p_dec, const char *psz_name )
+{
+ input_attachment_t *p_attachment;
+ if( input_Control( p_dec->p_owner->p_input, INPUT_GET_ATTACHMENT, &p_attachment, psz_name ) )
+ return NULL;
+ return p_attachment;
+}
/**
* Spawns a new decoder thread
case DEMUX_SET_NEXT_DEMUX_TIME:
case DEMUX_GET_TITLE_INFO:
case DEMUX_SET_GROUP:
+ case DEMUX_GET_ATTACHMENTS:
return VLC_EGENERIC;
default:
p_input->p->i_title_offset = p_input->p->i_seekpoint_offset = 0;
p_input->i_state = INIT_S;
p_input->p->i_rate = INPUT_RATE_DEFAULT;
- p_input->p->i_bookmark = 0;
- p_input->p->bookmark = NULL;
+ TAB_INIT( p_input->p->i_bookmark, p_input->p->bookmark );
+ TAB_INIT( p_input->p->i_attachment, p_input->p->attachment );
p_input->p->p_meta = NULL;
p_input->p->p_es_out = NULL;
p_input->p->p_sout = NULL;
#undef CL_CO
}
+ if( p_input->p->i_attachment > 0 )
+ {
+ for( i = 0; i < p_input->p->i_attachment; i++ )
+ vlc_input_attachment_Delete( p_input->p->attachment[i] );
+ TAB_CLEAN( p_input->p->i_attachment, p_input->p->attachment );
+ }
+
vlc_mutex_destroy( &p_input->p->counters.counters_lock );
/* Tell we're dead */
in->p_stream = NULL;
in->p_demux = NULL;
in->b_title_demux = VLC_FALSE;
- in->i_title = 0;
- in->title = NULL;
+ TAB_INIT( in->i_title, in->title );
in->b_can_pace_control = VLC_TRUE;
in->b_eof = VLC_FALSE;
in->i_cr_average = 0;
goto error;
}
- /* TODO get title from demux */
+ /* Get title from demux */
if( !p_input->b_preparsing && in->i_title <= 0 )
{
if( demux2_Control( in->p_demux, DEMUX_GET_TITLE_INFO,
&in->title, &in->i_title,
&in->i_title_offset, &in->i_seekpoint_offset ))
{
- in->i_title = 0;
- in->title = NULL;
+ TAB_INIT( in->i_title, in->title );
}
else
{
in->b_title_demux = VLC_TRUE;
}
}
+ /* get attachment */
+ if( !p_input->b_preparsing )
+ {
+ int i_attachment;
+ input_attachment_t **attachment;
+ if( !demux2_Control( in->p_demux, DEMUX_GET_ATTACHMENTS,
+ &attachment, &i_attachment ) )
+ {
+ int i;
+ vlc_mutex_lock( &p_input->p->input.p_item->lock );
+ p_input->p->attachment = realloc( p_input->p->attachment,
+ sizeof(input_attachment_t**) * ( p_input->p->i_attachment + i_attachment ) );
+ for( i = 0; i < i_attachment; i++ )
+ p_input->p->attachment[p_input->p->i_attachment++] = attachment[i];
+ if( attachment )
+ free( attachment );
+ vlc_mutex_unlock( &p_input->p->input.p_item->lock );
+ }
+ }
}
if( var_GetInteger( p_input, "clock-synchro" ) != -1 )
*****************************************************************************/
static void InputSourceClean( input_source_t *in )
{
+ int i;
+
if( in->p_demux )
demux2_Delete( in->p_demux );
if( in->i_title > 0 )
{
- int i;
for( i = 0; i < in->i_title; i++ )
- {
vlc_input_title_Delete( in->title[i] );
- }
- free( in->title );
+ TAB_CLEAN( in->i_title, in->title );
}
}
int i_bookmark;
seekpoint_t **bookmark;
+ /* Input attachment */
+ int i_attachment;
+ input_attachment_t **attachment;
+
/* Global meta datas FIXME move to input_item_t ? */
vlc_meta_t *p_meta;