gstreamer_rtsp_server/subclass/
rtsp_media_factory.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::mem::transmute;
4
5use glib::{prelude::*, subclass::prelude::*, translate::*};
6
7use crate::{ffi, RTSPMediaFactory};
8
9pub trait RTSPMediaFactoryImpl:
10    ObjectImpl + ObjectSubclass<Type: IsA<RTSPMediaFactory>> + Send + Sync
11{
12    fn gen_key(&self, url: &gst_rtsp::RTSPUrl) -> Option<glib::GString> {
13        self.parent_gen_key(url)
14    }
15
16    fn create_element(&self, url: &gst_rtsp::RTSPUrl) -> Option<gst::Element> {
17        self.parent_create_element(url)
18    }
19
20    fn construct(&self, url: &gst_rtsp::RTSPUrl) -> Option<crate::RTSPMedia> {
21        self.parent_construct(url)
22    }
23
24    fn create_pipeline(&self, media: &crate::RTSPMedia) -> Option<gst::Pipeline> {
25        self.parent_create_pipeline(media)
26    }
27
28    fn configure(&self, media: &crate::RTSPMedia) {
29        self.parent_configure(media)
30    }
31
32    fn media_constructed(&self, media: &crate::RTSPMedia) {
33        self.parent_media_constructed(media)
34    }
35
36    fn media_configure(&self, media: &crate::RTSPMedia) {
37        self.parent_media_configure(media)
38    }
39}
40
41pub trait RTSPMediaFactoryImplExt: RTSPMediaFactoryImpl {
42    fn parent_gen_key(&self, url: &gst_rtsp::RTSPUrl) -> Option<glib::GString> {
43        unsafe {
44            let data = Self::type_data();
45            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaFactoryClass;
46            (*parent_class)
47                .gen_key
48                .map(|f| {
49                    from_glib_full(f(
50                        self.obj()
51                            .unsafe_cast_ref::<RTSPMediaFactory>()
52                            .to_glib_none()
53                            .0,
54                        url.to_glib_none().0,
55                    ))
56                })
57                .unwrap_or(None)
58        }
59    }
60
61    fn parent_create_element(&self, url: &gst_rtsp::RTSPUrl) -> Option<gst::Element> {
62        unsafe {
63            let data = Self::type_data();
64            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaFactoryClass;
65            (*parent_class)
66                .create_element
67                .map(|f| {
68                    from_glib_none(f(
69                        self.obj()
70                            .unsafe_cast_ref::<RTSPMediaFactory>()
71                            .to_glib_none()
72                            .0,
73                        url.to_glib_none().0,
74                    ))
75                })
76                .unwrap_or(None)
77        }
78    }
79
80    fn parent_construct(&self, url: &gst_rtsp::RTSPUrl) -> Option<crate::RTSPMedia> {
81        unsafe {
82            let data = Self::type_data();
83            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaFactoryClass;
84            (*parent_class)
85                .construct
86                .map(|f| {
87                    from_glib_full(f(
88                        self.obj()
89                            .unsafe_cast_ref::<RTSPMediaFactory>()
90                            .to_glib_none()
91                            .0,
92                        url.to_glib_none().0,
93                    ))
94                })
95                .unwrap_or(None)
96        }
97    }
98
99    fn parent_create_pipeline(&self, media: &crate::RTSPMedia) -> Option<gst::Pipeline> {
100        unsafe {
101            let data = Self::type_data();
102            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaFactoryClass;
103            (*parent_class)
104                .create_pipeline
105                .map(|f| {
106                    let ptr = f(
107                        self.obj()
108                            .unsafe_cast_ref::<RTSPMediaFactory>()
109                            .to_glib_none()
110                            .0,
111                        media.to_glib_none().0,
112                    ) as *mut gst::ffi::GstPipeline;
113
114                    // See https://gitlab.freedesktop.org/gstreamer/gst-rtsp-server/merge_requests/109
115                    if glib::gobject_ffi::g_object_is_floating(ptr as *mut _) != glib::ffi::GFALSE {
116                        glib::gobject_ffi::g_object_ref_sink(ptr as *mut _);
117                    }
118                    from_glib_none(ptr)
119                })
120                .unwrap_or(None)
121        }
122    }
123
124    fn parent_configure(&self, media: &crate::RTSPMedia) {
125        unsafe {
126            let data = Self::type_data();
127            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaFactoryClass;
128            if let Some(f) = (*parent_class).configure {
129                f(
130                    self.obj()
131                        .unsafe_cast_ref::<RTSPMediaFactory>()
132                        .to_glib_none()
133                        .0,
134                    media.to_glib_none().0,
135                );
136            }
137        }
138    }
139
140    fn parent_media_constructed(&self, media: &crate::RTSPMedia) {
141        unsafe {
142            let data = Self::type_data();
143            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaFactoryClass;
144            if let Some(f) = (*parent_class).media_constructed {
145                f(
146                    self.obj()
147                        .unsafe_cast_ref::<RTSPMediaFactory>()
148                        .to_glib_none()
149                        .0,
150                    media.to_glib_none().0,
151                );
152            }
153        }
154    }
155
156    fn parent_media_configure(&self, media: &crate::RTSPMedia) {
157        unsafe {
158            let data = Self::type_data();
159            let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaFactoryClass;
160            if let Some(f) = (*parent_class).media_configure {
161                f(
162                    self.obj()
163                        .unsafe_cast_ref::<RTSPMediaFactory>()
164                        .to_glib_none()
165                        .0,
166                    media.to_glib_none().0,
167                );
168            }
169        }
170    }
171}
172
173impl<T: RTSPMediaFactoryImpl> RTSPMediaFactoryImplExt for T {}
174unsafe impl<T: RTSPMediaFactoryImpl> IsSubclassable<T> for RTSPMediaFactory {
175    fn class_init(klass: &mut glib::Class<Self>) {
176        Self::parent_class_init::<T>(klass);
177        let klass = klass.as_mut();
178        klass.gen_key = Some(factory_gen_key::<T>);
179        klass.create_element = Some(factory_create_element::<T>);
180        klass.construct = Some(factory_construct::<T>);
181        klass.create_pipeline = Some(factory_create_pipeline::<T>);
182        klass.configure = Some(factory_configure::<T>);
183        klass.media_constructed = Some(factory_media_constructed::<T>);
184        klass.media_configure = Some(factory_media_configure::<T>);
185    }
186}
187
188unsafe extern "C" fn factory_gen_key<T: RTSPMediaFactoryImpl>(
189    ptr: *mut ffi::GstRTSPMediaFactory,
190    url: *const gst_rtsp::ffi::GstRTSPUrl,
191) -> *mut std::os::raw::c_char {
192    let instance = &*(ptr as *mut T::Instance);
193    let imp = instance.imp();
194
195    imp.gen_key(&from_glib_borrow(url)).into_glib_ptr()
196}
197
198unsafe extern "C" fn factory_create_element<T: RTSPMediaFactoryImpl>(
199    ptr: *mut ffi::GstRTSPMediaFactory,
200    url: *const gst_rtsp::ffi::GstRTSPUrl,
201) -> *mut gst::ffi::GstElement {
202    let instance = &*(ptr as *mut T::Instance);
203    let imp = instance.imp();
204
205    let element = imp.create_element(&from_glib_borrow(url)).into_glib_ptr();
206    glib::gobject_ffi::g_object_force_floating(element as *mut _);
207    element
208}
209
210unsafe extern "C" fn factory_construct<T: RTSPMediaFactoryImpl>(
211    ptr: *mut ffi::GstRTSPMediaFactory,
212    url: *const gst_rtsp::ffi::GstRTSPUrl,
213) -> *mut ffi::GstRTSPMedia {
214    let instance = &*(ptr as *mut T::Instance);
215    let imp = instance.imp();
216
217    imp.construct(&from_glib_borrow(url)).into_glib_ptr()
218}
219
220unsafe extern "C" fn factory_create_pipeline<T: RTSPMediaFactoryImpl>(
221    ptr: *mut ffi::GstRTSPMediaFactory,
222    media: *mut ffi::GstRTSPMedia,
223) -> *mut gst::ffi::GstElement {
224    static PIPELINE_QUARK: std::sync::OnceLock<glib::Quark> = std::sync::OnceLock::new();
225
226    let pipeline_quark =
227        PIPELINE_QUARK.get_or_init(|| glib::Quark::from_str("gstreamer-rs-rtsp-media-pipeline"));
228
229    let instance = &*(ptr as *mut T::Instance);
230    let imp = instance.imp();
231
232    let pipeline: *mut gst::ffi::GstPipeline = imp
233        .create_pipeline(&from_glib_borrow(media))
234        .into_glib_ptr();
235
236    // FIXME We somehow need to ensure the pipeline actually stays alive...
237    glib::gobject_ffi::g_object_set_qdata_full(
238        media as *mut _,
239        pipeline_quark.into_glib(),
240        pipeline as *mut _,
241        Some(transmute::<
242            *const (),
243            unsafe extern "C" fn(glib::ffi::gpointer),
244        >(glib::gobject_ffi::g_object_unref as *const ())),
245    );
246
247    pipeline as *mut _
248}
249
250unsafe extern "C" fn factory_configure<T: RTSPMediaFactoryImpl>(
251    ptr: *mut ffi::GstRTSPMediaFactory,
252    media: *mut ffi::GstRTSPMedia,
253) {
254    let instance = &*(ptr as *mut T::Instance);
255    let imp = instance.imp();
256
257    imp.configure(&from_glib_borrow(media));
258}
259
260unsafe extern "C" fn factory_media_constructed<T: RTSPMediaFactoryImpl>(
261    ptr: *mut ffi::GstRTSPMediaFactory,
262    media: *mut ffi::GstRTSPMedia,
263) {
264    let instance = &*(ptr as *mut T::Instance);
265    let imp = instance.imp();
266
267    imp.media_constructed(&from_glib_borrow(media));
268}
269
270unsafe extern "C" fn factory_media_configure<T: RTSPMediaFactoryImpl>(
271    ptr: *mut ffi::GstRTSPMediaFactory,
272    media: *mut ffi::GstRTSPMedia,
273) {
274    let instance = &*(ptr as *mut T::Instance);
275    let imp = instance.imp();
276
277    imp.media_configure(&from_glib_borrow(media));
278}