#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;
if (p_src_dir != NULL)
{
- const char *psz_file;
+ char *psz_file;
while ((psz_file = utf8_readdir(p_src_dir)) != NULL)
{
if (strlen(psz_file) > 4)
#endif
{
// test wether this file belongs to our family
+ uint8_t *p_peek;
+ bool file_ok = false;
stream_t *p_file_stream = stream_UrlNew( p_demux, s_filename.c_str());
- if ( p_file_stream != NULL )
+ /* peek the begining */
+ if( p_file_stream &&
+ stream_Peek( p_file_stream, &p_peek, 4 ) >= 4
+ && p_peek[0] == 0x1a && p_peek[1] == 0x45 &&
+ p_peek[2] == 0xdf && p_peek[3] == 0xa3 ) file_ok = true;
+
+ if ( file_ok )
{
vlc_stream_io_callback *p_file_io = new vlc_stream_io_callback( p_file_stream, VLC_TRUE );
EbmlStream *p_estream = new EbmlStream(*p_file_io);
}
else
{
+ if( p_file_stream ) {
+ stream_Delete( p_file_stream );
+ }
msg_Dbg( p_demux, "the file '%s' cannot be opened", s_filename.c_str() );
}
}
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() );
+ if( !(*ppp_attach) )
+ return VLC_ENOMEM;
+ 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 );
if( i_track >= p_segment->tracks.size() )
{
- msg_Err( p_demux, "invalid track number=%d", block->TrackNum() );
+ msg_Err( p_demux, "invalid track number" );
return;
}
if( tk->fmt.i_cat != NAV_ES && tk->p_es == NULL )
{
- msg_Err( p_demux, "unknown track number=%d", block->TrackNum() );
+ msg_Err( p_demux, "unknown track number" );
return;
}
if( i_pts + i_duration < p_sys->i_start_pts && tk->fmt.i_cat == AUDIO_ES )
p_stream1->segments.push_back( p_segment1 );
}
else
+ {
+ p_segment1->segment = NULL;
delete p_segment1;
+ }
}
if (p_l0->IsFiniteSize() )
{
{
tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'v' );
}
+ else if( !strncmp( tracks[i_track]->psz_codec, "V_THEORA", 8 ) )
+ {
+ uint8_t *p_data = tracks[i_track]->p_extra_data;
+ tracks[i_track]->fmt.i_codec = VLC_FOURCC( 't', 'h', 'e', 'o' );
+ if( tracks[i_track]->i_extra_data >= 4 ) {
+ if( p_data[0] == 2 ) {
+ int i = 1;
+ int i_size1 = 0, i_size2 = 0;
+ p_data++;
+ /* read size of first header packet */
+ while( *p_data == 0xFF &&
+ i < tracks[i_track]->i_extra_data )
+ {
+ i_size1 += *p_data;
+ p_data++;
+ i++;
+ }
+ i_size1 += *p_data;
+ p_data++;
+ i++;
+ msg_Dbg( &sys.demuxer, "first theora header size %d", i_size1 );
+ /* read size of second header packet */
+ while( *p_data == 0xFF &&
+ i < tracks[i_track]->i_extra_data )
+ {
+ i_size2 += *p_data;
+ p_data++;
+ i++;
+ }
+ i_size2 += *p_data;
+ p_data++;
+ i++;
+ int i_size3 = tracks[i_track]->i_extra_data - i - i_size1
+ - i_size2;
+ msg_Dbg( &sys.demuxer, "second theora header size %d", i_size2 );
+ msg_Dbg( &sys.demuxer, "third theora header size %d", i_size3 );
+ tracks[i_track]->fmt.i_extra = i_size1 + i_size2 + i_size3
+ + 6;
+ if( i_size1 > 0 && i_size2 > 0 && i_size3 > 0 ) {
+ tracks[i_track]->fmt.p_extra =
+ malloc( tracks[i_track]->fmt.i_extra );
+ uint8_t *p_out = (uint8_t*)tracks[i_track]->fmt.p_extra;
+ *p_out++ = (i_size1>>8) & 0xFF;
+ *p_out++ = i_size1 & 0xFF;
+ memcpy( p_out, p_data, i_size1 );
+ p_data += i_size1;
+ p_out += i_size1;
+
+ *p_out++ = (i_size2>>8) & 0xFF;
+ *p_out++ = i_size2 & 0xFF;
+ memcpy( p_out, p_data, i_size2 );
+ p_data += i_size2;
+ p_out += i_size2;
+
+ *p_out++ = (i_size3>>8) & 0xFF;
+ *p_out++ = i_size3 & 0xFF;
+ memcpy( p_out, p_data, i_size3 );
+ p_data += i_size3;
+ p_out += i_size3;
+ }
+ else
+ {
+ msg_Err( &sys.demuxer, "inconsistant theora extradata" );
+ }
+ }
+ else {
+ msg_Err( &sys.demuxer, "Wrong number of ogg packets with theora headers (%d)", p_data[0] + 1 );
+ }
+ }
+ }
else if( !strncmp( tracks[i_track]->psz_codec, "V_MPEG4", 7 ) )
{
if( !strcmp( tracks[i_track]->psz_codec, "V_MPEG4/MS/V3" ) )
tracks[i_track]->fmt.i_codec = VLC_FOURCC( 's', 'u', 'b', 't' );
tracks[i_track]->fmt.subs.psz_encoding = strdup( "UTF-8" );
}
+ else if( !strcmp( tracks[i_track]->psz_codec, "S_TEXT/USF" ) )
+ {
+ tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'u', 's', 'f', ' ' );
+ tracks[i_track]->fmt.subs.psz_encoding = strdup( "UTF-8" );
+ if( tracks[i_track]->i_extra_data )
+ {
+ tracks[i_track]->fmt.i_extra = tracks[i_track]->i_extra_data;
+ tracks[i_track]->fmt.p_extra = malloc( tracks[i_track]->i_extra_data );
+ memcpy( tracks[i_track]->fmt.p_extra, tracks[i_track]->p_extra_data, tracks[i_track]->i_extra_data );
+ }
+ }
else if( !strcmp( tracks[i_track]->psz_codec, "S_TEXT/SSA" ) ||
!strcmp( tracks[i_track]->psz_codec, "S_TEXT/ASS" ) ||
!strcmp( tracks[i_track]->psz_codec, "S_SSA" ) ||
{
if ( b_ui_hooked )
{
- p_ev->b_die = VLC_TRUE;
-
+ vlc_object_kill( p_ev );
vlc_thread_join( p_ev );
vlc_object_destroy( p_ev );
}
}
+/*****************************************************************************
+ * 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 );
+ }
+ else
+ {
+ delete new_attachment;
+ }
+ }
+
+ attachedFile = &GetNextChild<KaxAttached>( *attachments, *attachedFile );
+ }
+}
+
/*****************************************************************************
* ParseChapters:
*****************************************************************************/
return true;
p_tmp = (EbmlBinary *)p_item_a->p_next_segment_uid;
+ if ( !p_tmp )
+ return false;
+
if ( p_item_b->p_segment_uid != NULL
&& *p_tmp == *p_item_b->p_segment_uid )
return true;
}
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 ) )
{
for( i_track = 0; i_track < tracks.size(); i_track++ )
{
+#if LIBMATROSKA_VERSION >= 0x000800
+ if( (simpleblock && tracks[i_track]->i_number == simpleblock->TrackNum()) ||
+ (block && tracks[i_track]->i_number == block->TrackNum()) )
+#else
if( tracks[i_track]->i_number == block->TrackNum() )
+#endif
{
break;
}
}
- sys.i_pts = (sys.i_chapter_time + block->GlobalTimecode()) / (mtime_t) 1000;
+#if LIBMATROSKA_VERSION >= 0x000800
+ if( simpleblock )
+ sys.i_pts = (sys.i_chapter_time + simpleblock->GlobalTimecode()) / (mtime_t) 1000;
+ else
+#endif
+ sys.i_pts = (sys.i_chapter_time + block->GlobalTimecode()) / (mtime_t) 1000;
if( i_track < tracks.size() )
{