gstreamer: Add an EventViewMut accessor

Should make mutable access to events less verbose.

Fixes: https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/issues/474
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1448>
This commit is contained in:
Arun Raghavan 2024-05-31 13:42:18 +03:00 committed by GStreamer Marge Bot
parent f62c8658e4
commit d16b28fc2f
3 changed files with 150 additions and 3 deletions

View file

@ -30,9 +30,44 @@ fn example_main() {
let main_loop = glib::MainLoop::new(None, false); let main_loop = glib::MainLoop::new(None, false);
// This creates a pipeline by parsing the gst-launch pipeline syntax. // This creates a pipeline by parsing the gst-launch pipeline syntax.
let pipeline = gst::parse::launch("audiotestsrc ! fakesink").unwrap(); let pipeline = gst::parse::launch("audiotestsrc ! identity name=capsmut ! fakesink").unwrap();
let bus = pipeline.bus().unwrap(); let bus = pipeline.bus().unwrap();
// This is a contrived example to mutate events. This would normally be code inside an element,
// which might transform caps to reflect transformation in the data
let identity = pipeline
.downcast_ref::<gst::Bin>()
.unwrap()
.by_name("capsmut")
.unwrap();
let _ = identity.static_pad("sink").unwrap().add_probe(
gst::PadProbeType::EVENT_DOWNSTREAM,
move |_, probe_info| {
let Some(e) = probe_info.event() else {
return gst::PadProbeReturn::Ok;
};
if e.type_() != gst::EventType::Caps {
return gst::PadProbeReturn::Ok;
};
let mut ev = probe_info.take_event().unwrap();
let ev_ref = ev.make_mut();
let gst::EventViewMut::Caps(caps) = ev_ref.view_mut() else {
unreachable!()
};
caps.structure_mut().set("custom-field", true);
identity
.static_pad("src")
.unwrap()
.push_event(ev_ref.to_owned());
gst::PadProbeReturn::Drop
},
);
pipeline pipeline
.set_state(gst::State::Playing) .set_state(gst::State::Playing)
.expect("Unable to set the pipeline to the `Playing` state"); .expect("Unable to set the pipeline to the `Playing` state");

View file

@ -1,6 +1,8 @@
// Take a look at the license at the top of the repository in the LICENSE file. // Take a look at the license at the top of the repository in the LICENSE file.
use std::{borrow::Borrow, cmp, ffi::CStr, fmt, mem, num::NonZeroU32, ops::Deref, ptr}; use std::{
borrow::Borrow, cmp, ffi::CStr, fmt, mem, num::NonZeroU32, ops::Deref, ops::DerefMut, ptr,
};
use glib::{ use glib::{
translate::{FromGlibPtrContainer, *}, translate::{FromGlibPtrContainer, *},
@ -281,6 +283,49 @@ impl EventRef {
} }
} }
} }
pub fn view_mut(&mut self) -> EventViewMut {
unsafe {
let type_ = (*self.as_ptr()).type_;
match type_ {
ffi::GST_EVENT_FLUSH_START => FlushStart::view_mut(self),
ffi::GST_EVENT_FLUSH_STOP => FlushStop::view_mut(self),
ffi::GST_EVENT_STREAM_START => StreamStart::view_mut(self),
ffi::GST_EVENT_CAPS => Caps::view_mut(self),
ffi::GST_EVENT_SEGMENT => Segment::view_mut(self),
ffi::GST_EVENT_STREAM_COLLECTION => StreamCollection::view_mut(self),
ffi::GST_EVENT_TAG => Tag::view_mut(self),
ffi::GST_EVENT_BUFFERSIZE => Buffersize::view_mut(self),
ffi::GST_EVENT_SINK_MESSAGE => SinkMessage::view_mut(self),
ffi::GST_EVENT_STREAM_GROUP_DONE => StreamGroupDone::view_mut(self),
ffi::GST_EVENT_EOS => Eos::view_mut(self),
ffi::GST_EVENT_TOC => Toc::view_mut(self),
ffi::GST_EVENT_PROTECTION => Protection::view_mut(self),
ffi::GST_EVENT_SEGMENT_DONE => SegmentDone::view_mut(self),
ffi::GST_EVENT_GAP => Gap::view_mut(self),
#[cfg(feature = "v1_18")]
ffi::GST_EVENT_INSTANT_RATE_CHANGE => InstantRateChange::view_mut(self),
ffi::GST_EVENT_QOS => Qos::view_mut(self),
ffi::GST_EVENT_SEEK => Seek::view_mut(self),
ffi::GST_EVENT_NAVIGATION => Navigation::view_mut(self),
ffi::GST_EVENT_LATENCY => Latency::view_mut(self),
ffi::GST_EVENT_STEP => Step::view_mut(self),
ffi::GST_EVENT_RECONFIGURE => Reconfigure::view_mut(self),
ffi::GST_EVENT_TOC_SELECT => TocSelect::view_mut(self),
ffi::GST_EVENT_SELECT_STREAMS => SelectStreams::view_mut(self),
#[cfg(feature = "v1_18")]
ffi::GST_EVENT_INSTANT_RATE_SYNC_TIME => InstantRateSyncTime::view_mut(self),
ffi::GST_EVENT_CUSTOM_UPSTREAM => CustomUpstream::view_mut(self),
ffi::GST_EVENT_CUSTOM_DOWNSTREAM => CustomDownstream::view_mut(self),
ffi::GST_EVENT_CUSTOM_DOWNSTREAM_OOB => CustomDownstreamOob::view_mut(self),
ffi::GST_EVENT_CUSTOM_DOWNSTREAM_STICKY => CustomDownstreamSticky::view_mut(self),
ffi::GST_EVENT_CUSTOM_BOTH => CustomBoth::view_mut(self),
ffi::GST_EVENT_CUSTOM_BOTH_OOB => CustomBothOob::view_mut(self),
_ => Other::view_mut(self),
}
}
}
} }
impl fmt::Debug for Event { impl fmt::Debug for Event {
@ -347,6 +392,47 @@ pub enum EventView<'a> {
Other(&'a Other), Other(&'a Other),
} }
#[derive(Debug)]
#[non_exhaustive]
pub enum EventViewMut<'a> {
FlushStart(&'a mut FlushStart),
FlushStop(&'a mut FlushStop),
StreamStart(&'a mut StreamStart),
Caps(&'a mut Caps),
Segment(&'a mut Segment),
StreamCollection(&'a mut StreamCollection),
Tag(&'a mut Tag),
Buffersize(&'a mut Buffersize),
SinkMessage(&'a mut SinkMessage),
StreamGroupDone(&'a mut StreamGroupDone),
Eos(&'a mut Eos),
Toc(&'a mut Toc),
Protection(&'a mut Protection),
SegmentDone(&'a mut SegmentDone),
Gap(&'a mut Gap),
#[cfg(feature = "v1_18")]
#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
InstantRateChange(&'a mut InstantRateChange),
Qos(&'a mut Qos),
Seek(&'a mut Seek),
Navigation(&'a mut Navigation),
Latency(&'a mut Latency),
Step(&'a mut Step),
Reconfigure(&'a mut Reconfigure),
TocSelect(&'a mut TocSelect),
SelectStreams(&'a mut SelectStreams),
#[cfg(feature = "v1_18")]
#[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
InstantRateSyncTime(&'a mut InstantRateSyncTime),
CustomUpstream(&'a mut CustomUpstream),
CustomDownstream(&'a mut CustomDownstream),
CustomDownstreamOob(&'a mut CustomDownstreamOob),
CustomDownstreamSticky(&'a mut CustomDownstreamSticky),
CustomBoth(&'a mut CustomBoth),
CustomBothOob(&'a mut CustomBothOob),
Other(&'a mut Other),
}
macro_rules! declare_concrete_event { macro_rules! declare_concrete_event {
(@sticky $name:ident, $param:ident) => { (@sticky $name:ident, $param:ident) => {
declare_concrete_event!($name, $param); declare_concrete_event!($name, $param);
@ -370,11 +456,22 @@ macro_rules! declare_concrete_event {
unsafe { &*(self as *const Self as *const EventRef) } unsafe { &*(self as *const Self as *const EventRef) }
} }
#[inline]
pub fn event_mut(&mut self) -> &mut EventRef {
unsafe { &mut *(self as *mut Self as *mut EventRef) }
}
#[inline] #[inline]
unsafe fn view(event: &EventRef) -> EventView<'_> { unsafe fn view(event: &EventRef) -> EventView<'_> {
let event = &*(event as *const EventRef as *const Self); let event = &*(event as *const EventRef as *const Self);
EventView::$name(event) EventView::$name(event)
} }
#[inline]
unsafe fn view_mut(event: &mut EventRef) -> EventViewMut<'_> {
let event = &mut *(event as *mut EventRef as *mut Self);
EventViewMut::$name(event)
}
} }
impl Deref for $name { impl Deref for $name {
@ -386,6 +483,13 @@ macro_rules! declare_concrete_event {
} }
} }
impl DerefMut for $name {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
self.event_mut()
}
}
impl ToOwned for $name { impl ToOwned for $name {
type Owned = $name<Event>; type Owned = $name<Event>;
@ -413,6 +517,14 @@ macro_rules! declare_concrete_event {
} }
} }
impl DerefMut for $name<Event> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
debug_assert!(self.0.is_writable());
unsafe { &mut *(self.0.as_mut_ptr() as *mut Self::Target) }
}
}
impl Borrow<$name> for $name<Event> { impl Borrow<$name> for $name<Event> {
#[inline] #[inline]
fn borrow(&self) -> &$name { fn borrow(&self) -> &$name {

View file

@ -148,7 +148,7 @@ mod bufferlist_serde;
pub mod query; pub mod query;
pub use crate::query::{Query, QueryRef, QueryView, QueryViewMut}; pub use crate::query::{Query, QueryRef, QueryView, QueryViewMut};
pub mod event; pub mod event;
pub use crate::event::{Event, EventRef, EventView, GroupId, Seqnum}; pub use crate::event::{Event, EventRef, EventView, EventViewMut, GroupId, Seqnum};
pub mod context; pub mod context;
pub use crate::context::{Context, ContextRef}; pub use crate::context::{Context, ContextRef};
mod rank; mod rank;