LibMedia: Adjust Matroska seeking based on SeekPreRoll

This is important for seeking Opus tracks, as Opus needs to decode a
certain amount of input data before its output converges. Without this,
audio after a seek can sound muffled briefly.
This commit is contained in:
Zaggy1024 2025-10-21 15:32:16 -05:00 committed by Jelle Raaijmakers
parent 31c751ee92
commit e72080b15f
Notes: github-actions[bot] 2025-11-21 10:03:50 +00:00
2 changed files with 10 additions and 0 deletions

View file

@ -135,6 +135,8 @@ public:
void set_timestamp_scale(double timestamp_scale) { m_timestamp_scale = timestamp_scale; }
u64 codec_delay() const { return m_codec_delay; }
void set_codec_delay(u64 codec_delay) { m_codec_delay = codec_delay; }
u64 seek_pre_roll() const { return m_seek_pre_roll; }
void set_seek_pre_roll(u64 seek_pre_roll) { m_seek_pre_roll = seek_pre_roll; }
u64 timestamp_offset() const { return m_timestamp_offset; }
void set_timestamp_offset(u64 timestamp_offset) { m_timestamp_offset = timestamp_offset; }
Optional<VideoTrack> video_track() const { return m_video_track; }
@ -153,6 +155,7 @@ private:
FixedArray<u8> m_codec_private_data;
double m_timestamp_scale { 1 };
u64 m_codec_delay { 0 };
u64 m_seek_pre_roll { 0 };
u64 m_timestamp_offset { 0 };
Optional<VideoTrack> m_video_track;
Optional<AudioTrack> m_audio_track;

View file

@ -57,6 +57,7 @@ constexpr u32 TRACK_LANGUAGE_BCP_47_ID = 0x22B59D;
constexpr u32 TRACK_CODEC_ID = 0x86;
constexpr u32 TRACK_CODEC_PRIVATE_ID = 0x63A2;
constexpr u32 TRACK_CODEC_DELAY_ID = 0x56AA;
constexpr u32 TRACK_SEEK_PRE_ROLL_ID = 0x56BB;
constexpr u32 TRACK_TIMESTAMP_SCALE_ID = 0x23314F;
constexpr u32 TRACK_OFFSET_ID = 0x537F;
constexpr u32 TRACK_VIDEO_ID = 0xE0;
@ -512,6 +513,10 @@ static DecoderErrorOr<NonnullRefPtr<TrackEntry>> parse_track_entry(Streamer& str
track_entry->set_codec_delay(TRY_READ(streamer.read_u64()));
dbgln_if(MATROSKA_TRACE_DEBUG, "Read Track's CodecDelay attribute: {}", track_entry->codec_delay());
break;
case TRACK_SEEK_PRE_ROLL_ID:
track_entry->set_seek_pre_roll(TRY_READ(streamer.read_u64()));
dbgln_if(MATROSKA_TRACE_DEBUG, "Read Track's SeekPreRoll attribute: {}", track_entry->seek_pre_roll());
break;
case TRACK_TIMESTAMP_SCALE_ID:
track_entry->set_timestamp_scale(TRY_READ(streamer.read_float()));
dbgln_if(MATROSKA_TRACE_DEBUG, "Read Track's TrackTimestampScale attribute: {}", track_entry->timestamp_scale());
@ -1090,6 +1095,8 @@ DecoderErrorOr<bool> Reader::has_cues_for_track(u64 track_number)
DecoderErrorOr<SampleIterator> Reader::seek_to_random_access_point(SampleIterator iterator, AK::Duration timestamp)
{
timestamp -= AK::Duration::from_nanoseconds(AK::clamp_to<i64>(iterator.m_track->seek_pre_roll()));
if (TRY(has_cues_for_track(iterator.m_track->track_number()))) {
TRY(seek_to_cue_for_timestamp(iterator, timestamp));
VERIFY(iterator.last_timestamp().has_value());