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