Commit 66a31249 authored by Steve Lhomme's avatar Steve Lhomme

mkv.cpp: hard-linked segments can now play in order (crash to solve)

parent 8697e6ef
...@@ -508,7 +508,7 @@ public: ...@@ -508,7 +508,7 @@ public:
bool Preload( ); bool Preload( );
bool PreloadFamily( const matroska_segment_t & segment ); bool PreloadFamily( const matroska_segment_t & segment );
size_t PreloadLinked( const demux_sys_t & of_sys ); size_t PreloadLinked( const demux_sys_t & of_sys, std::vector<matroska_segment_t*> & segments );
void ParseInfo( EbmlElement *info ); void ParseInfo( EbmlElement *info );
void ParseChapters( EbmlElement *chapters ); void ParseChapters( EbmlElement *chapters );
void ParseSeekHead( EbmlElement *seekhead ); void ParseSeekHead( EbmlElement *seekhead );
...@@ -519,6 +519,7 @@ public: ...@@ -519,6 +519,7 @@ public:
int BlockGet( KaxBlock **pp_block, int64_t *pi_ref1, int64_t *pi_ref2, int64_t *pi_duration ); int BlockGet( KaxBlock **pp_block, int64_t *pi_ref1, int64_t *pi_ref2, int64_t *pi_duration );
bool Select( mtime_t i_start_time ); bool Select( mtime_t i_start_time );
void UnSelect( ); void UnSelect( );
static bool CompareSegmentUIDs( const matroska_segment_t * item_a, const matroska_segment_t * item_b );
}; };
class matroska_stream_t class matroska_stream_t
...@@ -529,6 +530,7 @@ public: ...@@ -529,6 +530,7 @@ public:
,p_es(NULL) ,p_es(NULL)
,i_current_segment(-1) ,i_current_segment(-1)
,sys(demuxer) ,sys(demuxer)
,f_duration(-1.0)
{} {}
~matroska_stream_t() ~matroska_stream_t()
...@@ -547,6 +549,9 @@ public: ...@@ -547,6 +549,9 @@ public:
demux_sys_t & sys; demux_sys_t & sys;
/* duration of the stream */
float f_duration;
inline matroska_segment_t *Segment() inline matroska_segment_t *Segment()
{ {
if ( i_current_segment >= 0 && size_t(i_current_segment) < segments.size() ) if ( i_current_segment >= 0 && size_t(i_current_segment) < segments.size() )
...@@ -558,6 +563,7 @@ public: ...@@ -558,6 +563,7 @@ public:
void PreloadFamily( const matroska_segment_t & segment ); void PreloadFamily( const matroska_segment_t & segment );
size_t PreloadLinked( const demux_sys_t & of_sys ); size_t PreloadLinked( const demux_sys_t & of_sys );
void PreparePlayback( );
}; };
class demux_sys_t class demux_sys_t
...@@ -603,6 +609,7 @@ public: ...@@ -603,6 +609,7 @@ public:
matroska_segment_t *FindSegment( const EbmlBinary & uid ) const; matroska_segment_t *FindSegment( const EbmlBinary & uid ) const;
void PreloadFamily( ); void PreloadFamily( );
void PreloadLinked( ); void PreloadLinked( );
void PreparePlayback( );
matroska_stream_t *AnalyseAllSegmentsFound( EbmlStream *p_estream ); matroska_stream_t *AnalyseAllSegmentsFound( EbmlStream *p_estream );
}; };
...@@ -747,6 +754,7 @@ static int Open( vlc_object_t * p_this ) ...@@ -747,6 +754,7 @@ static int Open( vlc_object_t * p_this )
p_sys->PreloadFamily( ); p_sys->PreloadFamily( );
p_sys->PreloadLinked( ); p_sys->PreloadLinked( );
p_sys->PreparePlayback( );
/* *** Load the cue if found *** */ /* *** Load the cue if found *** */
if( p_segment->i_cues_position >= 0 ) if( p_segment->i_cues_position >= 0 )
...@@ -828,17 +836,17 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) ...@@ -828,17 +836,17 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
case DEMUX_GET_LENGTH: case DEMUX_GET_LENGTH:
pi64 = (int64_t*)va_arg( args, int64_t * ); pi64 = (int64_t*)va_arg( args, int64_t * );
if( p_segment && p_segment->f_duration > 0.0 ) if( p_stream->f_duration > 0.0 )
{ {
*pi64 = (int64_t)(p_segment->f_duration * 1000); *pi64 = (int64_t)(p_stream->f_duration * 1000);
return VLC_SUCCESS; return VLC_SUCCESS;
} }
return VLC_EGENERIC; return VLC_EGENERIC;
case DEMUX_GET_POSITION: case DEMUX_GET_POSITION:
pf = (double*)va_arg( args, double * ); pf = (double*)va_arg( args, double * );
if ( p_segment && p_segment->f_duration > 0.0 ) if ( p_stream->f_duration > 0.0 )
*pf = (double)p_sys->i_pts / (1000.0 * p_segment->f_duration); *pf = (double)p_sys->i_pts / (1000.0 * p_stream->f_duration);
return VLC_SUCCESS; return VLC_SUCCESS;
case DEMUX_SET_POSITION: case DEMUX_SET_POSITION:
...@@ -1638,9 +1646,9 @@ static void Seek( demux_t *p_demux, mtime_t i_date, double f_percent, const chap ...@@ -1638,9 +1646,9 @@ static void Seek( demux_t *p_demux, mtime_t i_date, double f_percent, const chap
/* seek without index or without date */ /* seek without index or without date */
if( f_percent >= 0 && (config_GetInt( p_demux, "mkv-seek-percent" ) || !p_segment->b_cues || i_date < 0 )) if( f_percent >= 0 && (config_GetInt( p_demux, "mkv-seek-percent" ) || !p_segment->b_cues || i_date < 0 ))
{ {
if (p_segment->f_duration >= 0) if (p_stream->f_duration >= 0)
{ {
i_date = int64_t( f_percent * p_segment->f_duration * 1000.0 ); i_date = int64_t( f_percent * p_stream->f_duration * 1000.0 );
} }
else else
{ {
...@@ -3108,7 +3116,7 @@ void matroska_segment_t::ParseChapters( EbmlElement *chapters ) ...@@ -3108,7 +3116,7 @@ void matroska_segment_t::ParseChapters( EbmlElement *chapters )
} }
else if( MKV_IS_ID( l, KaxEditionFlagOrdered ) ) else if( MKV_IS_ID( l, KaxEditionFlagOrdered ) )
{ {
edition.b_ordered = config_GetInt( &sys.demuxer, "mkv-use-ordered-chapters" ) ? (uint8(*static_cast<KaxEditionFlagOrdered *>( l )) != 0) : 0; edition.b_ordered = config_GetInt( &sys.demuxer, "mkv-use-ordered-chapters" ) ? (uint8(*static_cast<KaxEditionFlagOrdered *>( l )) != 0) : 0;
} }
else if( MKV_IS_ID( l, KaxEditionFlagDefault ) ) else if( MKV_IS_ID( l, KaxEditionFlagDefault ) )
{ {
...@@ -3440,12 +3448,13 @@ size_t matroska_stream_t::PreloadLinked( const demux_sys_t & of_sys ) ...@@ -3440,12 +3448,13 @@ size_t matroska_stream_t::PreloadLinked( const demux_sys_t & of_sys )
size_t i_result = 0; size_t i_result = 0;
for (size_t i=0; i<segments.size(); i++) for (size_t i=0; i<segments.size(); i++)
{ {
i_result += segments[i]->PreloadLinked( of_sys ); i_result += segments[i]->PreloadLinked( of_sys, segments );
} }
return i_result; return i_result;
} }
size_t matroska_segment_t::PreloadLinked( const demux_sys_t & of_sys ) size_t matroska_segment_t::PreloadLinked( const demux_sys_t & of_sys, std::vector<matroska_segment_t*> & segments )
{ {
size_t i_result = 0; size_t i_result = 0;
if ( prev_segment_uid.GetBuffer() ) if ( prev_segment_uid.GetBuffer() )
...@@ -3453,7 +3462,11 @@ size_t matroska_segment_t::PreloadLinked( const demux_sys_t & of_sys ) ...@@ -3453,7 +3462,11 @@ size_t matroska_segment_t::PreloadLinked( const demux_sys_t & of_sys )
matroska_segment_t *p_segment = of_sys.FindSegment( prev_segment_uid ); matroska_segment_t *p_segment = of_sys.FindSegment( prev_segment_uid );
if ( p_segment ) if ( p_segment )
{ {
i_result += p_segment->Preload( ) ? 1 : 0; if ( p_segment->Preload( ) )
{
segments.push_back( p_segment );
i_result++;
}
} }
} }
if ( next_segment_uid.GetBuffer() ) if ( next_segment_uid.GetBuffer() )
...@@ -3461,12 +3474,53 @@ size_t matroska_segment_t::PreloadLinked( const demux_sys_t & of_sys ) ...@@ -3461,12 +3474,53 @@ size_t matroska_segment_t::PreloadLinked( const demux_sys_t & of_sys )
matroska_segment_t *p_segment = of_sys.FindSegment( next_segment_uid ); matroska_segment_t *p_segment = of_sys.FindSegment( next_segment_uid );
if ( p_segment ) if ( p_segment )
{ {
i_result += p_segment->Preload( ) ? 1 : 0; if ( p_segment->Preload( ) )
{
segments.push_back( p_segment );
i_result++;
}
} }
} }
return i_result; return i_result;
} }
void demux_sys_t::PreparePlayback( )
{
matroska_stream_t *p_stream = Stream();
if ( p_stream )
{
p_stream->PreparePlayback( );
}
}
void matroska_stream_t::PreparePlayback( )
{
size_t i;
// update duration
f_duration = 0.0;
for (i=0; i<segments.size(); i++)
{
f_duration += segments[i]->f_duration;
}
// sort segment order
std::sort( segments.begin(), segments.end(), matroska_segment_t::CompareSegmentUIDs );
}
bool matroska_segment_t::CompareSegmentUIDs( const matroska_segment_t * p_item_a, const matroska_segment_t * p_item_b )
{
EbmlBinary * p_itema = (EbmlBinary *)(&p_item_a->segment_uid);
if ( *p_itema == p_item_b->prev_segment_uid )
return true;
p_itema = (EbmlBinary *)(&p_item_a->next_segment_uid);
if ( *p_itema == p_item_b->segment_uid )
return true;
return false;
}
bool matroska_segment_t::Preload( ) bool matroska_segment_t::Preload( )
{ {
if ( b_preloaded ) if ( b_preloaded )
......
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