hlsbasesink: Add enable-endlist property

Write "EXT-X-ENDLIST" tag at the end of stream if enabled, and
default to "TRUE" which is the hlssink2's behavior as well

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1306>
This commit is contained in:
Seungha Yang 2023-09-04 22:09:55 +09:00
parent 7835d78b3d
commit 52117e4b11
3 changed files with 21 additions and 14 deletions

View file

@ -36,6 +36,7 @@ const DEFAULT_SEND_KEYFRAME_REQUESTS: bool = true;
const DEFAULT_SYNC: bool = true; const DEFAULT_SYNC: bool = true;
const DEFAULT_LATENCY: gst::ClockTime = const DEFAULT_LATENCY: gst::ClockTime =
gst::ClockTime::from_mseconds((DEFAULT_TARGET_DURATION * 500) as u64); gst::ClockTime::from_mseconds((DEFAULT_TARGET_DURATION * 500) as u64);
const DEFAULT_ENDLIST: bool = true;
const SIGNAL_GET_PLAYLIST_STREAM: &str = "get-playlist-stream"; const SIGNAL_GET_PLAYLIST_STREAM: &str = "get-playlist-stream";
const SIGNAL_GET_INIT_STREAM: &str = "get-init-stream"; const SIGNAL_GET_INIT_STREAM: &str = "get-init-stream";
@ -81,6 +82,7 @@ struct Settings {
max_num_segment_files: usize, max_num_segment_files: usize,
enable_program_date_time: bool, enable_program_date_time: bool,
pdt_follows_pipeline_clock: bool, pdt_follows_pipeline_clock: bool,
enable_endlist: bool,
} }
impl Default for Settings { impl Default for Settings {
@ -92,6 +94,7 @@ impl Default for Settings {
max_num_segment_files: DEFAULT_MAX_NUM_SEGMENT_FILES as usize, max_num_segment_files: DEFAULT_MAX_NUM_SEGMENT_FILES as usize,
enable_program_date_time: DEFAULT_PROGRAM_DATE_TIME_TAG, enable_program_date_time: DEFAULT_PROGRAM_DATE_TIME_TAG,
pdt_follows_pipeline_clock: DEFAULT_CLOCK_TRACKING_FOR_PDT, pdt_follows_pipeline_clock: DEFAULT_CLOCK_TRACKING_FOR_PDT,
enable_endlist: DEFAULT_ENDLIST,
} }
} }
} }
@ -169,6 +172,11 @@ impl ObjectImpl for HlsBaseSink {
.blurb("As there might be drift between the wallclock and pipeline clock, this controls whether the Program-Date-Time markers should follow the pipeline clock rate (true), or be skewed to match the wallclock rate (false).") .blurb("As there might be drift between the wallclock and pipeline clock, this controls whether the Program-Date-Time markers should follow the pipeline clock rate (true), or be skewed to match the wallclock rate (false).")
.default_value(DEFAULT_CLOCK_TRACKING_FOR_PDT) .default_value(DEFAULT_CLOCK_TRACKING_FOR_PDT)
.build(), .build(),
glib::ParamSpecBoolean::builder("enable-endlist")
.nick("Enable Endlist")
.blurb("Write \"EXT-X-ENDLIST\" tag to manifest at the end of stream")
.default_value(DEFAULT_ENDLIST)
.build(),
] ]
}); });
@ -202,6 +210,9 @@ impl ObjectImpl for HlsBaseSink {
"pdt-follows-pipeline-clock" => { "pdt-follows-pipeline-clock" => {
settings.pdt_follows_pipeline_clock = value.get().expect("type checked upstream"); settings.pdt_follows_pipeline_clock = value.get().expect("type checked upstream");
} }
"enable-endlist" => {
settings.enable_endlist = value.get().expect("type checked upstream");
}
_ => unimplemented!(), _ => unimplemented!(),
}; };
} }
@ -218,6 +229,7 @@ impl ObjectImpl for HlsBaseSink {
"playlist-length" => settings.playlist_length.to_value(), "playlist-length" => settings.playlist_length.to_value(),
"enable-program-date-time" => settings.enable_program_date_time.to_value(), "enable-program-date-time" => settings.enable_program_date_time.to_value(),
"pdt-follows-pipeline-clock" => settings.pdt_follows_pipeline_clock.to_value(), "pdt-follows-pipeline-clock" => settings.pdt_follows_pipeline_clock.to_value(),
"enable-endlist" => settings.enable_endlist.to_value(),
_ => unimplemented!(), _ => unimplemented!(),
} }
} }
@ -335,7 +347,9 @@ impl HlsBaseSink {
let mut state = self.state.lock().unwrap(); let mut state = self.state.lock().unwrap();
if let Some(mut context) = state.context.take() { if let Some(mut context) = state.context.take() {
if context.playlist.is_rendering() { if context.playlist.is_rendering() {
context.playlist.stop(); context
.playlist
.stop(self.settings.lock().unwrap().enable_endlist);
let _ = self.write_playlist(&mut context); let _ = self.write_playlist(&mut context);
} }
} }

View file

@ -79,19 +79,10 @@ impl Playlist {
} }
/// Sets the playlist to stopped state. /// Sets the playlist to stopped state.
pub fn stop(&mut self) { pub fn stop(&mut self, write_endlist: bool) {
match &self.inner.playlist_type { self.inner.end_list = write_endlist;
None => self.inner.end_list = false, if self.turn_vod {
Some(defined) => match defined { self.inner.playlist_type = Some(MediaPlaylistType::Vod);
MediaPlaylistType::Other(_) => unreachable!(),
MediaPlaylistType::Event => {
if self.turn_vod {
self.inner.playlist_type = Some(MediaPlaylistType::Vod);
}
self.inner.end_list = true
}
MediaPlaylistType::Vod => self.inner.end_list = false,
},
} }
} }

View file

@ -240,6 +240,7 @@ fn test_hlssink3_element_with_video_content() -> Result<(), ()> {
segment00003.ts segment00003.ts
#EXTINF:0.3, #EXTINF:0.3,
segment00004.ts segment00004.ts
#EXT-X-ENDLIST
"###, "###,
contents.to_string() contents.to_string()
); );
@ -432,6 +433,7 @@ fn test_hlssink3_write_correct_playlist_content() -> Result<(), ()> {
#EXT-X-MEDIA-SEQUENCE:1 #EXT-X-MEDIA-SEQUENCE:1
#EXTINF:1.633, #EXTINF:1.633,
segments/my-own-filename-000.ts segments/my-own-filename-000.ts
#EXT-X-ENDLIST
"###, "###,
contents.to_string() contents.to_string()
); );