all: added support for demuxer attachment (Patch by Bernie Purcell)
authorLaurent Aimar <fenrir@videolan.org>
Thu, 31 May 2007 19:22:27 +0000 (19:22 +0000)
committerLaurent Aimar <fenrir@videolan.org>
Thu, 31 May 2007 19:22:27 +0000 (19:22 +0000)
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.

15 files changed:
include/vlc_codec.h
include/vlc_common.h
include/vlc_input.h
modules/demux/mkv.cpp
modules/demux/playlist/asx.c
modules/demux/playlist/dvb.c
modules/demux/playlist/m3u.c
modules/demux/playlist/pls.c
modules/demux/playlist/podcast.c
modules/demux/playlist/shoutcast.c
src/input/control.c
src/input/decoder.c
src/input/demux.c
src/input/input.c
src/input/input_internal.h

index 79fa421..d1bc79d 100644 (file)
@@ -142,4 +142,6 @@ struct encoder_t
  * @}
  */
 
+VLC_EXPORT( input_attachment_t *, decoder_GetInputAttachment, ( decoder_t *, const char *psz_name ) );
+
 #endif /* _VLC_CODEC_H */
index 2a7330d..0aef066 100644 (file)
@@ -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;
index 92057ab..0183868 100644 (file)
@@ -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 * */
 };
index 2c74a4c..f1025bb 100644 (file)
@@ -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<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() )
@@ -1350,6 +1373,7 @@ public:
     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;
@@ -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<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:
  *****************************************************************************/
@@ -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<KaxAttachments*>( el ) );
         }
         else if( MKV_IS_ID( el, KaxChapters ) )
         {
index 129ea61..62b1570 100644 (file)
@@ -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, "<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" ) )
     {
         ;
     }
index 2fe46ab..4236210 100644 (file)
@@ -54,7 +54,7 @@ int E_(Import_DVB)( vlc_object_t *p_this )
     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 */
index 2f8c36d..7cbdc4b 100644 (file)
@@ -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" );
index ed0c3b0..e776127 100644 (file)
@@ -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" ) )
     {
         ;
     }
index e63c0ff..f8e4e5f 100644 (file)
@@ -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" );
index 518c6cc..1b3e1de 100644 (file)
@@ -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" );
index fb73936..551b8eb 100644 (file)
@@ -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;
index 8c8eee1..05c405c 100644 (file)
@@ -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
index f005282..6270656 100644 (file)
@@ -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:
index 4e59924..cbc5e1e 100644 (file)
@@ -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 );
     }
 }
 
index 6b56a88..335bcbd 100644 (file)
@@ -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;