mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 22:27:35 +00:00
LibVideo: Pass the current sample to demuxers to lazily seek better
In cases where the PlaybackManager's earliest buffered or displayed sample is closer to the seek target than the demuxer's chosen keyframe, we don't want to seek at all. To enable this, demuxers now receive an optional parameter with the earliest timestamp that the caller can still access. The demuxer in turn returns an optional to indicate when a seek was not needed, which allows PlaybackManager to avoid clearing its queue and re-decoding frames.
This commit is contained in:
parent
275d57eb6f
commit
3bfef8bfe0
7 changed files with 61 additions and 42 deletions
|
@ -806,7 +806,7 @@ DecoderErrorOr<void> Reader::seek_to_cue_for_timestamp(SampleIterator& iterator,
|
|||
return {};
|
||||
}
|
||||
|
||||
static DecoderErrorOr<bool> find_keyframe_before_timestamp(SampleIterator& iterator, Time const& timestamp)
|
||||
static DecoderErrorOr<void> search_clusters_for_keyframe_before_timestamp(SampleIterator& iterator, Time const& timestamp)
|
||||
{
|
||||
#if MATROSKA_DEBUG
|
||||
size_t inter_frames_count;
|
||||
|
@ -837,10 +837,9 @@ static DecoderErrorOr<bool> find_keyframe_before_timestamp(SampleIterator& itera
|
|||
dbgln("Seeked to a keyframe with {} inter frames to skip", inter_frames_count);
|
||||
#endif
|
||||
iterator = last_keyframe.release_value();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
DecoderErrorOr<bool> Reader::has_cues_for_track(u64 track_number)
|
||||
|
@ -849,37 +848,23 @@ DecoderErrorOr<bool> Reader::has_cues_for_track(u64 track_number)
|
|||
return m_cues.contains(track_number);
|
||||
}
|
||||
|
||||
DecoderErrorOr<void> Reader::seek_to_random_access_point(SampleIterator& iterator, Time timestamp)
|
||||
DecoderErrorOr<SampleIterator> Reader::seek_to_random_access_point(SampleIterator iterator, Time timestamp)
|
||||
{
|
||||
if (iterator.m_last_timestamp == timestamp)
|
||||
return {};
|
||||
|
||||
if (TRY(has_cues_for_track(iterator.m_track.track_number()))) {
|
||||
auto seeked_iterator = iterator;
|
||||
TRY(seek_to_cue_for_timestamp(seeked_iterator, timestamp));
|
||||
VERIFY(seeked_iterator.m_last_timestamp <= timestamp);
|
||||
|
||||
// We only need to seek to a keyframe if it's not faster to continue from the current position.
|
||||
if (timestamp < iterator.m_last_timestamp || seeked_iterator.m_last_timestamp > iterator.m_last_timestamp)
|
||||
iterator = seeked_iterator;
|
||||
return {};
|
||||
TRY(seek_to_cue_for_timestamp(iterator, timestamp));
|
||||
VERIFY(iterator.last_timestamp().has_value() && iterator.last_timestamp().value() <= timestamp);
|
||||
return iterator;
|
||||
}
|
||||
|
||||
// FIXME: This could cache the keyframes it finds. Is it worth doing? Probably not, most files will have Cues :^)
|
||||
if (timestamp < iterator.last_timestamp() || iterator.last_timestamp().is_negative()) {
|
||||
if (!iterator.last_timestamp().has_value() || timestamp < iterator.last_timestamp().value()) {
|
||||
// If the timestamp is before the iterator's current position, then we need to start from the beginning of the Segment.
|
||||
iterator = TRY(create_sample_iterator(iterator.m_track.track_number()));
|
||||
if (!TRY(find_keyframe_before_timestamp(iterator, timestamp)))
|
||||
return DecoderError::corrupted("No random access points found"sv);
|
||||
|
||||
return {};
|
||||
TRY(search_clusters_for_keyframe_before_timestamp(iterator, timestamp));
|
||||
return iterator;
|
||||
}
|
||||
|
||||
auto seeked_iterator = iterator;
|
||||
if (TRY(find_keyframe_before_timestamp(seeked_iterator, timestamp)))
|
||||
iterator = seeked_iterator;
|
||||
VERIFY(iterator.last_timestamp() <= timestamp);
|
||||
return {};
|
||||
TRY(search_clusters_for_keyframe_before_timestamp(iterator, timestamp));
|
||||
return iterator;
|
||||
}
|
||||
|
||||
DecoderErrorOr<Optional<Vector<CuePoint> const&>> Reader::cue_points_for_track(u64 track_number)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue