Commit 1ec6b9e4 authored by Denis Charmet's avatar Denis Charmet Committed by Jean-Baptiste Kempf

Fix next/prev uid segment linking in MKV

This still doesn't work with ordered chapters though.
Signed-off-by: default avatarJean-Baptiste Kempf <jb@videolan.org>
(cherry picked from commit 50f3a9b9)
Signed-off-by: default avatarJean-Baptiste Kempf <jb@videolan.org>
parent b1f63c28
...@@ -536,10 +536,12 @@ matroska_stream_c *demux_sys_t::AnalyseAllSegmentsFound( demux_t *p_demux, EbmlS ...@@ -536,10 +536,12 @@ matroska_stream_c *demux_sys_t::AnalyseAllSegmentsFound( demux_t *p_demux, EbmlS
else if( MKV_IS_ID( l, KaxPrevUID ) ) else if( MKV_IS_ID( l, KaxPrevUID ) )
{ {
p_segment1->p_prev_segment_uid = new KaxPrevUID( *static_cast<KaxPrevUID*>(l) ); p_segment1->p_prev_segment_uid = new KaxPrevUID( *static_cast<KaxPrevUID*>(l) );
p_segment1->b_ref_external_segments = true;
} }
else if( MKV_IS_ID( l, KaxNextUID ) ) else if( MKV_IS_ID( l, KaxNextUID ) )
{ {
p_segment1->p_next_segment_uid = new KaxNextUID( *static_cast<KaxNextUID*>(l) ); p_segment1->p_next_segment_uid = new KaxNextUID( *static_cast<KaxNextUID*>(l) );
p_segment1->b_ref_external_segments = true;
} }
else if( MKV_IS_ID( l, KaxSegmentFamily ) ) else if( MKV_IS_ID( l, KaxSegmentFamily ) )
{ {
......
...@@ -102,8 +102,10 @@ virtual_chapter_c::~virtual_chapter_c() ...@@ -102,8 +102,10 @@ virtual_chapter_c::~virtual_chapter_c()
virtual_edition_c::virtual_edition_c( chapter_edition_c * p_edit, std::vector<matroska_segment_c*> *opened_segments) virtual_edition_c::virtual_edition_c( chapter_edition_c * p_edit, std::vector<matroska_segment_c*> *opened_segments)
{ {
bool b_fake_ordered = false;
matroska_segment_c *p_main_segment = (*opened_segments)[0]; matroska_segment_c *p_main_segment = (*opened_segments)[0];
p_edition = p_edit; p_edition = p_edit;
b_ordered = false;
int64_t usertime_offset = 0; int64_t usertime_offset = 0;
...@@ -123,14 +125,13 @@ virtual_edition_c::virtual_edition_c( chapter_edition_c * p_edit, std::vector<ma ...@@ -123,14 +125,13 @@ virtual_edition_c::virtual_edition_c( chapter_edition_c * p_edit, std::vector<ma
} }
else /* Not ordered or no edition at all */ else /* Not ordered or no edition at all */
{ {
b_ordered = false;
matroska_segment_c * p_cur = p_main_segment; matroska_segment_c * p_cur = p_main_segment;
virtual_chapter_c * p_vchap = NULL; virtual_chapter_c * p_vchap = NULL;
int64_t tmp = 0; int64_t tmp = 0;
/* check for prev linked segments */ /* check for prev linked segments */
/* FIXME to avoid infinite recursion we limit to 5 prev sould be better as parameter */ /* FIXME to avoid infinite recursion we limit to 10 prev should be better as parameter */
for( int limit = 0; limit < 5 && p_cur->p_prev_segment_uid ; limit++ ) for( int limit = 0; limit < 10 && p_cur->p_prev_segment_uid ; limit++ )
{ {
matroska_segment_c * p_prev = NULL; matroska_segment_c * p_prev = NULL;
if( ( p_prev = getSegmentbyUID( p_cur->p_prev_segment_uid, opened_segments ) ) ) if( ( p_prev = getSegmentbyUID( p_cur->p_prev_segment_uid, opened_segments ) ) )
...@@ -139,6 +140,10 @@ virtual_edition_c::virtual_edition_c( chapter_edition_c * p_edit, std::vector<ma ...@@ -139,6 +140,10 @@ virtual_edition_c::virtual_edition_c( chapter_edition_c * p_edit, std::vector<ma
msg_Dbg( &p_main_segment->sys.demuxer, "Prev segment 0x%x found\n", msg_Dbg( &p_main_segment->sys.demuxer, "Prev segment 0x%x found\n",
*(int32_t*)p_cur->p_prev_segment_uid->GetBuffer() ); *(int32_t*)p_cur->p_prev_segment_uid->GetBuffer() );
/* Preload segment */
if ( !p_prev->b_preloaded )
p_prev->Preload();
/* Create virtual_chapter from the first edition if any */ /* Create virtual_chapter from the first edition if any */
chapter_item_c * p_chap = ( p_prev->stored_editions.size() > 0 )? ((chapter_item_c *)p_prev->stored_editions[0]) : NULL; chapter_item_c * p_chap = ( p_prev->stored_editions.size() > 0 )? ((chapter_item_c *)p_prev->stored_editions[0]) : NULL;
...@@ -148,6 +153,7 @@ virtual_edition_c::virtual_edition_c( chapter_edition_c * p_edit, std::vector<ma ...@@ -148,6 +153,7 @@ virtual_edition_c::virtual_edition_c( chapter_edition_c * p_edit, std::vector<ma
chapters.insert( chapters.begin(), p_vchap ); chapters.insert( chapters.begin(), p_vchap );
p_cur = p_prev; p_cur = p_prev;
b_fake_ordered = true;
} }
else /* segment not found */ else /* segment not found */
break; break;
...@@ -162,7 +168,7 @@ virtual_edition_c::virtual_edition_c( chapter_edition_c * p_edit, std::vector<ma ...@@ -162,7 +168,7 @@ virtual_edition_c::virtual_edition_c( chapter_edition_c * p_edit, std::vector<ma
chapters.push_back( p_vchap ); chapters.push_back( p_vchap );
/* Append next linked segments */ /* Append next linked segments */
for( int limit = 0; limit < 5 && p_cur->p_next_segment_uid; limit++ ) for( int limit = 0; limit < 10 && p_cur->p_next_segment_uid; limit++ )
{ {
matroska_segment_c * p_next = NULL; matroska_segment_c * p_next = NULL;
if( ( p_next = getSegmentbyUID( p_cur->p_next_segment_uid, opened_segments ) ) ) if( ( p_next = getSegmentbyUID( p_cur->p_next_segment_uid, opened_segments ) ) )
...@@ -171,6 +177,10 @@ virtual_edition_c::virtual_edition_c( chapter_edition_c * p_edit, std::vector<ma ...@@ -171,6 +177,10 @@ virtual_edition_c::virtual_edition_c( chapter_edition_c * p_edit, std::vector<ma
msg_Dbg( &p_main_segment->sys.demuxer, "Next segment 0x%x found\n", msg_Dbg( &p_main_segment->sys.demuxer, "Next segment 0x%x found\n",
*(int32_t*) p_cur->p_next_segment_uid->GetBuffer() ); *(int32_t*) p_cur->p_next_segment_uid->GetBuffer() );
/* Preload segment */
if ( !p_next->b_preloaded )
p_next->Preload();
/* Create virtual_chapter from the first edition if any */ /* Create virtual_chapter from the first edition if any */
chapter_item_c * p_chap = ( p_next->stored_editions.size() > 0 )?( (chapter_item_c *)p_next->stored_editions[0] ) : NULL; chapter_item_c * p_chap = ( p_next->stored_editions.size() > 0 )?( (chapter_item_c *)p_next->stored_editions[0] ) : NULL;
...@@ -181,6 +191,7 @@ virtual_edition_c::virtual_edition_c( chapter_edition_c * p_edit, std::vector<ma ...@@ -181,6 +191,7 @@ virtual_edition_c::virtual_edition_c( chapter_edition_c * p_edit, std::vector<ma
p_cur = p_next; p_cur = p_next;
b_fake_ordered = true;
} }
else /* segment not found */ else /* segment not found */
break; break;
...@@ -188,6 +199,8 @@ virtual_edition_c::virtual_edition_c( chapter_edition_c * p_edit, std::vector<ma ...@@ -188,6 +199,8 @@ virtual_edition_c::virtual_edition_c( chapter_edition_c * p_edit, std::vector<ma
/* Retime chapters */ /* Retime chapters */
retimeChapters(); retimeChapters();
if(b_fake_ordered)
b_ordered = true;
} }
#if MKV_DEBUG #if MKV_DEBUG
...@@ -228,10 +241,6 @@ void virtual_edition_c::retimeChapters() ...@@ -228,10 +241,6 @@ void virtual_edition_c::retimeChapters()
i_duration = 0; i_duration = 0;
/* Sort by start time */
if( chapters.size() > 1 )
std::sort( chapters.begin(), chapters.end(), virtual_chapter_c::CompareTimecode );
/* On non ordered editions we have one top chapter == one segment */ /* On non ordered editions we have one top chapter == one segment */
for( size_t i = 0; i < chapters.size(); i++ ) for( size_t i = 0; i < chapters.size(); i++ )
{ {
...@@ -383,8 +392,8 @@ bool virtual_segment_c::UpdateCurrentToChapter( demux_t & demux ) ...@@ -383,8 +392,8 @@ bool virtual_segment_c::UpdateCurrentToChapter( demux_t & demux )
{ {
// only physically seek if necessary // only physically seek if necessary
if ( p_current_chapter == NULL || if ( p_current_chapter == NULL ||
( p_current_chapter->p_chapter->i_end_time != p_cur_chapter->p_chapter->i_start_time ) || ( p_current_chapter && p_current_chapter->p_segment != p_cur_chapter->p_segment ) ||
( p_current_chapter && p_current_chapter->p_segment != p_cur_chapter->p_segment ) ) ( p_current_chapter->p_chapter->i_end_time != p_cur_chapter->p_chapter->i_start_time ))
{ {
Seek( demux, p_cur_chapter->i_virtual_start_time, 0, p_cur_chapter, -1 ); Seek( demux, p_cur_chapter->i_virtual_start_time, 0, p_cur_chapter, -1 );
return true; return true;
...@@ -439,8 +448,8 @@ void virtual_segment_c::Seek( demux_t & demuxer, mtime_t i_date, mtime_t i_time_ ...@@ -439,8 +448,8 @@ void virtual_segment_c::Seek( demux_t & demuxer, mtime_t i_date, mtime_t i_time_
if ( p_chapter != NULL ) if ( p_chapter != NULL )
{ {
p_sys->i_chapter_time = i_time_offset = p_chapter->i_virtual_start_time - ( ( p_chapter->p_chapter )? p_chapter->p_chapter->i_start_time : 0 );
i_time_offset = p_chapter->i_virtual_start_time - ( ( p_chapter->p_chapter )? p_chapter->p_chapter->i_start_time : 0 ); p_sys->i_chapter_time = i_time_offset - p_chapter->p_segment->i_start_time;
if ( p_chapter->p_chapter && p_chapter->i_seekpoint_num > 0 ) if ( p_chapter->p_chapter && p_chapter->i_seekpoint_num > 0 )
{ {
demuxer.info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT; demuxer.info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
......
...@@ -63,9 +63,7 @@ public: ...@@ -63,9 +63,7 @@ public:
static bool CompareTimecode( const virtual_chapter_c * itemA, const virtual_chapter_c * itemB ) static bool CompareTimecode( const virtual_chapter_c * itemA, const virtual_chapter_c * itemB )
{ {
return ( itemA->i_virtual_start_time < itemB->i_virtual_start_time || return ( itemA->i_virtual_start_time < itemB->i_virtual_start_time );
( itemA->i_virtual_start_time == itemB->i_virtual_start_time &&
itemA->i_virtual_stop_time < itemB->i_virtual_stop_time ) );
} }
matroska_segment_c *p_segment; matroska_segment_c *p_segment;
......
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