/*****************************************************************************
* mkv.cpp : matroska demuxer
*****************************************************************************
- * Copyright (C) 2003-2004 VideoLAN
+ * Copyright (C) 2003-2004 the VideoLAN team
* $Id$
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
N_("Use chapter codecs found in the segment."), VLC_TRUE );
add_bool( "mkv-seek-percent", 0, NULL,
- N_("Seek based on percent not time."),
+ N_("Seek based on percent not time"),
N_("Seek based on percent not time."), VLC_TRUE );
add_bool( "mkv-use-dummy", 0, NULL,
std::vector<chapter_codec_cmds_c*> codecs;
- bool operator<( const chapter_item_c & item ) const
+ static bool CompareTimecode( const chapter_item_c * itemA, const chapter_item_c * itemB )
{
- return ( i_user_start_time < item.i_user_start_time || (i_user_start_time == item.i_user_start_time && i_user_end_time < item.i_user_end_time) );
+ return ( itemA->i_user_start_time < itemB->i_user_start_time || (itemA->i_user_start_time == itemB->i_user_start_time && itemA->i_user_end_time < itemB->i_user_end_time) );
}
bool Enter( bool b_do_subchapters );
{
free( tracks[i_track]->fmt.psz_description );
}
-/* if( tracks[i_track]->psz_codec )
+ if( tracks[i_track]->psz_codec )
{
free( tracks[i_track]->psz_codec );
}
if( tracks[i_track]->fmt.psz_language )
{
free( tracks[i_track]->fmt.psz_language );
- }*/
+ }
delete tracks[i_track];
}
void PreloadFamily( const matroska_segment_c & of_segment );
void PreloadLinked( matroska_segment_c *p_segment );
bool PreparePlayback( virtual_segment_c *p_new_segment );
- matroska_stream_c *AnalyseAllSegmentsFound( EbmlStream *p_estream );
+ matroska_stream_c *AnalyseAllSegmentsFound( EbmlStream *p_estream, bool b_initial = false );
void JumpTo( virtual_segment_c & p_segment, chapter_item_c * p_chapter );
void StartUiThread();
#define MKV_IS_ID( el, C ) ( EbmlId( (*el) ) == C::ClassInfos.GlobalId )
-static char *UTF8ToStr ( const UTFstring &u );
+static inline char * ToUTF8( const UTFstring &u )
+{
+ return strdup( u.GetUTF8().c_str() );
+}
/*****************************************************************************
* Open: initializes matroska demux structures
return VLC_EGENERIC;
}
- p_stream = p_sys->AnalyseAllSegmentsFound( p_io_stream );
+ p_stream = p_sys->AnalyseAllSegmentsFound( p_io_stream, true );
if( p_stream == NULL )
{
msg_Err( p_demux, "cannot find KaxSegment" );
#endif
{
// test wether this file belongs to our family
- vlc_stream_io_callback *p_file_io = new vlc_stream_io_callback( stream_UrlNew( p_demux, s_filename.c_str()), VLC_TRUE );
- EbmlStream *p_estream = new EbmlStream(*p_file_io);
-
- p_stream = p_sys->AnalyseAllSegmentsFound( p_estream );
- if ( p_stream == NULL )
+ stream_t *p_file_stream = stream_UrlNew( p_demux, s_filename.c_str());
+ if ( p_file_stream != NULL )
{
- msg_Dbg( p_demux, "the file '%s' will not be used", s_filename.c_str() );
- delete p_estream;
- delete p_file_io;
+ 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);
+
+ p_stream = p_sys->AnalyseAllSegmentsFound( p_estream );
+
+ if ( p_stream == NULL )
+ {
+ msg_Dbg( p_demux, "the file '%s' will not be used", s_filename.c_str() );
+ delete p_estream;
+ delete p_file_io;
+ }
+ else
+ {
+ p_stream->p_in = p_file_io;
+ p_stream->p_es = p_estream;
+ p_sys->streams.push_back( p_stream );
+ }
}
else
{
- p_stream->p_in = p_file_io;
- p_stream->p_es = p_estream;
- p_sys->streams.push_back( p_stream );
+ msg_Dbg( p_demux, "the file '%s' cannot be opened", s_filename.c_str() );
}
}
}
}
return;
}
- // TODO implement correct timestamping when B frames are used
-#if 0
+ // correct timestamping when B frames are used
if( tk->fmt.i_cat != VIDEO_ES )
{
p_block->i_dts = p_block->i_pts = i_pts;
}
else
{
- p_block->i_pts = i_pts;
+ if( !strcmp( tk->psz_codec, "V_MS/VFW/FOURCC" ) )
+ {
+ p_block->i_pts = 0;
+ }
+ else
+ {
+ p_block->i_pts = i_pts;
+ }
p_block->i_dts = p_sys->i_pts;
}
-#else
- p_block->i_pts = i_pts;
- p_block->i_dts = p_sys->i_last_dts;
-#endif
#if 0
msg_Dbg( p_demux, "block i_dts: "I64Fd" / i_pts: "I64Fd, p_block->i_dts, p_block->i_pts);
#undef tk
}
-matroska_stream_c *demux_sys_t::AnalyseAllSegmentsFound( EbmlStream *p_estream )
+matroska_stream_c *demux_sys_t::AnalyseAllSegmentsFound( EbmlStream *p_estream, bool b_initial )
{
int i_upper_lvl = 0;
size_t i;
{
return NULL;
}
- p_l0->SkipData(*p_estream, EbmlHead_Context);
+ p_l0->SkipData(*p_estream, KaxMatroska_Context);
delete p_l0;
// find all segments in this file
{
EbmlParser *ep;
matroska_segment_c *p_segment1 = new matroska_segment_c( *this, *p_estream );
- b_keep_segment = false;
+ b_keep_segment = b_initial;
ep = new EbmlParser(p_estream, p_l0, &demuxer );
p_segment1->ep = ep;
else
delete p_segment1;
}
-
- p_l0->SkipData(*p_estream, EbmlHead_Context);
- p_l0 = p_estream->FindNextID(KaxSegment::ClassInfos, 0xFFFFFFFFL);
+ if (p_l0->IsFiniteSize() )
+ {
+ p_l0->SkipData(*p_estream, KaxMatroska_Context);
+ p_l0 = p_estream->FindNextID(KaxSegment::ClassInfos, 0xFFFFFFFFL);
+ }
+ else
+ p_l0 = p_l0->SkipData(*p_estream, KaxSegment_Context);
}
if ( !b_keep_stream )
size_t i_track;
/* add all es */
- msg_Dbg( &sys.demuxer, "found %d es", tracks.size() );
+ msg_Dbg( &sys.demuxer, "found %d es", (int)tracks.size() );
sys.b_pci_packet_set = false;
for( i_track = 0; i_track < tracks.size(); i_track++ )
{
if( tracks[i_track]->fmt.i_cat == UNKNOWN_ES )
{
- msg_Warn( &sys.demuxer, "invalid track[%d, n=%d]", i_track, tracks[i_track]->i_number );
+ msg_Warn( &sys.demuxer, "invalid track[%d, n=%d]", (int)i_track, tracks[i_track]->i_number );
tracks[i_track]->p_es = NULL;
continue;
}
else if( !strcmp( tracks[i_track]->psz_codec, "V_MPEG4/ISO/AVC" ) )
{
tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'a', 'v', 'c', '1' );
- tracks[i_track]->fmt.b_packetized = VLC_FALSE;
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, "A_TTA1" ) )
{
/* FIXME: support this codec */
- msg_Err( &sys.demuxer, "TTA not supported yet[%d, n=%d]", i_track, tracks[i_track]->i_number );
+ msg_Err( &sys.demuxer, "TTA not supported yet[%d, n=%d]", (int)i_track, tracks[i_track]->i_number );
tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'u', 'n', 'd', 'f' );
}
else if( !strcmp( tracks[i_track]->psz_codec, "A_WAVPACK4" ) )
{
/* FIXME: support this codec */
- msg_Err( &sys.demuxer, "Wavpack not supported yet[%d, n=%d]", i_track, tracks[i_track]->i_number );
+ msg_Err( &sys.demuxer, "Wavpack not supported yet[%d, n=%d]", (int)i_track, tracks[i_track]->i_number );
tracks[i_track]->fmt.i_codec = VLC_FOURCC( 'u', 'n', 'd', 'f' );
}
else if( !strcmp( tracks[i_track]->psz_codec, "S_TEXT/UTF8" ) )
}
uint64 vlc_stream_io_callback::getFilePointer( void )
{
+ if ( s == NULL )
+ return 0;
return stream_Tell( s );
}
void vlc_stream_io_callback::close( void )
{
KaxTrackName &tname = *(KaxTrackName*)l;
- tk->fmt.psz_description = UTF8ToStr( UTFstring( tname ) );
+ tk->fmt.psz_description = ToUTF8( UTFstring( tname ) );
msg_Dbg( &sys.demuxer, "| | | + Track Name=%s", tk->fmt.psz_description );
}
else if( MKV_IS_ID( l, KaxTrackLanguage ) )
{
KaxTrackLanguage &lang = *(KaxTrackLanguage*)l;
+ if ( tk->fmt.psz_language != NULL )
+ free( tk->fmt.psz_language );
tk->fmt.psz_language = strdup( string( lang ).c_str() );
msg_Dbg( &sys.demuxer,
"| | | + Track Language=`%s'", tk->fmt.psz_language );
{
KaxCodecName &cname = *(KaxCodecName*)l;
- tk->psz_codec_name = UTF8ToStr( UTFstring( cname ) );
+ tk->psz_codec_name = ToUTF8( UTFstring( cname ) );
msg_Dbg( &sys.demuxer, "| | | + Track Codec Name=%s", tk->psz_codec_name );
}
else if( MKV_IS_ID( l, KaxContentEncodings ) )
// {
// KaxCodecSettings &cset = *(KaxCodecSettings*)l;
-// tk->psz_codec_settings = UTF8ToStr( UTFstring( cset ) );
+// tk->psz_codec_settings = ToUTF8( UTFstring( cset ) );
// msg_Dbg( &sys.demuxer, "| | | + Track Codec Settings=%s", tk->psz_codec_settings );
// }
// else if( EbmlId( *l ) == KaxCodecInfoURL::ClassInfos.GlobalId )
if( MKV_IS_ID( l, KaxSegmentUID ) )
{
- p_segment_uid = new KaxSegmentUID(*static_cast<KaxSegmentUID*>(l));
+ if ( p_segment_uid == NULL )
+ p_segment_uid = new KaxSegmentUID(*static_cast<KaxSegmentUID*>(l));
msg_Dbg( &sys.demuxer, "| | + UID=%d", *(uint32*)p_segment_uid->GetBuffer() );
}
else if( MKV_IS_ID( l, KaxPrevUID ) )
{
- p_prev_segment_uid = new KaxPrevUID(*static_cast<KaxPrevUID*>(l));
+ if ( p_prev_segment_uid == NULL )
+ p_prev_segment_uid = new KaxPrevUID(*static_cast<KaxPrevUID*>(l));
msg_Dbg( &sys.demuxer, "| | + PrevUID=%d", *(uint32*)p_prev_segment_uid->GetBuffer() );
}
else if( MKV_IS_ID( l, KaxNextUID ) )
{
- p_next_segment_uid = new KaxNextUID(*static_cast<KaxNextUID*>(l));
+ if ( p_next_segment_uid == NULL )
+ p_next_segment_uid = new KaxNextUID(*static_cast<KaxNextUID*>(l));
msg_Dbg( &sys.demuxer, "| | + NextUID=%d", *(uint32*)p_next_segment_uid->GetBuffer() );
}
{
KaxMuxingApp &mapp = *(KaxMuxingApp*)l;
- psz_muxing_application = UTF8ToStr( UTFstring( mapp ) );
+ psz_muxing_application = ToUTF8( UTFstring( mapp ) );
msg_Dbg( &sys.demuxer, "| | + Muxing Application=%s",
psz_muxing_application );
{
KaxWritingApp &wapp = *(KaxWritingApp*)l;
- psz_writing_application = UTF8ToStr( UTFstring( wapp ) );
+ psz_writing_application = ToUTF8( UTFstring( wapp ) );
msg_Dbg( &sys.demuxer, "| | + Writing Application=%s",
psz_writing_application );
{
KaxSegmentFilename &sfn = *(KaxSegmentFilename*)l;
- psz_segment_filename = UTF8ToStr( UTFstring( sfn ) );
+ psz_segment_filename = ToUTF8( UTFstring( sfn ) );
msg_Dbg( &sys.demuxer, "| | + Segment Filename=%s",
psz_segment_filename );
{
KaxTitle &title = *(KaxTitle*)l;
- psz_title = UTF8ToStr( UTFstring( title ) );
+ psz_title = ToUTF8( UTFstring( title ) );
msg_Dbg( &sys.demuxer, "| | + Title=%s", psz_title );
}
for (k = 0; k < i_level; k++)
chapters.psz_name += '+';
chapters.psz_name += ' ';
- chapters.psz_name += UTF8ToStr( UTFstring( name ) );
+ chapters.psz_name += ToUTF8( UTFstring( name ) );
chapters.b_user_display = true;
- msg_Dbg( &sys.demuxer, "| | | | | + ChapterString '%s'", UTF8ToStr(UTFstring(name)) );
+ msg_Dbg( &sys.demuxer, "| | | | | + ChapterString '%s'", ToUTF8(UTFstring(name)) );
}
else if( MKV_IS_ID( l, KaxChapterLanguage ) )
{
#undef idx
}
-static char * UTF8ToStr( const UTFstring &u )
-{
- int i_src;
- const wchar_t *src;
- char *dst, *p;
-
- i_src = u.length();
- src = u.c_str();
-
- p = dst = (char*)malloc( i_src + 1);
- while( i_src > 0 )
- {
- if( *src < 255 )
- {
- *p++ = (char)*src;
- }
- else
- {
- *p++ = '?';
- }
- src++;
- i_src--;
- }
- *p++= '\0';
-
- return dst;
-}
-
void chapter_edition_c::RefreshChapters( )
{
chapter_item_c::RefreshChapters( b_ordered, -1 );
}
else
{
- std::sort( sub_chapters.begin(), sub_chapters.end() );
+ if ( sub_chapters.begin() != sub_chapters.end() )
+ std::sort( sub_chapters.begin(), sub_chapters.end(), chapter_item_c::CompareTimecode );
i_user_start_time = i_start_time;
if ( i_end_time != -1 )
i_user_end_time = i_end_time;
{
sz_name = N_("Segment ");
char psz_str[6];
- sprintf( psz_str, "%d", i );
+ sprintf( psz_str, "%d", (int)i );
sz_name += psz_str;
p_title->psz_name = strdup( sz_name.c_str() );
}
bool matroska_segment_c::CompareSegmentUIDs( const matroska_segment_c * p_item_a, const matroska_segment_c * p_item_b )
{
+ if ( p_item_a == NULL || p_item_b == NULL )
+ return false;
+
EbmlBinary * p_itema = (EbmlBinary *)(p_item_a->p_segment_uid);
- if ( *p_itema == *p_item_b->p_prev_segment_uid )
+ if ( p_item_b->p_prev_segment_uid != NULL && *p_itema == *p_item_b->p_prev_segment_uid )
return true;
p_itema = (EbmlBinary *)(&p_item_a->p_next_segment_uid);
- if ( *p_itema == *p_item_b->p_segment_uid )
+ if ( p_item_b->p_segment_uid != NULL && *p_itema == *p_item_b->p_segment_uid )
return true;
- if ( *p_itema == *p_item_b->p_prev_segment_uid )
+ if ( p_item_b->p_prev_segment_uid != NULL && *p_itema == *p_item_b->p_prev_segment_uid )
return true;
return false;
if ( i_size != 8 )
return false;
- virtual_segment_c *p_segment;
- chapter_item_c *p_chapter;
+ virtual_segment_c *p_segment = NULL;
+ chapter_item_c *p_chapter = NULL;
bool f_result = false;
uint16 i_command = ( p_command[0] << 8 ) + p_command[1];