From ae7f82591bbbbb64c6d97f458a8259338e4ae03e Mon Sep 17 00:00:00 2001 From: Zaggy1024 Date: Thu, 11 Sep 2025 18:37:06 -0500 Subject: [PATCH] LibMedia: Separate file duration from track duration in Demuxer Most users will only care about the total file duration, and shouldn't be required to determine the file duration from multiple track durations. To facilitate that, add a total_duration() function that returns the demuxer's duration not associated to any particular track. --- .../Containers/Matroska/MatroskaDemuxer.cpp | 9 ++++++++- .../Containers/Matroska/MatroskaDemuxer.h | 3 ++- Libraries/LibMedia/Demuxer.h | 3 ++- Libraries/LibMedia/FFmpeg/FFmpegDemuxer.cpp | 20 +++++++++---------- Libraries/LibMedia/FFmpeg/FFmpegDemuxer.h | 4 ++-- Libraries/LibMedia/PlaybackManager.cpp | 2 +- 6 files changed, 25 insertions(+), 16 deletions(-) diff --git a/Libraries/LibMedia/Containers/Matroska/MatroskaDemuxer.cpp b/Libraries/LibMedia/Containers/Matroska/MatroskaDemuxer.cpp index 572b4c5121f..ce093849712 100644 --- a/Libraries/LibMedia/Containers/Matroska/MatroskaDemuxer.cpp +++ b/Libraries/LibMedia/Containers/Matroska/MatroskaDemuxer.cpp @@ -4,7 +4,9 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include #include "MatroskaDemuxer.h" @@ -192,10 +194,15 @@ DecoderErrorOr MatroskaDemuxer::get_next_sample_for_track(Track track) return Sample(status.block->timestamp(), move(sample_data), VideoSampleData(cicp)); } -DecoderErrorOr MatroskaDemuxer::duration(Track) +DecoderErrorOr MatroskaDemuxer::total_duration() { auto duration = TRY(m_reader.segment_information()).duration(); return duration.value_or(AK::Duration::zero()); } +DecoderErrorOr MatroskaDemuxer::duration_of_track(Track const&) +{ + return total_duration(); +} + } diff --git a/Libraries/LibMedia/Containers/Matroska/MatroskaDemuxer.h b/Libraries/LibMedia/Containers/Matroska/MatroskaDemuxer.h index 6fb3f724dca..a85a2d653f4 100644 --- a/Libraries/LibMedia/Containers/Matroska/MatroskaDemuxer.h +++ b/Libraries/LibMedia/Containers/Matroska/MatroskaDemuxer.h @@ -32,7 +32,8 @@ public: DecoderErrorOr> seek_to_most_recent_keyframe(Track track, AK::Duration timestamp, Optional earliest_available_sample = OptionalNone()) override; - DecoderErrorOr duration(Track track) override; + DecoderErrorOr duration_of_track(Track const& track) override; + DecoderErrorOr total_duration() override; DecoderErrorOr get_codec_id_for_track(Track track) override; diff --git a/Libraries/LibMedia/Demuxer.h b/Libraries/LibMedia/Demuxer.h index d2b4ffefd8f..c2b1b4ed133 100644 --- a/Libraries/LibMedia/Demuxer.h +++ b/Libraries/LibMedia/Demuxer.h @@ -36,7 +36,8 @@ public: // in the case that the timestamp is closer to the current time than the nearest keyframe. virtual DecoderErrorOr> seek_to_most_recent_keyframe(Track track, AK::Duration timestamp, Optional earliest_available_sample = OptionalNone()) = 0; - virtual DecoderErrorOr duration(Track track) = 0; + virtual DecoderErrorOr duration_of_track(Track const&) = 0; + virtual DecoderErrorOr total_duration() = 0; }; } diff --git a/Libraries/LibMedia/FFmpeg/FFmpegDemuxer.cpp b/Libraries/LibMedia/FFmpeg/FFmpegDemuxer.cpp index 98b833e8ae6..940d7551e41 100644 --- a/Libraries/LibMedia/FFmpeg/FFmpegDemuxer.cpp +++ b/Libraries/LibMedia/FFmpeg/FFmpegDemuxer.cpp @@ -68,6 +68,15 @@ static inline AK::Duration time_units_to_duration(i64 time_units, AVRational con return time_units_to_duration(time_units, time_base.num, time_base.den); } +DecoderErrorOr FFmpegDemuxer::total_duration() +{ + if (m_format_context->duration < 0) { + return DecoderError::format(DecoderErrorCategory::Unknown, "Negative stream duration"); + } + + return time_units_to_duration(m_format_context->duration, 1, AV_TIME_BASE); +} + DecoderErrorOr FFmpegDemuxer::duration_of_track(Track const& track) { VERIFY(track.identifier() < m_format_context->nb_streams); @@ -78,11 +87,7 @@ DecoderErrorOr FFmpegDemuxer::duration_of_track(Track const& track } // If the stream doesn't specify the duration, fallback to what the container says the duration is. - // If the container doesn't know the duration, then we're out of luck. Return an error. - if (m_format_context->duration < 0) - return DecoderError::format(DecoderErrorCategory::Unknown, "Negative stream duration"); - - return time_units_to_duration(m_format_context->duration, 1, AV_TIME_BASE); + return total_duration(); } DecoderErrorOr FFmpegDemuxer::get_track_for_stream_index(u32 stream_index) @@ -144,11 +149,6 @@ DecoderErrorOr> FFmpegDemuxer::seek_to_most_recent_keyfra return timestamp; } -DecoderErrorOr FFmpegDemuxer::duration(Track track) -{ - return duration_of_track(track); -} - DecoderErrorOr FFmpegDemuxer::get_codec_id_for_track(Track track) { VERIFY(track.identifier() < m_format_context->nb_streams); diff --git a/Libraries/LibMedia/FFmpeg/FFmpegDemuxer.h b/Libraries/LibMedia/FFmpeg/FFmpegDemuxer.h index 5779315ee54..029b444b0a5 100644 --- a/Libraries/LibMedia/FFmpeg/FFmpegDemuxer.h +++ b/Libraries/LibMedia/FFmpeg/FFmpegDemuxer.h @@ -30,7 +30,8 @@ public: virtual DecoderErrorOr> seek_to_most_recent_keyframe(Track track, AK::Duration timestamp, Optional earliest_available_sample = OptionalNone()) override; - virtual DecoderErrorOr duration(Track track) override; + virtual DecoderErrorOr duration_of_track(Track const&) override; + virtual DecoderErrorOr total_duration() override; virtual DecoderErrorOr get_codec_id_for_track(Track track) override; @@ -39,7 +40,6 @@ public: virtual DecoderErrorOr get_next_sample_for_track(Track track) override; private: - DecoderErrorOr duration_of_track(Track const& track); DecoderErrorOr get_track_for_stream_index(u32 stream_index); NonnullOwnPtr m_stream; diff --git a/Libraries/LibMedia/PlaybackManager.cpp b/Libraries/LibMedia/PlaybackManager.cpp index cc2c8e0179c..c196f7597a0 100644 --- a/Libraries/LibMedia/PlaybackManager.cpp +++ b/Libraries/LibMedia/PlaybackManager.cpp @@ -90,7 +90,7 @@ AK::Duration PlaybackManager::duration() { auto duration_result = ({ auto demuxer_locker = Threading::MutexLocker(m_decoder_mutex); - m_demuxer->duration(m_selected_video_track); + m_demuxer->duration_of_track(m_selected_video_track); }); if (duration_result.is_error()) { dispatch_decoder_error(duration_result.release_error());