From: Laurent Aimar Date: Thu, 31 May 2007 19:22:27 +0000 (+0000) Subject: all: added support for demuxer attachment (Patch by Bernie Purcell) X-Git-Tag: 0.9.0-test0~7186 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=a8a47dd1bae256f55201fc70c93b2917af1d6d55;p=vlc all: added support for demuxer attachment (Patch by Bernie Purcell) 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. --- diff --git a/include/vlc_codec.h b/include/vlc_codec.h index 79fa42132d..d1bc79d141 100644 --- a/include/vlc_codec.h +++ b/include/vlc_codec.h @@ -142,4 +142,6 @@ struct encoder_t * @} */ +VLC_EXPORT( input_attachment_t *, decoder_GetInputAttachment, ( decoder_t *, const char *psz_name ) ); + #endif /* _VLC_CODEC_H */ diff --git a/include/vlc_common.h b/include/vlc_common.h index 2a7330d148..0aef0661c6 100644 --- a/include/vlc_common.h +++ b/include/vlc_common.h @@ -272,6 +272,7 @@ typedef struct es_descriptor_t es_descriptor_t; 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; diff --git a/include/vlc_input.h b/include/vlc_input.h index 92057abdb2..01838689e8 100644 --- a/include/vlc_input.h +++ b/include/vlc_input.h @@ -303,7 +303,57 @@ static inline input_title_t *vlc_input_title_Duplicate( input_title_t *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. *****************************************************************************/ @@ -428,6 +478,10 @@ enum input_query_e 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 * */ }; diff --git a/modules/demux/mkv.cpp b/modules/demux/mkv.cpp index 2c74a4c03c..f1025bbe01 100644 --- a/modules/demux/mkv.cpp +++ b/modules/demux/mkv.cpp @@ -62,6 +62,7 @@ #include "ebml/StdIOCallback.h" #include "matroska/KaxAttachments.h" +#include "matroska/KaxAttached.h" #include "matroska/KaxBlock.h" #include "matroska/KaxBlockData.h" #include "matroska/KaxChapters.h" @@ -1154,6 +1155,7 @@ public: 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 ); @@ -1298,6 +1300,25 @@ typedef struct } 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: @@ -1329,6 +1350,8 @@ public: delete opened_segments[i]; for ( i=0; i streams; + std::vector stored_attachments; std::vector opened_segments; std::vector used_segments; virtual_segment_c *p_current_segment; @@ -1607,9 +1631,30 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) 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 ); @@ -4910,6 +4955,44 @@ void matroska_segment_c::ParseChapterAtom( int i_level, KaxChapterAtom *ca, chap } } +/***************************************************************************** + * 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( *attachments ); + + while( attachedFile && ( attachedFile->GetSize() > 0 ) ) + { + std::string psz_mime_type = GetChild( *attachedFile ); + KaxFileName &file_name = GetChild( *attachedFile ); + KaxFileData &img_data = GetChild( *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( *attachments, *attachedFile ); + } +} + /***************************************************************************** * ParseChapters: *****************************************************************************/ @@ -5441,7 +5524,8 @@ bool matroska_segment_c::Preload( ) } 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( el ) ); } else if( MKV_IS_ID( el, KaxChapters ) ) { diff --git a/modules/demux/playlist/asx.c b/modules/demux/playlist/asx.c index 129ea61636..62b1570767 100644 --- a/modules/demux/playlist/asx.c +++ b/modules/demux/playlist/asx.c @@ -194,9 +194,9 @@ int E_(Import_ASX)( vlc_object_t *p_this ) // skip over possible leading empty lines and empty spaces p_peek = (uint8_t *)SkipBlanks((char *)p_peek, 6); - if( POKE( p_peek, "b_force ) + if( !demux2_IsPathExtension( p_demux, ".conf" ) && !p_demux->b_force ) return VLC_EGENERIC; /* Check if this really is a channels file */ diff --git a/modules/demux/playlist/m3u.c b/modules/demux/playlist/m3u.c index 2f8c36dcd4..7cbdc4b57e 100644 --- a/modules/demux/playlist/m3u.c +++ b/modules/demux/playlist/m3u.c @@ -56,10 +56,10 @@ int E_(Import_M3U)( vlc_object_t *p_this ) 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" ); diff --git a/modules/demux/playlist/pls.c b/modules/demux/playlist/pls.c index ed0c3b0ed9..e776127f07 100644 --- a/modules/demux/playlist/pls.c +++ b/modules/demux/playlist/pls.c @@ -51,7 +51,7 @@ int E_(Import_PLS)( vlc_object_t *p_this ) 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" ) ) { ; } diff --git a/modules/demux/playlist/podcast.c b/modules/demux/playlist/podcast.c index e63c0ff859..f8e4e5fffb 100644 --- a/modules/demux/playlist/podcast.c +++ b/modules/demux/playlist/podcast.c @@ -53,7 +53,7 @@ int E_(Import_podcast)( vlc_object_t *p_this ) { 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" ); diff --git a/modules/demux/playlist/shoutcast.c b/modules/demux/playlist/shoutcast.c index 518c6cc42c..1b3e1de813 100644 --- a/modules/demux/playlist/shoutcast.c +++ b/modules/demux/playlist/shoutcast.c @@ -67,7 +67,7 @@ int E_(Import_Shoutcast)( vlc_object_t *p_this ) { 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" ); diff --git a/src/input/control.c b/src/input/control.c index fb73936219..551b8eb710 100644 --- a/src/input/control.c +++ b/src/input/control.c @@ -546,6 +546,51 @@ int input_vaControl( input_thread_t *p_input, int i_query, va_list args ) } 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; diff --git a/src/input/decoder.c b/src/input/decoder.c index 8c8eee14bf..05c405ca71 100644 --- a/src/input/decoder.c +++ b/src/input/decoder.c @@ -92,6 +92,15 @@ struct decoder_owner_sys_t 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 diff --git a/src/input/demux.c b/src/input/demux.c index f005282054..62706566fc 100644 --- a/src/input/demux.c +++ b/src/input/demux.c @@ -269,6 +269,7 @@ int demux2_vaControlHelper( stream_t *s, case DEMUX_SET_NEXT_DEMUX_TIME: case DEMUX_GET_TITLE_INFO: case DEMUX_SET_GROUP: + case DEMUX_GET_ATTACHMENTS: return VLC_EGENERIC; default: diff --git a/src/input/input.c b/src/input/input.c index 4e59924930..cbc5e1ee94 100644 --- a/src/input/input.c +++ b/src/input/input.c @@ -150,8 +150,8 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item, 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; @@ -1292,6 +1292,13 @@ static void End( input_thread_t * p_input ) #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 */ @@ -2062,8 +2069,7 @@ static input_source_t *InputSourceNew( input_thread_t *p_input ) 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; @@ -2307,21 +2313,39 @@ static int InputSourceInit( input_thread_t *p_input, 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 ) @@ -2349,6 +2373,8 @@ error: *****************************************************************************/ static void InputSourceClean( input_source_t *in ) { + int i; + if( in->p_demux ) demux2_Delete( in->p_demux ); @@ -2360,12 +2386,9 @@ static void InputSourceClean( input_source_t *in ) 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 ); } } diff --git a/src/input/input_internal.h b/src/input/input_internal.h index 6b56a88b10..335bcbd038 100644 --- a/src/input/input_internal.h +++ b/src/input/input_internal.h @@ -87,6 +87,10 @@ struct input_thread_private_t 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;