/*****************************************************************************
* mkv.cpp : matroska demuxer
*****************************************************************************
- * Copyright (C) 2003-2004 the VideoLAN team
+ * Copyright (C) 2003-2010 the VideoLAN team
* $Id$
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
} \
ep->Up(); } while( 0 )
+static const struct {
+ vlc_meta_type_t type;
+ const char *key;
+} metadata_map[] = { {vlc_meta_Title, "TITLE"},
+ {vlc_meta_Artist, "ARTIST"},
+ {vlc_meta_Genre, "GENRE"},
+ {vlc_meta_Copyright, "COPYRIGHT"},
+ {vlc_meta_Description, "DESCRIPTION"},
+ {vlc_meta_Publisher, "PUBLISHER"},
+ {vlc_meta_URL, "URL"},
+ {vlc_meta_Title, NULL},
+};
+
+void matroska_segment_c::ParseSimpleTags( KaxTagSimple *tag )
+{
+ EbmlElement *el;
+ EbmlParser *ep = new EbmlParser( &es, tag, &sys.demuxer );
+ char *k = NULL, *v = NULL;
+
+ if( !sys.meta )
+ sys.meta = vlc_meta_New();
+
+ msg_Dbg( &sys.demuxer, "| + Simple Tag ");
+ while( ( el = ep->Get() ) != NULL )
+ {
+ if( MKV_IS_ID( el, KaxTagName ) )
+ {
+ KaxTagName &key = *(KaxTagName*)el;
+ key.ReadData( es.I_O(), SCOPE_ALL_DATA );
+ k = strdup( UTFstring( key ).GetUTF8().c_str() );
+ }
+ if( MKV_IS_ID( el, KaxTagString ) )
+ {
+ KaxTagString &value = *(KaxTagString*)el;
+ value.ReadData( es.I_O(), SCOPE_ALL_DATA );
+ v = strdup( UTFstring( value ).GetUTF8().c_str() );
+ }
+ }
+ delete ep;
+
+ if( !k || !v )
+ {
+ msg_Warn( &sys.demuxer, "Invalid MKV SimpleTag found.");
+ return;
+ }
+
+ for( int i = 0; metadata_map[i].key; i++ )
+ {
+ if( !strcmp( k, metadata_map[i].key ) )
+ {
+ vlc_meta_Set( sys.meta, metadata_map[i].type, v );
+ goto done;
+ }
+ }
+ vlc_meta_AddExtra( sys.meta, k, v );
+done:
+ free( k );
+ free( v );
+ return;
+}
+
void matroska_segment_c::LoadTags( KaxTags *tags )
{
/* Master elements */
{
msg_Dbg( &sys.demuxer, "| + Multi Title" );
}
+ else if( MKV_IS_ID( el, KaxTagSimple ) )
+ ParseSimpleTags( static_cast<KaxTagSimple*>( el ) );
else
{
msg_Dbg( &sys.demuxer, "| + LoadTag Unknown (%s)", typeid( *el ).name() );
*****************************************************************************/
void matroska_segment_c::InformationCreate( )
{
+#if 0
sys.meta = vlc_meta_New();
if( psz_title )
{
vlc_meta_SetDate( sys.meta, psz_date_utc );
}
-#if 0
+
if( psz_segment_filename )
{
fprintf( stderr, "***** WARNING: Unhandled meta - Use custom\n" );
#undef idx
}
-
bool matroska_segment_c::PreloadFamily( const matroska_segment_c & of_segment )
{
if ( b_preloaded )
;//LoadTags( static_cast<KaxTags*>( el ) );
i_tags_position = (int64_t) es.I_O().getFilePointer();
}
+ else if( MKV_IS_ID( el, EbmlVoid ) )
+ msg_Dbg( &sys.demuxer, "| + Void" );
else
msg_Dbg( &sys.demuxer, "| + Preload Unknown (%s)", typeid(*el).name() );
}
ParseChapters( static_cast<KaxChapters*>( el ) );
i_chapters_position = i_element_position;
}
- else if( MKV_IS_ID( el, KaxTag ) ) // FIXME
+ else if( MKV_IS_ID( el, KaxTags ) )
{
msg_Dbg( &sys.demuxer, "| + Tags" );
if( i_tags_position < 0 )
- ;//LoadTags( static_cast<KaxTags*>( el ) );
+ LoadTags( static_cast<KaxTags*>( el ) );
i_tags_position = i_element_position;
}
else
}
}
-
int matroska_segment_c::BlockFindTrackIndex( size_t *pi_track,
const KaxBlock *p_block, const KaxSimpleBlock *p_simpleblock )
{
size_t i_track;
-
for( i_track = 0; i_track < tracks.size(); i_track++ )
{
const mkv_track_t *tk = tracks[i_track];
return VLC_SUCCESS;
}
+static inline void fill_extra_data( mkv_track_t *p_tk )
+{
+ p_tk->fmt.i_extra = p_tk->i_extra_data;
+ p_tk->fmt.p_extra = xmalloc( p_tk->i_extra_data );
+ memcpy( p_tk->fmt.p_extra, p_tk->p_extra_data, p_tk->i_extra_data );
+}
+
bool matroska_segment_c::Select( mtime_t i_start_time )
{
/* add all es */
!strcmp( p_tk->psz_codec, "V_MPEG2" ) )
{
p_tk->fmt.i_codec = VLC_CODEC_MPGV;
+ if( p_tk->i_extra_data )
+ fill_extra_data( p_tk );
}
else if( !strncmp( p_tk->psz_codec, "V_THEORA", 8 ) )
{
p_tk->fmt.i_codec = VLC_CODEC_THEORA;
- p_tk->fmt.i_extra = p_tk->i_extra_data;
- p_tk->fmt.p_extra = xmalloc( p_tk->i_extra_data );
- memcpy( p_tk->fmt.p_extra,p_tk->p_extra_data, p_tk->i_extra_data );
+ fill_extra_data( p_tk );
p_tk->b_pts_only = true;
}
else if( !strncmp( p_tk->psz_codec, "V_REAL/RV", 9 ) )
p_tk->fmt.i_codec = VLC_FOURCC( 'a', 'v', 'c', '1' );
else
p_tk->fmt.i_codec = VLC_CODEC_MP4V;
- p_tk->fmt.i_extra = p_tk->i_extra_data;
- p_tk->fmt.p_extra = xmalloc( p_tk->i_extra_data );
- memcpy( p_tk->fmt.p_extra,p_tk->p_extra_data, p_tk->i_extra_data );
+ fill_extra_data( p_tk );
}
}
else if( !strcmp( p_tk->psz_codec, "V_QUICKTIME" ) )
}
stream_Delete( p_mp4_stream );
}
+ else if( !strcmp( p_tk->psz_codec, "V_MJPEG" ) )
+ {
+ p_tk->fmt.i_codec = VLC_CODEC_MJPG;
+ }
else if( !strcmp( p_tk->psz_codec, "A_MS/ACM" ) )
{
if( p_tk->i_extra_data < (int)sizeof( WAVEFORMATEX ) )
else if( !strcmp( p_tk->psz_codec, "A_FLAC" ) )
{
p_tk->fmt.i_codec = VLC_CODEC_FLAC;
- p_tk->fmt.i_extra = p_tk->i_extra_data;
- p_tk->fmt.p_extra = xmalloc( p_tk->i_extra_data );
- memcpy( p_tk->fmt.p_extra,p_tk->p_extra_data, p_tk->i_extra_data );
+ fill_extra_data( p_tk );
}
else if( !strcmp( p_tk->psz_codec, "A_VORBIS" ) )
{
p_tk->fmt.i_codec = VLC_CODEC_VORBIS;
- p_tk->fmt.i_extra = p_tk->i_extra_data;
- p_tk->fmt.p_extra = xmalloc( p_tk->i_extra_data );
- memcpy( p_tk->fmt.p_extra,p_tk->p_extra_data, p_tk->i_extra_data );
+ fill_extra_data( p_tk );
}
else if( !strncmp( p_tk->psz_codec, "A_AAC/MPEG2/", strlen( "A_AAC/MPEG2/" ) ) ||
!strncmp( p_tk->psz_codec, "A_AAC/MPEG4/", strlen( "A_AAC/MPEG4/" ) ) )
else if( !strcmp( p_tk->psz_codec, "A_AAC" ) )
{
p_tk->fmt.i_codec = VLC_CODEC_MP4A;
- p_tk->fmt.i_extra = p_tk->i_extra_data;
- p_tk->fmt.p_extra = xmalloc( p_tk->i_extra_data );
- memcpy( p_tk->fmt.p_extra, p_tk->p_extra_data, p_tk->i_extra_data );
+ fill_extra_data( p_tk );
}
else if( !strcmp( p_tk->psz_codec, "A_WAVPACK4" ) )
{
p_tk->fmt.i_codec = VLC_CODEC_WAVPACK;
- p_tk->fmt.i_extra = p_tk->i_extra_data;
- p_tk->fmt.p_extra = xmalloc( p_tk->i_extra_data );
- memcpy( p_tk->fmt.p_extra, p_tk->p_extra_data, p_tk->i_extra_data );
+ fill_extra_data( p_tk );
}
else if( !strcmp( p_tk->psz_codec, "A_TTA1" ) )
{
p_fmt->i_codec = VLC_CODEC_TTA;
- p_fmt->i_extra = p_tk->i_extra_data;
- if( p_fmt->i_extra > 0 )
+ if( p_tk->i_extra_data > 0 )
{
- p_fmt->p_extra = xmalloc( p_tk->i_extra_data );
- memcpy( p_fmt->p_extra, p_tk->p_extra_data, p_tk->i_extra_data );
+ fill_extra_data( p_tk );
}
else
{
else if( !strcmp( p_tk->psz_codec, "A_REAL/28_8" ) )
p_tk->fmt.i_codec = VLC_CODEC_RA_288;
/* FIXME 14_4, RALF and SIPR */
- p_tk->fmt.i_extra = p_tk->i_extra_data;
- p_tk->fmt.p_extra = xmalloc( p_tk->i_extra_data );
- memcpy( p_tk->fmt.p_extra,p_tk->p_extra_data, p_tk->i_extra_data );
+ fill_extra_data( p_tk );
}
else if( !strcmp( p_tk->psz_codec, "A_REAL/14_4" ) )
{
p_tk->fmt.i_codec = VLC_CODEC_KATE;
p_tk->fmt.subs.psz_encoding = strdup( "UTF-8" );
- p_tk->fmt.i_extra = p_tk->i_extra_data;
- p_tk->fmt.p_extra = xmalloc( p_tk->i_extra_data );
- memcpy( p_tk->fmt.p_extra,p_tk->p_extra_data, p_tk->i_extra_data );
+ fill_extra_data( p_tk );
}
else if( !strcmp( p_tk->psz_codec, "S_TEXT/ASCII" ) )
{
p_tk->fmt.subs.psz_encoding = strdup( "UTF-8" );
if( p_tk->i_extra_data )
{
- p_tk->fmt.i_extra = p_tk->i_extra_data;
- p_tk->fmt.p_extra = xmalloc( p_tk->i_extra_data );
- memcpy( p_tk->fmt.p_extra, p_tk->p_extra_data, p_tk->i_extra_data );
+ fill_extra_data( p_tk );
}
}
else if( !strcmp( p_tk->psz_codec, "S_TEXT/SSA" ) ||
p_tk->fmt.subs.psz_encoding = strdup( "UTF-8" );
if( p_tk->i_extra_data )
{
- p_tk->fmt.i_extra = p_tk->i_extra_data;
- p_tk->fmt.p_extra = xmalloc( p_tk->i_extra_data );
- memcpy( p_tk->fmt.p_extra, p_tk->p_extra_data, p_tk->i_extra_data );
+ fill_extra_data( p_tk );
}
}
else if( !strcmp( p_tk->psz_codec, "S_VOBSUB" ) )
}
}
es_out_Control( sys.demuxer.out, ES_OUT_SET_NEXT_DISPLAY_TIME, i_start_time );
-
+
sys.i_start_pts = i_start_time;
// reset the stream reading to the first cluster of the segment used
es.I_O().setFilePointer( i_start_pos );
void matroska_segment_c::UnSelect( )
{
- size_t i_track;
-
- for( i_track = 0; i_track < tracks.size(); i_track++ )
+ for( size_t i_track = 0; i_track < tracks.size(); i_track++ )
{
if ( tracks[i_track]->p_es != NULL )
{