net: hlssink3: Use closed fragment location in playlist generation

Currently, we incorrectly use the last location we generated, which is
the current in-flight fragment while generating a new playlist. Instead,
the playlist should use the fragment that was just close (i.e. the
previous fragment), so it does not refer to a fragment we have not yet
uploaded.

This is a bug that was copied over from how hlssink2 does things.

Fixes: https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/issues/701
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/2324>
This commit is contained in:
Arun Raghavan 2025-06-27 15:36:51 -04:00 committed by GStreamer Marge Bot
parent ab50ef2fb7
commit 5d4b23eb2c
2 changed files with 29 additions and 4 deletions

View file

@ -350,6 +350,20 @@ impl HlsBaseSink {
}
}
pub fn get_location(&self, fragment_id: u32) -> Option<String> {
let mut state = self.state.lock().unwrap();
let context = match state.context.as_mut() {
Some(context) => context,
None => {
gst::error!(CAT, imp = self, "Playlist is not configured",);
return None;
}
};
sprintf::sprintf!(&context.segment_template, fragment_id).ok()
}
pub fn get_fragment_stream(&self, fragment_id: u32) -> Option<(gio::OutputStream, String)> {
let mut state = self.state.lock().unwrap();
let context = match state.context.as_mut() {

View file

@ -583,15 +583,28 @@ impl HlsSink3 {
CAT,
imp = self,
"New segment location: {:?}",
state.current_segment_location.as_ref()
segment_file_location,
);
Ok(segment_file_location)
}
fn on_fragment_closed(&self, s: &gst::StructureRef, closed_at: gst::ClockTime) {
let obj = self.obj();
let base_imp = obj.upcast_ref::<HlsBaseSink>().imp();
let mut state = self.state.lock().unwrap();
let location = match state.current_segment_location.take() {
let location = match s
.get::<u32>("fragment-id")
.ok()
// Try to get the location of the fragment we just closed, if splitmuxsink gave us the
// fragment id (1.26+)
.and_then(|fragment_id| base_imp.get_location(fragment_id))
// Else fallback to the last fragment location we generated, which is techincally wrong
// (because this is the current fragment in progress, not the last fragment closed)
.or_else(|| state.current_segment_location.take())
{
Some(location) => location,
None => {
gst::error!(CAT, imp = self, "Unknown segment location");
@ -628,8 +641,6 @@ impl HlsSink3 {
drop(state);
let obj = self.obj();
let base_imp = obj.upcast_ref::<HlsBaseSink>().imp();
let uri = base_imp.get_segment_uri(&location, None);
let _ = base_imp.add_segment(
&location,