uriplaylistbin: allow to change 'iterations' property while playing

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1492>
This commit is contained in:
Guillaume Desmottes 2024-02-14 13:06:19 +01:00
parent 00b56ca845
commit 61c9cbdc8f
3 changed files with 105 additions and 16 deletions

View file

@ -10590,7 +10590,7 @@
"default": "1", "default": "1",
"max": "-1", "max": "-1",
"min": "0", "min": "0",
"mutable": "ready", "mutable": "playing",
"readable": true, "readable": true,
"type": "guint", "type": "guint",
"writable": true "writable": true

View file

@ -81,6 +81,10 @@ impl State {
current_uri_index: 0, current_uri_index: 0,
} }
} }
fn update_iterations(&mut self, iterations: u32) {
self.playlist.iterations = iterations;
}
} }
#[derive(Default)] #[derive(Default)]
@ -189,7 +193,7 @@ impl ObjectImpl for UriPlaylistBin {
.nick("Iterations") .nick("Iterations")
.blurb("Number of time the playlist items should be played each (0 = unlimited)") .blurb("Number of time the playlist items should be played each (0 = unlimited)")
.default_value(1) .default_value(1)
.mutable_ready() .mutable_playing()
.build(), .build(),
glib::ParamSpecUInt::builder("current-iteration") glib::ParamSpecUInt::builder("current-iteration")
.nick("Current iteration") .nick("Current iteration")
@ -222,16 +226,25 @@ impl ObjectImpl for UriPlaylistBin {
settings.uris = new_value; settings.uris = new_value;
} }
"iterations" => { "iterations" => {
let mut settings = self.settings.lock().unwrap();
let new_value = value.get().expect("type checked upstream"); let new_value = value.get().expect("type checked upstream");
gst::info!( {
CAT, let mut settings = self.settings.lock().unwrap();
imp: self, gst::info!(
"Changing iterations from {:?} to {:?}", CAT,
settings.iterations, imp: self,
new_value, "Changing iterations from {:?} to {:?}",
); settings.iterations,
settings.iterations = new_value; new_value,
);
settings.iterations = new_value;
}
{
let mut state = self.state.lock().unwrap();
if let Some(state) = state.as_mut() {
state.update_iterations(new_value);
}
}
} }
_ => unimplemented!(), _ => unimplemented!(),
} }

View file

@ -71,11 +71,19 @@ fn init() {
}); });
} }
struct IterationsChange {
/// change the uriplaylistbin iterations property when receiving the nth stream-start event
when_ss: u32,
/// new 'iterations' value
iterations: u32,
}
fn test( fn test(
medias: Vec<TestMedia>, medias: Vec<TestMedia>,
n_streams: u32, n_streams: u32,
iterations: u32, iterations: u32,
check_streams: bool, check_streams: bool,
iterations_change: Option<IterationsChange>,
) -> (Vec<gst::Message>, u32, u64) { ) -> (Vec<gst::Message>, u32, u64) {
init(); init();
@ -128,6 +136,7 @@ fn test(
let bus = pipeline.bus().unwrap(); let bus = pipeline.bus().unwrap();
let mut events = vec![]; let mut events = vec![];
let mut n_stream_start = 0;
loop { loop {
let msg = bus.iter_timed(gst::ClockTime::NONE).next().unwrap(); let msg = bus.iter_timed(gst::ClockTime::NONE).next().unwrap();
@ -153,6 +162,14 @@ fn test(
events.push(msg.clone()) events.push(msg.clone())
} }
MessageView::StreamsSelected(_) => events.push(msg.clone()), MessageView::StreamsSelected(_) => events.push(msg.clone()),
MessageView::StreamStart(_) => {
n_stream_start += 1;
if let Some(change) = &iterations_change {
if change.when_ss == n_stream_start {
playlist.set_property("iterations", change.iterations);
}
}
}
_ => {} _ => {}
} }
} }
@ -253,7 +270,8 @@ fn assert_stream_selected(msg: gst::Message, n_streams: usize) -> gst::Object {
#[test] #[test]
fn single_audio() { fn single_audio() {
let (events, current_iteration, current_uri_index) = test(vec![TestMedia::ogg()], 1, 1, true); let (events, current_iteration, current_uri_index) =
test(vec![TestMedia::ogg()], 1, 1, true, None);
assert_eos(events.into_iter().last().unwrap()); assert_eos(events.into_iter().last().unwrap());
assert_eq!(current_iteration, 0); assert_eq!(current_iteration, 0);
assert_eq!(current_uri_index, 0); assert_eq!(current_uri_index, 0);
@ -261,7 +279,8 @@ fn single_audio() {
#[test] #[test]
fn single_video() { fn single_video() {
let (events, current_iteration, current_uri_index) = test(vec![TestMedia::mkv()], 2, 1, true); let (events, current_iteration, current_uri_index) =
test(vec![TestMedia::mkv()], 2, 1, true, None);
assert_eos(events.into_iter().last().unwrap()); assert_eos(events.into_iter().last().unwrap());
assert_eq!(current_iteration, 0); assert_eq!(current_iteration, 0);
assert_eq!(current_uri_index, 0); assert_eq!(current_uri_index, 0);
@ -274,6 +293,7 @@ fn multi_audio() {
1, 1,
1, 1,
true, true,
None,
); );
assert_eos(events.into_iter().last().unwrap()); assert_eos(events.into_iter().last().unwrap());
assert_eq!(current_iteration, 0); assert_eq!(current_iteration, 0);
@ -283,7 +303,7 @@ fn multi_audio() {
#[test] #[test]
fn multi_audio_video() { fn multi_audio_video() {
let (events, current_iteration, current_uri_index) = let (events, current_iteration, current_uri_index) =
test(vec![TestMedia::mkv(), TestMedia::mkv()], 2, 1, true); test(vec![TestMedia::mkv(), TestMedia::mkv()], 2, 1, true, None);
assert_eos(events.into_iter().last().unwrap()); assert_eos(events.into_iter().last().unwrap());
assert_eq!(current_iteration, 0); assert_eq!(current_iteration, 0);
assert_eq!(current_uri_index, 1); assert_eq!(current_uri_index, 1);
@ -292,7 +312,7 @@ fn multi_audio_video() {
#[test] #[test]
fn iterations() { fn iterations() {
let (events, current_iteration, current_uri_index) = let (events, current_iteration, current_uri_index) =
test(vec![TestMedia::mkv(), TestMedia::mkv()], 2, 2, true); test(vec![TestMedia::mkv(), TestMedia::mkv()], 2, 2, true, None);
assert_eos(events.into_iter().last().unwrap()); assert_eos(events.into_iter().last().unwrap());
assert_eq!(current_iteration, 1); assert_eq!(current_iteration, 1);
assert_eq!(current_uri_index, 1); assert_eq!(current_uri_index, 1);
@ -303,7 +323,7 @@ fn iterations() {
#[ignore] #[ignore]
fn nb_streams_increasing() { fn nb_streams_increasing() {
let (events, current_iteration, current_uri_index) = let (events, current_iteration, current_uri_index) =
test(vec![TestMedia::ogg(), TestMedia::mkv()], 2, 1, false); test(vec![TestMedia::ogg(), TestMedia::mkv()], 2, 1, false, None);
assert_eos(events.into_iter().last().unwrap()); assert_eos(events.into_iter().last().unwrap());
assert_eq!(current_iteration, 0); assert_eq!(current_iteration, 0);
assert_eq!(current_uri_index, 1); assert_eq!(current_uri_index, 1);
@ -316,6 +336,7 @@ fn missing_file() {
1, 1,
1, 1,
false, false,
None,
); );
assert_error( assert_error(
events.into_iter().last().unwrap(), events.into_iter().last().unwrap(),
@ -332,6 +353,7 @@ fn missing_http() {
1, 1,
1, 1,
false, false,
None,
); );
assert_error( assert_error(
events.into_iter().last().unwrap(), events.into_iter().last().unwrap(),
@ -340,3 +362,57 @@ fn missing_http() {
assert_eq!(current_iteration, 0); assert_eq!(current_iteration, 0);
assert_eq!(current_uri_index, 0); assert_eq!(current_uri_index, 0);
} }
#[test]
/// increase playlist iterations while it's playing
fn increase_iterations() {
let (events, current_iteration, current_uri_index) = test(
vec![TestMedia::mkv()],
2,
4,
false,
Some(IterationsChange {
when_ss: 2,
iterations: 8,
}),
);
assert_eos(events.into_iter().last().unwrap());
assert_eq!(current_iteration, 7);
assert_eq!(current_uri_index, 0);
}
#[test]
/// decrease playlist iterations while it's playing
fn decrease_iterations() {
let (events, current_iteration, current_uri_index) = test(
vec![TestMedia::mkv()],
2,
4,
false,
Some(IterationsChange {
when_ss: 2,
iterations: 1,
}),
);
assert_eos(events.into_iter().last().unwrap());
assert_eq!(current_iteration, 2);
assert_eq!(current_uri_index, 0);
}
#[test]
/// change an infinite playlist to a finite one
fn infinite_to_finite() {
let (events, current_iteration, current_uri_index) = test(
vec![TestMedia::mkv()],
2,
0,
false,
Some(IterationsChange {
when_ss: 2,
iterations: 4,
}),
);
assert_eos(events.into_iter().last().unwrap());
assert_eq!(current_iteration, 3);
assert_eq!(current_uri_index, 0);
}