diff --git a/docs/plugins/gst_plugins_cache.json b/docs/plugins/gst_plugins_cache.json index fafe1c1d..a6836361 100644 --- a/docs/plugins/gst_plugins_cache.json +++ b/docs/plugins/gst_plugins_cache.json @@ -7716,6 +7716,17 @@ } }, "properties": { + "event-types": { + "blurb": "Forward Event Types (default EOS)", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "mutable": "ready", + "readable": true, + "type": "GstValueArray", + "writable": true + }, "producer-name": { "blurb": "Producer Name to use", "conditionally-available": false, diff --git a/generic/inter/src/sink/imp.rs b/generic/inter/src/sink/imp.rs index eb5c699a..0274fc13 100644 --- a/generic/inter/src/sink/imp.rs +++ b/generic/inter/src/sink/imp.rs @@ -15,12 +15,14 @@ const DEFAULT_PRODUCER_NAME: &str = "default"; #[derive(Debug)] struct Settings { producer_name: String, + event_types: Vec, } impl Default for Settings { fn default() -> Self { Settings { producer_name: DEFAULT_PRODUCER_NAME.to_string(), + event_types: vec![gst::EventType::Eos], } } } @@ -41,9 +43,9 @@ impl InterSink { let settings = self.settings.lock().unwrap(); let state = self.state.lock().unwrap(); - InterStreamProducer::acquire(&settings.producer_name, &state.appsink)?; - - Ok(()) + InterStreamProducer::acquire(&settings.producer_name, &state.appsink).map(|producer| { + producer.set_forward_events(settings.event_types.clone()); + }) } fn unprepare(&self) { @@ -83,12 +85,28 @@ impl ObjectSubclass for InterSink { impl ObjectImpl for InterSink { fn properties() -> &'static [glib::ParamSpec] { static PROPERTIES: LazyLock> = LazyLock::new(|| { - vec![glib::ParamSpecString::builder("producer-name") - .nick("Producer Name") - .blurb("Producer Name to use") - .doc_show_default() - .mutable_playing() - .build()] + vec![ + glib::ParamSpecString::builder("producer-name") + .nick("Producer Name") + .blurb("Producer Name to use") + .doc_show_default() + .mutable_playing() + .build(), + gst::ParamSpecArray::builder("event-types") + .element_spec( + &glib::ParamSpecEnum::builder_with_default( + "event-type", + gst::EventType::Eos, + ) + .nick("Event Type") + .blurb("Event Type") + .build(), + ) + .nick("Forwarded Event Types") + .blurb("Forward Event Types (default EOS)") + .mutable_ready() + .build(), + ] }); PROPERTIES.as_ref() @@ -123,6 +141,16 @@ impl ObjectImpl for InterSink { } } } + "event-types" => { + let mut settings = self.settings.lock().unwrap(); + let types = value + .get::() + .expect("type checked upstream") + .iter() + .map(|v| v.get::().expect("type checked upstream")) + .collect::>(); + settings.event_types = types; + } _ => unimplemented!(), }; } @@ -133,6 +161,15 @@ impl ObjectImpl for InterSink { let settings = self.settings.lock().unwrap(); settings.producer_name.to_value() } + "event-types" => { + let settings = self.settings.lock().unwrap(); + settings + .event_types + .iter() + .map(|x| x.to_send_value()) + .collect::() + .to_value() + } _ => unimplemented!(), } } diff --git a/generic/inter/tests/inter.rs b/generic/inter/tests/inter.rs index bc7e746f..5170074b 100644 --- a/generic/inter/tests/inter.rs +++ b/generic/inter/tests/inter.rs @@ -136,3 +136,51 @@ fn test_change_producer_name() { element1.set_state(gst::State::Null).unwrap(); element2.set_state(gst::State::Null).unwrap(); } + +#[test] +#[serial] +fn test_event_forwarding() { + init(); + + let mut hc = start_consumer("p"); + let (srcpad, intersink) = start_producer("p"); + + intersink.set_state(gst::State::Null).unwrap(); + intersink.set_property( + "event-types", + gst::Array::new(vec![gst::EventType::Eos, gst::EventType::CustomDownstream]), + ); + intersink.set_state(gst::State::Playing).unwrap(); + + // FYI necessary push b/c: + // https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1875#note_2630453 + push_one(&srcpad, gst::ClockTime::from_nseconds(1)); + + let s = gst::Structure::builder("MyEvent") + .field("unsigned", 100u64) + .build(); + assert!(srcpad.push_event(gst::event::CustomDownstream::new(s))); + assert!(srcpad.push_event(gst::event::Eos::new())); + + let mut found = false; + loop { + use gst::EventView; + + if let Ok(event) = hc.pull_event() { + match event.view() { + EventView::CustomDownstream(e) => { + let v = e.structure().unwrap().get::("unsigned"); + assert!(v.is_ok_and(|v| v == 100u64)); + found = true; + break; + } + EventView::Eos(..) => { + break; + } + _ => (), + }; + } + } + intersink.set_state(gst::State::Null).unwrap(); + assert!(found); +}