gstreamer_base/flow_combiner.rs
1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use crate::ffi;
4use glib::{prelude::*, translate::*};
5
6glib::wrapper! {
7 /// Utility struct to help handling [`gst::FlowReturn`][crate::gst::FlowReturn] combination. Useful for
8 /// [`gst::Element`][crate::gst::Element]<!-- -->s that have multiple source pads and need to combine
9 /// the different [`gst::FlowReturn`][crate::gst::FlowReturn] for those pads.
10 ///
11 /// [`FlowCombiner`][crate::FlowCombiner] works by using the last [`gst::FlowReturn`][crate::gst::FlowReturn] for all [`gst::Pad`][crate::gst::Pad]
12 /// it has in its list and computes the combined return value and provides
13 /// it to the caller.
14 ///
15 /// To add a new pad to the [`FlowCombiner`][crate::FlowCombiner] use [`add_pad()`][Self::add_pad()].
16 /// The new [`gst::Pad`][crate::gst::Pad] is stored with a default value of [`gst::FlowReturn::Ok`][crate::gst::FlowReturn::Ok].
17 ///
18 /// In case you want a [`gst::Pad`][crate::gst::Pad] to be removed, use [`remove_pad()`][Self::remove_pad()].
19 ///
20 /// Please be aware that this struct isn't thread safe as its designed to be
21 /// used by demuxers, those usually will have a single thread operating it.
22 ///
23 /// These functions will take refs on the passed [`gst::Pad`][crate::gst::Pad]<!-- -->s.
24 ///
25 /// Aside from reducing the user's code size, the main advantage of using this
26 /// helper struct is to follow the standard rules for [`gst::FlowReturn`][crate::gst::FlowReturn] combination.
27 /// These rules are:
28 ///
29 /// * [`gst::FlowReturn::Eos`][crate::gst::FlowReturn::Eos]: only if all returns are EOS too
30 /// * [`gst::FlowReturn::NotLinked`][crate::gst::FlowReturn::NotLinked]: only if all returns are NOT_LINKED too
31 /// * [`gst::FlowReturn::Error`][crate::gst::FlowReturn::Error] or below: if at least one returns an error return
32 /// * [`gst::FlowReturn::NotNegotiated`][crate::gst::FlowReturn::NotNegotiated]: if at least one returns a not-negotiated return
33 /// * [`gst::FlowReturn::Flushing`][crate::gst::FlowReturn::Flushing]: if at least one returns flushing
34 /// * [`gst::FlowReturn::Ok`][crate::gst::FlowReturn::Ok]: otherwise
35 ///
36 /// [`gst::FlowReturn::Error`][crate::gst::FlowReturn::Error] or below, GST_FLOW_NOT_NEGOTIATED and GST_FLOW_FLUSHING are
37 /// returned immediately from the [`update_flow()`][Self::update_flow()] function.
38 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
39 #[doc(alias = "GstFlowCombiner")]
40 pub struct FlowCombiner(Shared<ffi::GstFlowCombiner>);
41
42 match fn {
43 ref => |ptr| ffi::gst_flow_combiner_ref(ptr),
44 unref => |ptr| ffi::gst_flow_combiner_unref(ptr),
45 type_ => || ffi::gst_flow_combiner_get_type(),
46 }
47}
48
49impl FlowCombiner {
50 /// Creates a new [`FlowCombiner`][crate::FlowCombiner], use `gst_flow_combiner_free()` to free it.
51 ///
52 /// # Returns
53 ///
54 /// A new [`FlowCombiner`][crate::FlowCombiner]
55 #[doc(alias = "gst_flow_combiner_new")]
56 pub fn new() -> Self {
57 assert_initialized_main_thread!();
58 unsafe { from_glib_full(ffi::gst_flow_combiner_new()) }
59 }
60
61 /// Adds a new [`gst::Pad`][crate::gst::Pad] to the [`FlowCombiner`][crate::FlowCombiner].
62 /// ## `pad`
63 /// the [`gst::Pad`][crate::gst::Pad] that is being added
64 #[doc(alias = "gst_flow_combiner_add_pad")]
65 pub fn add_pad<P: IsA<gst::Pad>>(&self, pad: &P) {
66 unsafe {
67 ffi::gst_flow_combiner_add_pad(self.to_glib_none().0, pad.as_ref().to_glib_none().0);
68 }
69 }
70
71 /// Removes all pads from a [`FlowCombiner`][crate::FlowCombiner] and resets it to its initial state.
72 #[doc(alias = "gst_flow_combiner_clear")]
73 pub fn clear(&self) {
74 unsafe {
75 ffi::gst_flow_combiner_clear(self.to_glib_none().0);
76 }
77 }
78
79 /// Removes a [`gst::Pad`][crate::gst::Pad] from the [`FlowCombiner`][crate::FlowCombiner].
80 /// ## `pad`
81 /// the [`gst::Pad`][crate::gst::Pad] to remove
82 #[doc(alias = "gst_flow_combiner_remove_pad")]
83 pub fn remove_pad<P: IsA<gst::Pad>>(&self, pad: &P) {
84 unsafe {
85 ffi::gst_flow_combiner_remove_pad(self.to_glib_none().0, pad.as_ref().to_glib_none().0);
86 }
87 }
88
89 /// Reset flow combiner and all pads to their initial state without removing pads.
90 #[doc(alias = "gst_flow_combiner_reset")]
91 pub fn reset(&self) {
92 unsafe {
93 ffi::gst_flow_combiner_reset(self.to_glib_none().0);
94 }
95 }
96
97 /// Computes the combined flow return for the pads in it.
98 ///
99 /// The [`gst::FlowReturn`][crate::gst::FlowReturn] parameter should be the last flow return update for a pad
100 /// in this [`FlowCombiner`][crate::FlowCombiner]. It will use this value to be able to shortcut some
101 /// combinations and avoid looking over all pads again. e.g. The last combined
102 /// return is the same as the latest obtained [`gst::FlowReturn`][crate::gst::FlowReturn].
103 /// ## `fret`
104 /// the latest [`gst::FlowReturn`][crate::gst::FlowReturn] received for a pad in this [`FlowCombiner`][crate::FlowCombiner]
105 ///
106 /// # Returns
107 ///
108 /// The combined [`gst::FlowReturn`][crate::gst::FlowReturn]
109 #[doc(alias = "gst_flow_combiner_update_flow")]
110 pub fn update_flow<FRet: Into<gst::FlowReturn>>(
111 &self,
112 fret: FRet,
113 ) -> Result<gst::FlowSuccess, gst::FlowError> {
114 let fret: gst::FlowReturn = fret.into();
115 unsafe {
116 try_from_glib(ffi::gst_flow_combiner_update_flow(
117 self.to_glib_none().0,
118 fret.into_glib(),
119 ))
120 }
121 }
122
123 /// Sets the provided pad's last flow return to provided value and computes
124 /// the combined flow return for the pads in it.
125 ///
126 /// The [`gst::FlowReturn`][crate::gst::FlowReturn] parameter should be the last flow return update for a pad
127 /// in this [`FlowCombiner`][crate::FlowCombiner]. It will use this value to be able to shortcut some
128 /// combinations and avoid looking over all pads again. e.g. The last combined
129 /// return is the same as the latest obtained [`gst::FlowReturn`][crate::gst::FlowReturn].
130 /// ## `pad`
131 /// the [`gst::Pad`][crate::gst::Pad] whose [`gst::FlowReturn`][crate::gst::FlowReturn] to update
132 /// ## `fret`
133 /// the latest [`gst::FlowReturn`][crate::gst::FlowReturn] received for a pad in this [`FlowCombiner`][crate::FlowCombiner]
134 ///
135 /// # Returns
136 ///
137 /// The combined [`gst::FlowReturn`][crate::gst::FlowReturn]
138 #[doc(alias = "gst_flow_combiner_update_pad_flow")]
139 pub fn update_pad_flow<P: IsA<gst::Pad>, FRet: Into<gst::FlowReturn>>(
140 &self,
141 pad: &P,
142 fret: FRet,
143 ) -> Result<gst::FlowSuccess, gst::FlowError> {
144 let fret: gst::FlowReturn = fret.into();
145 unsafe {
146 try_from_glib(ffi::gst_flow_combiner_update_pad_flow(
147 self.to_glib_none().0,
148 pad.as_ref().to_glib_none().0,
149 fret.into_glib(),
150 ))
151 }
152 }
153}
154
155impl Default for FlowCombiner {
156 fn default() -> Self {
157 Self::new()
158 }
159}
160
161#[derive(Debug)]
162pub struct UniqueFlowCombiner(FlowCombiner);
163
164unsafe impl Sync for UniqueFlowCombiner {}
165unsafe impl Send for UniqueFlowCombiner {}
166
167impl UniqueFlowCombiner {
168 pub fn new() -> Self {
169 Self(FlowCombiner::new())
170 }
171
172 pub fn add_pad<P: IsA<gst::Pad>>(&mut self, pad: &P) {
173 self.0.add_pad(pad);
174 }
175
176 pub fn clear(&mut self) {
177 self.0.clear();
178 }
179
180 pub fn remove_pad<P: IsA<gst::Pad>>(&mut self, pad: &P) {
181 self.0.remove_pad(pad);
182 }
183
184 pub fn reset(&mut self) {
185 self.0.reset();
186 }
187
188 pub fn update_flow(
189 &mut self,
190 fret: Result<gst::FlowSuccess, gst::FlowError>,
191 ) -> Result<gst::FlowSuccess, gst::FlowError> {
192 self.0.update_flow(fret)
193 }
194
195 pub fn update_pad_flow<P: IsA<gst::Pad>>(
196 &mut self,
197 pad: &P,
198 fret: Result<gst::FlowSuccess, gst::FlowError>,
199 ) -> Result<gst::FlowSuccess, gst::FlowError> {
200 self.0.update_pad_flow(pad, fret)
201 }
202}
203
204impl Default for UniqueFlowCombiner {
205 fn default() -> Self {
206 Self::new()
207 }
208}