Commit a8a47dd1 authored by Laurent Aimar's avatar Laurent Aimar

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.
parent 21a5ca24
......@@ -142,4 +142,6 @@ struct encoder_t
* @}
*/
VLC_EXPORT( input_attachment_t *, decoder_GetInputAttachment, ( decoder_t *, const char *psz_name ) );
#endif /* _VLC_CODEC_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;
......
......@@ -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 * */
};
......
......@@ -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 ) )
{
......
......@@ -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" ) )
{
;
}
......
......@@ -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 */
......
......@@ -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" );
......
......@@ -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" ) )
{
;
}
......
......@@ -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" );
......
......@@ -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" );
......
......@@ -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;
......
......@@ -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
......
......@@ -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:
......
......@@ -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 );
}
}
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment