gstreamer_rtsp_server/subclass/
rtsp_media.rs1use std::ptr;
4
5use glib::{prelude::*, subclass::prelude::*, translate::*};
6
7use crate::{ffi, RTSPMedia, RTSPThread};
8
9#[derive(Debug)]
10pub struct SDPInfo(ptr::NonNull<ffi::GstSDPInfo>);
11
12impl SDPInfo {
13 pub fn is_ipv6(&self) -> bool {
14 unsafe { from_glib(self.0.as_ref().is_ipv6) }
15 }
16
17 pub fn server_ip(&self) -> &str {
18 unsafe {
19 use std::ffi::CStr;
20 CStr::from_ptr(self.0.as_ref().server_ip).to_str().unwrap()
21 }
22 }
23}
24
25pub trait RTSPMediaImpl: ObjectImpl + ObjectSubclass<Type: IsA<RTSPMedia>> + Send + Sync {
26 fn handle_message(&self, message: &gst::MessageRef) -> bool {
27 self.parent_handle_message(message)
28 }
29
30 fn prepare(&self, thread: &RTSPThread) -> Result<(), gst::LoggableError> {
31 self.parent_prepare(thread)
32 }
33
34 fn unprepare(&self) -> Result<(), gst::LoggableError> {
35 self.parent_unprepare()
36 }
37
38 fn suspend(&self) -> Result<(), gst::LoggableError> {
39 self.parent_suspend()
40 }
41
42 fn unsuspend(&self) -> Result<(), gst::LoggableError> {
43 self.parent_unsuspend()
44 }
45
46 fn query_position(&self) -> Option<gst::ClockTime> {
49 self.parent_query_position()
50 }
51
52 fn query_stop(&self) -> Option<gst::ClockTime> {
53 self.parent_query_stop()
54 }
55
56 fn create_rtpbin(&self) -> Option<gst::Element> {
57 self.parent_create_rtpbin()
58 }
59
60 fn setup_rtpbin(&self, rtpbin: &gst::Element) -> Result<(), gst::LoggableError> {
61 self.parent_setup_rtpbin(rtpbin)
62 }
63
64 fn setup_sdp(
65 &self,
66 sdp: &mut gst_sdp::SDPMessageRef,
67 info: &SDPInfo,
68 ) -> Result<(), gst::LoggableError> {
69 self.parent_setup_sdp(sdp, info)
70 }
71
72 fn new_stream(&self, stream: &crate::RTSPStream) {
73 self.parent_new_stream(stream);
74 }
75
76 fn removed_stream(&self, stream: &crate::RTSPStream) {
77 self.parent_removed_stream(stream);
78 }
79
80 fn prepared(&self) {
81 self.parent_prepared();
82 }
83
84 fn unprepared(&self) {
85 self.parent_unprepared();
86 }
87
88 fn target_state(&self, state: gst::State) {
89 self.parent_target_state(state);
90 }
91
92 fn new_state(&self, state: gst::State) {
93 self.parent_new_state(state);
94 }
95
96 fn handle_sdp(&self, sdp: &gst_sdp::SDPMessageRef) -> Result<(), gst::LoggableError> {
97 self.parent_handle_sdp(sdp)
98 }
99}
100
101pub trait RTSPMediaImplExt: RTSPMediaImpl {
102 fn parent_handle_message(&self, message: &gst::MessageRef) -> bool {
103 unsafe {
104 let data = Self::type_data();
105 let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaClass;
106 if let Some(f) = (*parent_class).handle_message {
107 from_glib(f(
108 self.obj().unsafe_cast_ref::<RTSPMedia>().to_glib_none().0,
109 message.as_ptr() as *mut _,
110 ))
111 } else {
112 false
113 }
114 }
115 }
116
117 fn parent_prepare(&self, thread: &RTSPThread) -> Result<(), gst::LoggableError> {
118 unsafe {
119 let data = Self::type_data();
120 let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaClass;
121 if let Some(f) = (*parent_class).prepare {
122 gst::result_from_gboolean!(
123 f(
124 self.obj().unsafe_cast_ref::<RTSPMedia>().to_glib_none().0,
125 thread.to_glib_none().0
126 ),
127 gst::CAT_RUST,
128 "Parent function `prepare` failed"
129 )
130 } else {
131 Ok(())
132 }
133 }
134 }
135
136 fn parent_unprepare(&self) -> Result<(), gst::LoggableError> {
137 unsafe {
138 let data = Self::type_data();
139 let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaClass;
140 if let Some(f) = (*parent_class).unprepare {
141 gst::result_from_gboolean!(
142 f(self.obj().unsafe_cast_ref::<RTSPMedia>().to_glib_none().0),
143 gst::CAT_RUST,
144 "Parent function `unprepare` failed"
145 )
146 } else {
147 Ok(())
148 }
149 }
150 }
151
152 fn parent_suspend(&self) -> Result<(), gst::LoggableError> {
153 unsafe {
154 let data = Self::type_data();
155 let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaClass;
156 if let Some(f) = (*parent_class).suspend {
157 gst::result_from_gboolean!(
158 f(self.obj().unsafe_cast_ref::<RTSPMedia>().to_glib_none().0),
159 gst::CAT_RUST,
160 "Parent function `suspend` failed"
161 )
162 } else {
163 Ok(())
164 }
165 }
166 }
167
168 fn parent_unsuspend(&self) -> Result<(), gst::LoggableError> {
169 unsafe {
170 let data = Self::type_data();
171 let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaClass;
172 if let Some(f) = (*parent_class).unsuspend {
173 gst::result_from_gboolean!(
174 f(self.obj().unsafe_cast_ref::<RTSPMedia>().to_glib_none().0),
175 gst::CAT_RUST,
176 "Parent function `unsuspend` failed"
177 )
178 } else {
179 Ok(())
180 }
181 }
182 }
183
184 fn parent_query_position(&self) -> Option<gst::ClockTime> {
186 unsafe {
187 use std::mem;
188
189 let data = Self::type_data();
190 let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaClass;
191 if let Some(f) = (*parent_class).query_position {
192 let mut position = mem::MaybeUninit::uninit();
193 if f(
194 self.obj().unsafe_cast_ref::<RTSPMedia>().to_glib_none().0,
195 position.as_mut_ptr(),
196 ) == glib::ffi::GFALSE
197 {
198 None
199 } else {
200 from_glib(position.assume_init() as u64)
201 }
202 } else {
203 None
204 }
205 }
206 }
207
208 fn parent_query_stop(&self) -> Option<gst::ClockTime> {
209 unsafe {
210 use std::mem;
211
212 let data = Self::type_data();
213 let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaClass;
214 if let Some(f) = (*parent_class).query_stop {
215 let mut stop = mem::MaybeUninit::uninit();
216 if f(
217 self.obj().unsafe_cast_ref::<RTSPMedia>().to_glib_none().0,
218 stop.as_mut_ptr(),
219 ) == glib::ffi::GFALSE
220 {
221 None
222 } else {
223 from_glib(stop.assume_init() as u64)
224 }
225 } else {
226 None
227 }
228 }
229 }
230
231 fn parent_create_rtpbin(&self) -> Option<gst::Element> {
232 unsafe {
233 let data = Self::type_data();
234 let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaClass;
235 let f = (*parent_class)
236 .create_rtpbin
237 .expect("No `create_rtpbin` virtual method implementation in parent class");
238
239 from_glib_none(f(self
240 .obj()
241 .unsafe_cast_ref::<RTSPMedia>()
242 .to_glib_none()
243 .0))
244 }
245 }
246
247 fn parent_setup_rtpbin(&self, rtpbin: &gst::Element) -> Result<(), gst::LoggableError> {
248 unsafe {
249 let data = Self::type_data();
250 let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaClass;
251 if let Some(f) = (*parent_class).setup_rtpbin {
252 let ptr = rtpbin.to_glib_none().0;
253
254 glib::gobject_ffi::g_object_force_floating(ptr as *mut _);
256
257 let res = gst::result_from_gboolean!(
258 f(
259 self.obj().unsafe_cast_ref::<RTSPMedia>().to_glib_none().0,
260 ptr
261 ),
262 gst::CAT_RUST,
263 "Parent function `setup_sdp` failed"
264 );
265
266 if glib::gobject_ffi::g_object_is_floating(ptr as *mut _) != glib::ffi::GFALSE {
270 glib::gobject_ffi::g_object_ref_sink(ptr as *mut _);
271 }
272
273 res
274 } else {
275 Ok(())
276 }
277 }
278 }
279
280 fn parent_setup_sdp(
281 &self,
282 sdp: &mut gst_sdp::SDPMessageRef,
283 info: &SDPInfo,
284 ) -> Result<(), gst::LoggableError> {
285 unsafe {
286 let data = Self::type_data();
287 let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaClass;
288 let f = (*parent_class)
289 .setup_sdp
290 .expect("No `setup_sdp` virtual method implementation in parent class");
291
292 gst::result_from_gboolean!(
293 f(
294 self.obj().unsafe_cast_ref::<RTSPMedia>().to_glib_none().0,
295 sdp as *mut _ as *mut gst_sdp::ffi::GstSDPMessage,
296 info.0.as_ptr()
297 ),
298 gst::CAT_RUST,
299 "Parent function `setup_sdp` failed"
300 )
301 }
302 }
303
304 fn parent_new_stream(&self, stream: &crate::RTSPStream) {
305 unsafe {
306 let data = Self::type_data();
307 let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaClass;
308 if let Some(f) = (*parent_class).new_stream {
309 f(
310 self.obj().unsafe_cast_ref::<RTSPMedia>().to_glib_none().0,
311 stream.to_glib_none().0,
312 );
313 }
314 }
315 }
316
317 fn parent_removed_stream(&self, stream: &crate::RTSPStream) {
318 unsafe {
319 let data = Self::type_data();
320 let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaClass;
321 if let Some(f) = (*parent_class).removed_stream {
322 f(
323 self.obj().unsafe_cast_ref::<RTSPMedia>().to_glib_none().0,
324 stream.to_glib_none().0,
325 );
326 }
327 }
328 }
329
330 fn parent_prepared(&self) {
331 unsafe {
332 let data = Self::type_data();
333 let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaClass;
334 if let Some(f) = (*parent_class).prepared {
335 f(self.obj().unsafe_cast_ref::<RTSPMedia>().to_glib_none().0);
336 }
337 }
338 }
339
340 fn parent_unprepared(&self) {
341 unsafe {
342 let data = Self::type_data();
343 let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaClass;
344 if let Some(f) = (*parent_class).unprepared {
345 f(self.obj().unsafe_cast_ref::<RTSPMedia>().to_glib_none().0);
346 }
347 }
348 }
349
350 fn parent_target_state(&self, state: gst::State) {
351 unsafe {
352 let data = Self::type_data();
353 let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaClass;
354 if let Some(f) = (*parent_class).target_state {
355 f(
356 self.obj().unsafe_cast_ref::<RTSPMedia>().to_glib_none().0,
357 state.into_glib(),
358 );
359 }
360 }
361 }
362
363 fn parent_new_state(&self, state: gst::State) {
364 unsafe {
365 let data = Self::type_data();
366 let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaClass;
367 if let Some(f) = (*parent_class).new_state {
368 f(
369 self.obj().unsafe_cast_ref::<RTSPMedia>().to_glib_none().0,
370 state.into_glib(),
371 );
372 }
373 }
374 }
375
376 fn parent_handle_sdp(&self, sdp: &gst_sdp::SDPMessageRef) -> Result<(), gst::LoggableError> {
377 unsafe {
378 let data = Self::type_data();
379 let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTSPMediaClass;
380 let f = (*parent_class)
381 .handle_sdp
382 .expect("No `handle_sdp` virtual method implementation in parent class");
383
384 gst::result_from_gboolean!(
385 f(
386 self.obj().unsafe_cast_ref::<RTSPMedia>().to_glib_none().0,
387 sdp as *const _ as *mut gst_sdp::ffi::GstSDPMessage
388 ),
389 gst::CAT_RUST,
390 "Parent function `handle_sdp` failed"
391 )
392 }
393 }
394}
395
396impl<T: RTSPMediaImpl> RTSPMediaImplExt for T {}
397
398unsafe impl<T: RTSPMediaImpl> IsSubclassable<T> for RTSPMedia {
399 fn class_init(klass: &mut glib::Class<Self>) {
400 Self::parent_class_init::<T>(klass);
401 let klass = klass.as_mut();
402 klass.handle_message = Some(media_handle_message::<T>);
403 klass.prepare = Some(media_prepare::<T>);
404 klass.unprepare = Some(media_unprepare::<T>);
405 klass.suspend = Some(media_suspend::<T>);
406 klass.unsuspend = Some(media_unsuspend::<T>);
407 klass.query_position = Some(media_query_position::<T>);
408 klass.query_stop = Some(media_query_stop::<T>);
409 klass.create_rtpbin = Some(media_create_rtpbin::<T>);
410 klass.setup_rtpbin = Some(media_setup_rtpbin::<T>);
411 klass.setup_sdp = Some(media_setup_sdp::<T>);
412 klass.new_stream = Some(media_new_stream::<T>);
413 klass.removed_stream = Some(media_removed_stream::<T>);
414 klass.prepared = Some(media_prepared::<T>);
415 klass.unprepared = Some(media_unprepared::<T>);
416 klass.target_state = Some(media_target_state::<T>);
417 klass.new_state = Some(media_new_state::<T>);
418 klass.handle_sdp = Some(media_handle_sdp::<T>);
419 }
420}
421
422unsafe extern "C" fn media_handle_message<T: RTSPMediaImpl>(
423 ptr: *mut ffi::GstRTSPMedia,
424 message: *mut gst::ffi::GstMessage,
425) -> glib::ffi::gboolean {
426 let instance = &*(ptr as *mut T::Instance);
427 let imp = instance.imp();
428
429 imp.handle_message(gst::MessageRef::from_ptr(message))
430 .into_glib()
431}
432
433unsafe extern "C" fn media_prepare<T: RTSPMediaImpl>(
434 ptr: *mut ffi::GstRTSPMedia,
435 thread: *mut ffi::GstRTSPThread,
436) -> glib::ffi::gboolean {
437 let instance = &*(ptr as *mut T::Instance);
438 let imp = instance.imp();
439
440 match imp.prepare(&from_glib_borrow(thread)) {
441 Ok(()) => glib::ffi::GTRUE,
442 Err(err) => {
443 err.log_with_imp(imp);
444 glib::ffi::GFALSE
445 }
446 }
447}
448
449unsafe extern "C" fn media_unprepare<T: RTSPMediaImpl>(
450 ptr: *mut ffi::GstRTSPMedia,
451) -> glib::ffi::gboolean {
452 let instance = &*(ptr as *mut T::Instance);
453 let imp = instance.imp();
454
455 match imp.unprepare() {
456 Ok(()) => glib::ffi::GTRUE,
457 Err(err) => {
458 err.log_with_imp(imp);
459 glib::ffi::GFALSE
460 }
461 }
462}
463
464unsafe extern "C" fn media_suspend<T: RTSPMediaImpl>(
465 ptr: *mut ffi::GstRTSPMedia,
466) -> glib::ffi::gboolean {
467 let instance = &*(ptr as *mut T::Instance);
468 let imp = instance.imp();
469
470 match imp.suspend() {
471 Ok(()) => glib::ffi::GTRUE,
472 Err(err) => {
473 err.log_with_imp(imp);
474 glib::ffi::GFALSE
475 }
476 }
477}
478
479unsafe extern "C" fn media_unsuspend<T: RTSPMediaImpl>(
480 ptr: *mut ffi::GstRTSPMedia,
481) -> glib::ffi::gboolean {
482 let instance = &*(ptr as *mut T::Instance);
483 let imp = instance.imp();
484
485 match imp.unsuspend() {
486 Ok(()) => glib::ffi::GTRUE,
487 Err(err) => {
488 err.log_with_imp(imp);
489 glib::ffi::GFALSE
490 }
491 }
492}
493
494unsafe extern "C" fn media_query_position<T: RTSPMediaImpl>(
495 ptr: *mut ffi::GstRTSPMedia,
496 position: *mut i64,
497) -> glib::ffi::gboolean {
498 let instance = &*(ptr as *mut T::Instance);
499 let imp = instance.imp();
500
501 match imp.query_position() {
502 Some(pos) => {
503 *position = pos.into_glib() as i64;
504 glib::ffi::GTRUE
505 }
506 None => glib::ffi::GFALSE,
507 }
508}
509
510unsafe extern "C" fn media_query_stop<T: RTSPMediaImpl>(
511 ptr: *mut ffi::GstRTSPMedia,
512 stop: *mut i64,
513) -> glib::ffi::gboolean {
514 let instance = &*(ptr as *mut T::Instance);
515 let imp = instance.imp();
516
517 match imp.query_stop() {
518 Some(s) => {
519 *stop = s.into_glib() as i64;
520 glib::ffi::GTRUE
521 }
522 None => glib::ffi::GFALSE,
523 }
524}
525
526unsafe extern "C" fn media_create_rtpbin<T: RTSPMediaImpl>(
527 ptr: *mut ffi::GstRTSPMedia,
528) -> *mut gst::ffi::GstElement {
529 let instance = &*(ptr as *mut T::Instance);
530 let imp = instance.imp();
531
532 let res: *mut gst::ffi::GstElement = imp.create_rtpbin().into_glib_ptr();
533
534 if !res.is_null() {
535 glib::gobject_ffi::g_object_force_floating(res as *mut _);
536 }
537
538 res
539}
540
541unsafe extern "C" fn media_setup_rtpbin<T: RTSPMediaImpl>(
542 ptr: *mut ffi::GstRTSPMedia,
543 rtpbin: *mut gst::ffi::GstElement,
544) -> glib::ffi::gboolean {
545 let instance = &*(ptr as *mut T::Instance);
546 let imp = instance.imp();
547
548 if glib::gobject_ffi::g_object_is_floating(rtpbin as *mut _) != glib::ffi::GFALSE {
551 glib::gobject_ffi::g_object_ref_sink(rtpbin as *mut _);
552 }
553
554 let res = match imp.setup_rtpbin(&from_glib_borrow(rtpbin)) {
555 Ok(()) => glib::ffi::GTRUE,
556 Err(err) => {
557 err.log_with_imp(imp);
558 glib::ffi::GFALSE
559 }
560 };
561
562 glib::gobject_ffi::g_object_force_floating(rtpbin as *mut _);
564
565 res
566}
567
568unsafe extern "C" fn media_setup_sdp<T: RTSPMediaImpl>(
569 ptr: *mut ffi::GstRTSPMedia,
570 sdp: *mut gst_sdp::ffi::GstSDPMessage,
571 info: *mut ffi::GstSDPInfo,
572) -> glib::ffi::gboolean {
573 let instance = &*(ptr as *mut T::Instance);
574 let imp = instance.imp();
575
576 match imp.setup_sdp(
577 &mut *(sdp as *mut gst_sdp::SDPMessageRef),
578 &SDPInfo(ptr::NonNull::new(info).expect("NULL SDPInfo")),
579 ) {
580 Ok(()) => glib::ffi::GTRUE,
581 Err(err) => {
582 err.log_with_imp(imp);
583 glib::ffi::GFALSE
584 }
585 }
586}
587
588unsafe extern "C" fn media_new_stream<T: RTSPMediaImpl>(
589 ptr: *mut ffi::GstRTSPMedia,
590 stream: *mut ffi::GstRTSPStream,
591) {
592 let instance = &*(ptr as *mut T::Instance);
593 let imp = instance.imp();
594
595 imp.new_stream(&from_glib_borrow(stream));
596}
597
598unsafe extern "C" fn media_removed_stream<T: RTSPMediaImpl>(
599 ptr: *mut ffi::GstRTSPMedia,
600 stream: *mut ffi::GstRTSPStream,
601) {
602 let instance = &*(ptr as *mut T::Instance);
603 let imp = instance.imp();
604
605 imp.removed_stream(&from_glib_borrow(stream));
606}
607
608unsafe extern "C" fn media_prepared<T: RTSPMediaImpl>(ptr: *mut ffi::GstRTSPMedia) {
609 let instance = &*(ptr as *mut T::Instance);
610 let imp = instance.imp();
611
612 imp.prepared();
613}
614
615unsafe extern "C" fn media_unprepared<T: RTSPMediaImpl>(ptr: *mut ffi::GstRTSPMedia) {
616 let instance = &*(ptr as *mut T::Instance);
617 let imp = instance.imp();
618
619 imp.unprepared();
620}
621
622unsafe extern "C" fn media_target_state<T: RTSPMediaImpl>(
623 ptr: *mut ffi::GstRTSPMedia,
624 state: gst::ffi::GstState,
625) {
626 let instance = &*(ptr as *mut T::Instance);
627 let imp = instance.imp();
628
629 imp.target_state(from_glib(state));
630}
631
632unsafe extern "C" fn media_new_state<T: RTSPMediaImpl>(
633 ptr: *mut ffi::GstRTSPMedia,
634 state: gst::ffi::GstState,
635) {
636 let instance = &*(ptr as *mut T::Instance);
637 let imp = instance.imp();
638
639 imp.new_state(from_glib(state));
640}
641
642unsafe extern "C" fn media_handle_sdp<T: RTSPMediaImpl>(
643 ptr: *mut ffi::GstRTSPMedia,
644 sdp: *mut gst_sdp::ffi::GstSDPMessage,
645) -> glib::ffi::gboolean {
646 let instance = &*(ptr as *mut T::Instance);
647 let imp = instance.imp();
648
649 match imp.handle_sdp(&*(sdp as *const gst_sdp::SDPMessageRef)) {
650 Ok(()) => glib::ffi::GTRUE,
651 Err(err) => {
652 err.log_with_imp(imp);
653 glib::ffi::GFALSE
654 }
655 }
656}