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