Commit cdf5d257 authored by Laurent Aimar's avatar Laurent Aimar Committed by Jean-Baptiste Kempf

Fixed mkv seeking when simpleblock is used for video.

(cherry picked from commit 2c172c17)

This fixes the long-standing bug #3026, aka, VLC can't seek properly in most HD movies from p2p networks :)
Signed-off-by: default avatarJean-Baptiste Kempf <jb@videolan.org>
parent 4d5947dc
...@@ -610,8 +610,6 @@ void matroska_segment_c::Seek( mtime_t i_date, mtime_t i_time_offset, int64_t i_ ...@@ -610,8 +610,6 @@ void matroska_segment_c::Seek( mtime_t i_date, mtime_t i_time_offset, int64_t i_
KaxSimpleBlock *simpleblock; KaxSimpleBlock *simpleblock;
int i_track_skipping; int i_track_skipping;
int64_t i_block_duration; int64_t i_block_duration;
int64_t i_block_ref1;
int64_t i_block_ref2;
size_t i_track; size_t i_track;
int64_t i_seek_position = i_start_pos; int64_t i_seek_position = i_start_pos;
int64_t i_seek_time = i_start_time; int64_t i_seek_time = i_start_time;
...@@ -694,7 +692,9 @@ void matroska_segment_c::Seek( mtime_t i_date, mtime_t i_time_offset, int64_t i_ ...@@ -694,7 +692,9 @@ void matroska_segment_c::Seek( mtime_t i_date, mtime_t i_time_offset, int64_t i_
while( i_track_skipping > 0 ) while( i_track_skipping > 0 )
{ {
if( BlockGet( block, simpleblock, &i_block_ref1, &i_block_ref2, &i_block_duration ) ) bool b_key_picture;
bool b_discardable_picture;
if( BlockGet( block, simpleblock, &b_key_picture, &b_discardable_picture, &i_block_duration ) )
{ {
msg_Warn( &sys.demuxer, "cannot get block EOF?" ); msg_Warn( &sys.demuxer, "cannot get block EOF?" );
...@@ -724,14 +724,14 @@ void matroska_segment_c::Seek( mtime_t i_date, mtime_t i_time_offset, int64_t i_ ...@@ -724,14 +724,14 @@ void matroska_segment_c::Seek( mtime_t i_date, mtime_t i_time_offset, int64_t i_
} }
else if( tracks[i_track]->fmt.i_cat == VIDEO_ES ) else if( tracks[i_track]->fmt.i_cat == VIDEO_ES )
{ {
if( i_block_ref1 == 0 && tracks[i_track]->b_search_keyframe ) if( b_key_picture && tracks[i_track]->b_search_keyframe )
{ {
tracks[i_track]->b_search_keyframe = false; tracks[i_track]->b_search_keyframe = false;
i_track_skipping--; i_track_skipping--;
} }
if( !tracks[i_track]->b_search_keyframe ) if( !tracks[i_track]->b_search_keyframe )
{ {
BlockDecode( &sys.demuxer, block, simpleblock, sys.i_pts, 0, i_block_ref1 >= 0 || i_block_ref2 > 0 ); BlockDecode( &sys.demuxer, block, simpleblock, sys.i_pts, 0, b_key_picture || b_discardable_picture );
} }
} }
} }
...@@ -1250,12 +1250,13 @@ void matroska_segment_c::UnSelect( ) ...@@ -1250,12 +1250,13 @@ void matroska_segment_c::UnSelect( )
ep = NULL; ep = NULL;
} }
int matroska_segment_c::BlockGet( KaxBlock * & pp_block, KaxSimpleBlock * & pp_simpleblock, int64_t *pi_ref1, int64_t *pi_ref2, int64_t *pi_duration ) int matroska_segment_c::BlockGet( KaxBlock * & pp_block, KaxSimpleBlock * & pp_simpleblock, bool *pb_key_picture, bool *pb_discardable_picture, int64_t *pi_duration )
{ {
pp_simpleblock = NULL; pp_simpleblock = NULL;
pp_block = NULL; pp_block = NULL;
*pi_ref1 = 0;
*pi_ref2 = 0; *pb_key_picture = true;
*pb_discardable_picture = false;
for( ;; ) for( ;; )
{ {
...@@ -1275,6 +1276,11 @@ int matroska_segment_c::BlockGet( KaxBlock * & pp_block, KaxSimpleBlock * & pp_s ...@@ -1275,6 +1276,11 @@ int matroska_segment_c::BlockGet( KaxBlock * & pp_block, KaxSimpleBlock * & pp_s
pp_block = NULL; pp_block = NULL;
continue; continue;
} }
if( pp_simpleblock != NULL )
{
*pb_key_picture = pp_simpleblock->IsKeyframe();
*pb_discardable_picture = pp_simpleblock->IsDiscardable();
}
/* update the index */ /* update the index */
#define idx p_indexes[i_index - 1] #define idx p_indexes[i_index - 1]
...@@ -1284,7 +1290,7 @@ int matroska_segment_c::BlockGet( KaxBlock * & pp_block, KaxSimpleBlock * & pp_s ...@@ -1284,7 +1290,7 @@ int matroska_segment_c::BlockGet( KaxBlock * & pp_block, KaxSimpleBlock * & pp_s
idx.i_time = pp_simpleblock->GlobalTimecode() / (mtime_t)1000; idx.i_time = pp_simpleblock->GlobalTimecode() / (mtime_t)1000;
else else
idx.i_time = (*pp_block).GlobalTimecode() / (mtime_t)1000; idx.i_time = (*pp_block).GlobalTimecode() / (mtime_t)1000;
idx.b_key = *pi_ref1 == 0 ? true : false; idx.b_key = *pb_key_picture;
} }
#undef idx #undef idx
return VLC_SUCCESS; return VLC_SUCCESS;
...@@ -1398,14 +1404,11 @@ int matroska_segment_c::BlockGet( KaxBlock * & pp_block, KaxSimpleBlock * & pp_s ...@@ -1398,14 +1404,11 @@ int matroska_segment_c::BlockGet( KaxBlock * & pp_block, KaxSimpleBlock * & pp_s
KaxReferenceBlock &ref = *(KaxReferenceBlock*)el; KaxReferenceBlock &ref = *(KaxReferenceBlock*)el;
ref.ReadData( es.I_O() ); ref.ReadData( es.I_O() );
if( *pi_ref1 == 0 )
{ if( int64( ref ) < 0 )
*pi_ref1 = int64( ref ) * cluster->GlobalTimecodeScale(); *pb_key_picture = false;
} else if( int64( ref ) > 0 )
else if( *pi_ref2 == 0 ) *pb_discardable_picture = true;
{
*pi_ref2 = int64( ref ) * cluster->GlobalTimecodeScale();
}
} }
else if( MKV_IS_ID( el, KaxClusterSilentTrackNumber ) ) else if( MKV_IS_ID( el, KaxClusterSilentTrackNumber ) )
{ {
......
...@@ -148,7 +148,7 @@ public: ...@@ -148,7 +148,7 @@ public:
void LoadTags( KaxTags *tags ); void LoadTags( KaxTags *tags );
void InformationCreate( ); void InformationCreate( );
void Seek( mtime_t i_date, mtime_t i_time_offset, int64_t i_global_position ); void Seek( mtime_t i_date, mtime_t i_time_offset, int64_t i_global_position );
int BlockGet( KaxBlock * &, KaxSimpleBlock * &, int64_t *, int64_t *, int64_t *); int BlockGet( KaxBlock * &, KaxSimpleBlock * &, bool *, bool *, int64_t *);
int BlockFindTrackIndex( size_t *pi_track, int BlockFindTrackIndex( size_t *pi_track,
const KaxBlock *, const KaxSimpleBlock * ); const KaxBlock *, const KaxSimpleBlock * );
......
...@@ -673,10 +673,9 @@ static int Demux( demux_t *p_demux) ...@@ -673,10 +673,9 @@ static int Demux( demux_t *p_demux)
KaxBlock *block; KaxBlock *block;
KaxSimpleBlock *simpleblock; KaxSimpleBlock *simpleblock;
int64_t i_block_duration = 0; int64_t i_block_duration = 0;
int64_t i_block_ref1; bool b_key_picture;
int64_t i_block_ref2; bool b_discardable_picture;
if( p_segment->BlockGet( block, simpleblock, &b_key_picture, &b_discardable_picture, &i_block_duration ) )
if( p_segment->BlockGet( block, simpleblock, &i_block_ref1, &i_block_ref2, &i_block_duration ) )
{ {
if ( p_vsegment->Edition() && p_vsegment->Edition()->b_ordered ) if ( p_vsegment->Edition() && p_vsegment->Edition()->b_ordered )
{ {
...@@ -760,7 +759,7 @@ static int Demux( demux_t *p_demux) ...@@ -760,7 +759,7 @@ static int Demux( demux_t *p_demux)
continue; continue;
} }
BlockDecode( p_demux, block, simpleblock, p_sys->i_pts, i_block_duration, i_block_ref1 >= 0 || i_block_ref2 > 0 ); BlockDecode( p_demux, block, simpleblock, p_sys->i_pts, i_block_duration, b_key_picture || b_discardable_picture );
delete block; delete block;
i_block_count++; i_block_count++;
......
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