From 51545b90f0d010cdbc79bb77cbc3c544590a7592 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 23 Feb 2020 12:53:33 +0200 Subject: [PATCH] rtsp_server: Add support for subclassing RTSPServer and RTSPClient --- gstreamer-rtsp-server/src/subclass/mod.rs | 4 + .../src/subclass/rtsp_client.rs | 1283 +++++++++++++++++ .../src/subclass/rtsp_media_factory.rs | 3 +- .../src/subclass/rtsp_server.rs | 92 ++ 4 files changed, 1380 insertions(+), 2 deletions(-) create mode 100644 gstreamer-rtsp-server/src/subclass/rtsp_client.rs create mode 100644 gstreamer-rtsp-server/src/subclass/rtsp_server.rs diff --git a/gstreamer-rtsp-server/src/subclass/mod.rs b/gstreamer-rtsp-server/src/subclass/mod.rs index 2568a26c7..48ffcf1f8 100644 --- a/gstreamer-rtsp-server/src/subclass/mod.rs +++ b/gstreamer-rtsp-server/src/subclass/mod.rs @@ -7,10 +7,14 @@ // except according to those terms. #![allow(clippy::cast_ptr_alignment)] +pub mod rtsp_client; pub mod rtsp_media; pub mod rtsp_media_factory; +pub mod rtsp_server; pub mod prelude { + pub use super::rtsp_client::{RTSPClientImpl, RTSPClientImplExt}; pub use super::rtsp_media::{RTSPMediaImpl, RTSPMediaImplExt}; pub use super::rtsp_media_factory::{RTSPMediaFactoryImpl, RTSPMediaFactoryImplExt}; + pub use super::rtsp_server::{RTSPServerImpl, RTSPServerImplExt}; } diff --git a/gstreamer-rtsp-server/src/subclass/rtsp_client.rs b/gstreamer-rtsp-server/src/subclass/rtsp_client.rs new file mode 100644 index 000000000..2b6d3d201 --- /dev/null +++ b/gstreamer-rtsp-server/src/subclass/rtsp_client.rs @@ -0,0 +1,1283 @@ +// Copyright (C) 2020 Sebastian Dröge +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use gst_rtsp_server_sys; + +use glib::subclass::prelude::*; +use glib::translate::*; + +use RTSPClient; +use RTSPClientClass; + +pub trait RTSPClientImpl: RTSPClientImplExt + ObjectImpl + Send + Sync + 'static { + fn create_sdp(&self, client: &RTSPClient, media: &::RTSPMedia) -> Option { + self.parent_create_sdp(client, media) + } + + fn configure_client_media( + &self, + client: &RTSPClient, + media: &::RTSPMedia, + stream: &::RTSPStream, + ctx: &::RTSPContext, + ) -> Result<(), gst::LoggableError> { + self.parent_configure_client_media(client, media, stream, ctx) + } + + // TODO: configure_client_transport + + fn params_set(&self, client: &RTSPClient, ctx: &::RTSPContext) -> gst_rtsp::RTSPResult { + self.parent_params_set(client, ctx) + } + + fn params_get(&self, client: &RTSPClient, ctx: &::RTSPContext) -> gst_rtsp::RTSPResult { + self.parent_params_get(client, ctx) + } + + fn make_path_from_uri( + &self, + client: &RTSPClient, + url: &gst_rtsp::RTSPUrl, + ) -> Option { + self.parent_make_path_from_uri(client, url) + } + + fn closed(&self, client: &RTSPClient) { + self.parent_closed(client); + } + + fn new_session(&self, client: &RTSPClient, session: &::RTSPSession) { + self.parent_new_session(client, session); + } + + fn options_request(&self, client: &RTSPClient, ctx: &::RTSPContext) { + self.parent_options_request(client, ctx); + } + + fn describe_request(&self, client: &RTSPClient, ctx: &::RTSPContext) { + self.parent_describe_request(client, ctx); + } + + fn setup_request(&self, client: &RTSPClient, ctx: &::RTSPContext) { + self.parent_setup_request(client, ctx); + } + + fn play_request(&self, client: &RTSPClient, ctx: &::RTSPContext) { + self.parent_play_request(client, ctx); + } + + fn pause_request(&self, client: &RTSPClient, ctx: &::RTSPContext) { + self.parent_pause_request(client, ctx); + } + + fn teardown_request(&self, client: &RTSPClient, ctx: &::RTSPContext) { + self.parent_teardown_request(client, ctx); + } + + fn set_parameter_request(&self, client: &RTSPClient, ctx: &::RTSPContext) { + self.parent_set_parameter_request(client, ctx); + } + + fn get_parameter_request(&self, client: &RTSPClient, ctx: &::RTSPContext) { + self.parent_get_parameter_request(client, ctx); + } + + fn announce_request(&self, client: &RTSPClient, ctx: &::RTSPContext) { + self.parent_announce_request(client, ctx); + } + + fn record_request(&self, client: &RTSPClient, ctx: &::RTSPContext) { + self.parent_record_request(client, ctx); + } + + fn handle_response(&self, client: &RTSPClient, ctx: &::RTSPContext) { + self.parent_handle_response(client, ctx); + } + + // TODO: tunnel_http_response + // TODO: send_message + + fn handle_sdp( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + media: &::RTSPMedia, + sdp: &gst_sdp::SDPMessageRef, + ) -> Result<(), gst::LoggableError> { + self.parent_handle_sdp(client, ctx, media, sdp) + } + + fn check_requirements( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + arr: &[String], + ) -> Option { + self.parent_check_requirements(client, ctx, arr) + } + + fn pre_options_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode { + self.parent_pre_options_request(client, ctx) + } + + fn pre_describe_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode { + self.parent_pre_describe_request(client, ctx) + } + + fn pre_setup_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode { + self.parent_pre_setup_request(client, ctx) + } + + fn pre_play_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode { + self.parent_pre_play_request(client, ctx) + } + + fn pre_pause_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode { + self.parent_pre_pause_request(client, ctx) + } + + fn pre_teardown_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode { + self.parent_pre_teardown_request(client, ctx) + } + + fn pre_set_parameter_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode { + self.parent_pre_set_parameter_request(client, ctx) + } + + fn pre_get_parameter_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode { + self.parent_pre_get_parameter_request(client, ctx) + } + + fn pre_announce_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode { + self.parent_pre_announce_request(client, ctx) + } + + fn pre_record_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode { + self.parent_pre_record_request(client, ctx) + } +} + +pub trait RTSPClientImplExt { + fn parent_create_sdp( + &self, + client: &RTSPClient, + media: &::RTSPMedia, + ) -> Option; + + fn parent_configure_client_media( + &self, + client: &RTSPClient, + media: &::RTSPMedia, + stream: &::RTSPStream, + ctx: &::RTSPContext, + ) -> Result<(), gst::LoggableError>; + + // TODO: configure_client_transport + + fn parent_params_set(&self, client: &RTSPClient, ctx: &::RTSPContext) -> gst_rtsp::RTSPResult; + + fn parent_params_get(&self, client: &RTSPClient, ctx: &::RTSPContext) -> gst_rtsp::RTSPResult; + + fn parent_make_path_from_uri( + &self, + client: &RTSPClient, + url: &gst_rtsp::RTSPUrl, + ) -> Option; + + fn parent_closed(&self, client: &RTSPClient); + + fn parent_new_session(&self, client: &RTSPClient, session: &::RTSPSession); + + fn parent_options_request(&self, client: &RTSPClient, ctx: &::RTSPContext); + + fn parent_describe_request(&self, client: &RTSPClient, ctx: &::RTSPContext); + + fn parent_setup_request(&self, client: &RTSPClient, ctx: &::RTSPContext); + + fn parent_play_request(&self, client: &RTSPClient, ctx: &::RTSPContext); + + fn parent_pause_request(&self, client: &RTSPClient, ctx: &::RTSPContext); + + fn parent_teardown_request(&self, client: &RTSPClient, ctx: &::RTSPContext); + + fn parent_set_parameter_request(&self, client: &RTSPClient, ctx: &::RTSPContext); + + fn parent_get_parameter_request(&self, client: &RTSPClient, ctx: &::RTSPContext); + + fn parent_announce_request(&self, client: &RTSPClient, ctx: &::RTSPContext); + + fn parent_record_request(&self, client: &RTSPClient, ctx: &::RTSPContext); + + fn parent_handle_response(&self, client: &RTSPClient, ctx: &::RTSPContext); + + // TODO: tunnel_http_response + // TODO: send_message + + fn parent_handle_sdp( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + media: &::RTSPMedia, + sdp: &gst_sdp::SDPMessageRef, + ) -> Result<(), gst::LoggableError>; + + fn parent_check_requirements( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + arr: &[String], + ) -> Option; + + fn parent_pre_options_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode; + + fn parent_pre_describe_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode; + + fn parent_pre_setup_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode; + + fn parent_pre_play_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode; + + fn parent_pre_pause_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode; + + fn parent_pre_teardown_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode; + + fn parent_pre_set_parameter_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode; + + fn parent_pre_get_parameter_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode; + + fn parent_pre_announce_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode; + + fn parent_pre_record_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode; +} + +impl RTSPClientImplExt for T { + fn parent_create_sdp( + &self, + client: &RTSPClient, + media: &::RTSPMedia, + ) -> Option { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + let f = (*parent_class) + .create_sdp + .expect("No `create_rtpbin` virtual method implementation in parent class"); + + from_glib_full(f(client.to_glib_none().0, media.to_glib_none().0)) + } + } + + fn parent_configure_client_media( + &self, + client: &RTSPClient, + media: &::RTSPMedia, + stream: &::RTSPStream, + ctx: &::RTSPContext, + ) -> Result<(), gst::LoggableError> { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + let f = (*parent_class).configure_client_media.expect( + "No `configure_client_media` virtual method implementation in parent class", + ); + + gst_result_from_gboolean!( + f( + client.to_glib_none().0, + media.to_glib_none().0, + stream.to_glib_none().0, + ctx.to_glib_none().0 + ), + gst::CAT_RUST, + "Parent function `configure_client_media` failed" + ) + } + } + + // TODO: configure_client_transport + + fn parent_params_set(&self, client: &RTSPClient, ctx: &::RTSPContext) -> gst_rtsp::RTSPResult { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + let f = (*parent_class) + .params_set + .expect("No `params_set` virtual method implementation in parent class"); + + from_glib(f(client.to_glib_none().0, ctx.to_glib_none().0)) + } + } + + fn parent_params_get(&self, client: &RTSPClient, ctx: &::RTSPContext) -> gst_rtsp::RTSPResult { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + let f = (*parent_class) + .params_get + .expect("No `params_get` virtual method implementation in parent class"); + + from_glib(f(client.to_glib_none().0, ctx.to_glib_none().0)) + } + } + + fn parent_make_path_from_uri( + &self, + client: &RTSPClient, + url: &gst_rtsp::RTSPUrl, + ) -> Option { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + let f = (*parent_class) + .make_path_from_uri + .expect("No `make_path_from_uri` virtual method implementation in parent class"); + + from_glib_full(f(client.to_glib_none().0, url.to_glib_none().0)) + } + } + + fn parent_closed(&self, client: &RTSPClient) { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + if let Some(f) = (*parent_class).closed { + f(client.to_glib_none().0); + } + } + } + + fn parent_new_session(&self, client: &RTSPClient, session: &::RTSPSession) { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + if let Some(f) = (*parent_class).new_session { + f(client.to_glib_none().0, session.to_glib_none().0); + } + } + } + + fn parent_options_request(&self, client: &RTSPClient, ctx: &::RTSPContext) { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + if let Some(f) = (*parent_class).options_request { + f(client.to_glib_none().0, ctx.to_glib_none().0); + } + } + } + + fn parent_describe_request(&self, client: &RTSPClient, ctx: &::RTSPContext) { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + if let Some(f) = (*parent_class).describe_request { + f(client.to_glib_none().0, ctx.to_glib_none().0); + } + } + } + + fn parent_setup_request(&self, client: &RTSPClient, ctx: &::RTSPContext) { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + if let Some(f) = (*parent_class).setup_request { + f(client.to_glib_none().0, ctx.to_glib_none().0); + } + } + } + + fn parent_play_request(&self, client: &RTSPClient, ctx: &::RTSPContext) { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + if let Some(f) = (*parent_class).play_request { + f(client.to_glib_none().0, ctx.to_glib_none().0); + } + } + } + + fn parent_pause_request(&self, client: &RTSPClient, ctx: &::RTSPContext) { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + if let Some(f) = (*parent_class).pause_request { + f(client.to_glib_none().0, ctx.to_glib_none().0); + } + } + } + + fn parent_teardown_request(&self, client: &RTSPClient, ctx: &::RTSPContext) { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + if let Some(f) = (*parent_class).teardown_request { + f(client.to_glib_none().0, ctx.to_glib_none().0); + } + } + } + + fn parent_set_parameter_request(&self, client: &RTSPClient, ctx: &::RTSPContext) { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + if let Some(f) = (*parent_class).set_parameter_request { + f(client.to_glib_none().0, ctx.to_glib_none().0); + } + } + } + + fn parent_get_parameter_request(&self, client: &RTSPClient, ctx: &::RTSPContext) { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + if let Some(f) = (*parent_class).get_parameter_request { + f(client.to_glib_none().0, ctx.to_glib_none().0); + } + } + } + + fn parent_announce_request(&self, client: &RTSPClient, ctx: &::RTSPContext) { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + if let Some(f) = (*parent_class).announce_request { + f(client.to_glib_none().0, ctx.to_glib_none().0); + } + } + } + + fn parent_record_request(&self, client: &RTSPClient, ctx: &::RTSPContext) { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + if let Some(f) = (*parent_class).record_request { + f(client.to_glib_none().0, ctx.to_glib_none().0); + } + } + } + + fn parent_handle_response(&self, client: &RTSPClient, ctx: &::RTSPContext) { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + if let Some(f) = (*parent_class).handle_response { + f(client.to_glib_none().0, ctx.to_glib_none().0); + } + } + } + + // TODO: tunnel_http_response + // TODO: send_message + + fn parent_handle_sdp( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + media: &::RTSPMedia, + sdp: &gst_sdp::SDPMessageRef, + ) -> Result<(), gst::LoggableError> { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + let f = (*parent_class) + .handle_sdp + .expect("No `handle_sdp` virtual method implementation in parent class"); + + gst_result_from_gboolean!( + f( + client.to_glib_none().0, + ctx.to_glib_none().0, + media.to_glib_none().0, + sdp as *const _ as *mut _ + ), + gst::CAT_RUST, + "Parent function `handle_sdp` failed" + ) + } + } + + fn parent_check_requirements( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + arr: &[String], + ) -> Option { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + if let Some(f) = (*parent_class).check_requirements { + from_glib_full(f( + client.to_glib_none().0, + ctx.to_glib_none().0, + arr.to_glib_none().0, + )) + } else { + None + } + } + } + + fn parent_pre_options_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + if let Some(f) = (*parent_class).pre_options_request { + from_glib(f(client.to_glib_none().0, ctx.to_glib_none().0)) + } else { + gst_rtsp::RTSPStatusCode::Ok + } + } + } + + fn parent_pre_describe_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + if let Some(f) = (*parent_class).pre_describe_request { + from_glib(f(client.to_glib_none().0, ctx.to_glib_none().0)) + } else { + gst_rtsp::RTSPStatusCode::Ok + } + } + } + + fn parent_pre_setup_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + if let Some(f) = (*parent_class).pre_setup_request { + from_glib(f(client.to_glib_none().0, ctx.to_glib_none().0)) + } else { + gst_rtsp::RTSPStatusCode::Ok + } + } + } + + fn parent_pre_play_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + if let Some(f) = (*parent_class).pre_play_request { + from_glib(f(client.to_glib_none().0, ctx.to_glib_none().0)) + } else { + gst_rtsp::RTSPStatusCode::Ok + } + } + } + + fn parent_pre_pause_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + if let Some(f) = (*parent_class).pre_pause_request { + from_glib(f(client.to_glib_none().0, ctx.to_glib_none().0)) + } else { + gst_rtsp::RTSPStatusCode::Ok + } + } + } + + fn parent_pre_teardown_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + if let Some(f) = (*parent_class).pre_teardown_request { + from_glib(f(client.to_glib_none().0, ctx.to_glib_none().0)) + } else { + gst_rtsp::RTSPStatusCode::Ok + } + } + } + + fn parent_pre_set_parameter_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + if let Some(f) = (*parent_class).pre_set_parameter_request { + from_glib(f(client.to_glib_none().0, ctx.to_glib_none().0)) + } else { + gst_rtsp::RTSPStatusCode::Ok + } + } + } + + fn parent_pre_get_parameter_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + if let Some(f) = (*parent_class).pre_get_parameter_request { + from_glib(f(client.to_glib_none().0, ctx.to_glib_none().0)) + } else { + gst_rtsp::RTSPStatusCode::Ok + } + } + } + + fn parent_pre_announce_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + if let Some(f) = (*parent_class).pre_announce_request { + from_glib(f(client.to_glib_none().0, ctx.to_glib_none().0)) + } else { + gst_rtsp::RTSPStatusCode::Ok + } + } + } + + fn parent_pre_record_request( + &self, + client: &RTSPClient, + ctx: &::RTSPContext, + ) -> gst_rtsp::RTSPStatusCode { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPClientClass; + if let Some(f) = (*parent_class).pre_record_request { + from_glib(f(client.to_glib_none().0, ctx.to_glib_none().0)) + } else { + gst_rtsp::RTSPStatusCode::Ok + } + } + } +} +unsafe impl IsSubclassable for RTSPClientClass { + fn override_vfuncs(&mut self) { + >::override_vfuncs(self); + unsafe { + let klass = &mut *(self as *mut Self as *mut gst_rtsp_server_sys::GstRTSPClientClass); + klass.create_sdp = Some(client_create_sdp::); + klass.configure_client_media = Some(client_configure_client_media::); + klass.params_set = Some(client_params_set::); + klass.params_get = Some(client_params_get::); + klass.make_path_from_uri = Some(client_make_path_from_uri::); + klass.closed = Some(client_closed::); + klass.new_session = Some(client_new_session::); + klass.options_request = Some(client_options_request::); + klass.describe_request = Some(client_describe_request::); + klass.setup_request = Some(client_setup_request::); + klass.play_request = Some(client_play_request::); + klass.pause_request = Some(client_pause_request::); + klass.teardown_request = Some(client_teardown_request::); + klass.set_parameter_request = Some(client_set_parameter_request::); + klass.get_parameter_request = Some(client_get_parameter_request::); + klass.announce_request = Some(client_announce_request::); + klass.record_request = Some(client_record_request::); + klass.handle_response = Some(client_handle_response::); + klass.handle_sdp = Some(client_handle_sdp::); + klass.check_requirements = Some(client_check_requirements::); + klass.pre_options_request = Some(client_pre_options_request::); + klass.pre_describe_request = Some(client_pre_describe_request::); + klass.pre_setup_request = Some(client_pre_setup_request::); + klass.pre_play_request = Some(client_pre_play_request::); + klass.pre_pause_request = Some(client_pre_pause_request::); + klass.pre_teardown_request = Some(client_pre_teardown_request::); + klass.pre_set_parameter_request = Some(client_pre_set_parameter_request::); + klass.pre_get_parameter_request = Some(client_pre_get_parameter_request::); + klass.pre_announce_request = Some(client_pre_announce_request::); + klass.pre_record_request = Some(client_pre_record_request::); + } + } +} + +unsafe extern "C" fn client_create_sdp( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + media: *mut gst_rtsp_server_sys::GstRTSPMedia, +) -> *mut gst_sdp_sys::GstSDPMessage +where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + let sdp = imp.create_sdp(&wrap, &from_glib_borrow(media)); + let ptr = sdp.to_glib_none().0; + std::mem::forget(sdp); + + ptr as *mut _ +} + +unsafe extern "C" fn client_configure_client_media( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + media: *mut gst_rtsp_server_sys::GstRTSPMedia, + stream: *mut gst_rtsp_server_sys::GstRTSPStream, + ctx: *mut gst_rtsp_server_sys::GstRTSPContext, +) -> glib_sys::gboolean +where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + match imp.configure_client_media( + &wrap, + &from_glib_borrow(media), + &from_glib_borrow(stream), + &from_glib_borrow(ctx), + ) { + Ok(()) => glib_sys::GTRUE, + Err(err) => { + err.log_with_object(&wrap); + glib_sys::GFALSE + } + } +} + +unsafe extern "C" fn client_params_set( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + ctx: *mut gst_rtsp_server_sys::GstRTSPContext, +) -> gst_rtsp_sys::GstRTSPResult +where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.params_set(&wrap, &from_glib_borrow(ctx)).to_glib() +} + +unsafe extern "C" fn client_params_get( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + ctx: *mut gst_rtsp_server_sys::GstRTSPContext, +) -> gst_rtsp_sys::GstRTSPResult +where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.params_get(&wrap, &from_glib_borrow(ctx)).to_glib() +} + +unsafe extern "C" fn client_make_path_from_uri( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + url: *const gst_rtsp_sys::GstRTSPUrl, +) -> *mut std::os::raw::c_char +where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.make_path_from_uri(&wrap, &from_glib_borrow(url)) + .to_glib_full() +} + +unsafe extern "C" fn client_closed(ptr: *mut gst_rtsp_server_sys::GstRTSPClient) +where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.closed(&wrap); +} + +unsafe extern "C" fn client_new_session( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + session: *mut gst_rtsp_server_sys::GstRTSPSession, +) where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.new_session(&wrap, &from_glib_borrow(session)); +} + +unsafe extern "C" fn client_options_request( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + ctx: *mut gst_rtsp_server_sys::GstRTSPContext, +) where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.options_request(&wrap, &from_glib_borrow(ctx)); +} + +unsafe extern "C" fn client_describe_request( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + ctx: *mut gst_rtsp_server_sys::GstRTSPContext, +) where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.describe_request(&wrap, &from_glib_borrow(ctx)); +} + +unsafe extern "C" fn client_setup_request( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + ctx: *mut gst_rtsp_server_sys::GstRTSPContext, +) where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.setup_request(&wrap, &from_glib_borrow(ctx)); +} + +unsafe extern "C" fn client_play_request( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + ctx: *mut gst_rtsp_server_sys::GstRTSPContext, +) where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.play_request(&wrap, &from_glib_borrow(ctx)); +} + +unsafe extern "C" fn client_pause_request( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + ctx: *mut gst_rtsp_server_sys::GstRTSPContext, +) where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.pause_request(&wrap, &from_glib_borrow(ctx)); +} + +unsafe extern "C" fn client_teardown_request( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + ctx: *mut gst_rtsp_server_sys::GstRTSPContext, +) where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.teardown_request(&wrap, &from_glib_borrow(ctx)); +} + +unsafe extern "C" fn client_set_parameter_request( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + ctx: *mut gst_rtsp_server_sys::GstRTSPContext, +) where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.set_parameter_request(&wrap, &from_glib_borrow(ctx)); +} + +unsafe extern "C" fn client_get_parameter_request( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + ctx: *mut gst_rtsp_server_sys::GstRTSPContext, +) where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.get_parameter_request(&wrap, &from_glib_borrow(ctx)); +} + +unsafe extern "C" fn client_announce_request( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + ctx: *mut gst_rtsp_server_sys::GstRTSPContext, +) where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.announce_request(&wrap, &from_glib_borrow(ctx)); +} + +unsafe extern "C" fn client_record_request( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + ctx: *mut gst_rtsp_server_sys::GstRTSPContext, +) where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.record_request(&wrap, &from_glib_borrow(ctx)); +} + +unsafe extern "C" fn client_handle_response( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + ctx: *mut gst_rtsp_server_sys::GstRTSPContext, +) where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.handle_response(&wrap, &from_glib_borrow(ctx)); +} + +unsafe extern "C" fn client_handle_sdp( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + ctx: *mut gst_rtsp_server_sys::GstRTSPContext, + media: *mut gst_rtsp_server_sys::GstRTSPMedia, + sdp: *mut gst_sdp_sys::GstSDPMessage, +) -> glib_sys::gboolean +where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + match imp.handle_sdp( + &wrap, + &from_glib_borrow(ctx), + &from_glib_borrow(media), + &*(sdp as *mut _), + ) { + Ok(()) => glib_sys::GTRUE, + Err(err) => { + err.log_with_object(&wrap); + glib_sys::GFALSE + } + } +} + +unsafe extern "C" fn client_check_requirements( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + ctx: *mut gst_rtsp_server_sys::GstRTSPContext, + arr: *mut *mut std::os::raw::c_char, +) -> *mut std::os::raw::c_char +where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.check_requirements( + &wrap, + &from_glib_borrow(ctx), + Vec::from_glib_none(arr).as_slice(), + ) + .to_glib_full() +} + +unsafe extern "C" fn client_pre_options_request( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + ctx: *mut gst_rtsp_server_sys::GstRTSPContext, +) -> gst_rtsp_sys::GstRTSPStatusCode +where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.pre_options_request(&wrap, &from_glib_borrow(ctx)) + .to_glib() +} + +unsafe extern "C" fn client_pre_describe_request( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + ctx: *mut gst_rtsp_server_sys::GstRTSPContext, +) -> gst_rtsp_sys::GstRTSPStatusCode +where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.pre_describe_request(&wrap, &from_glib_borrow(ctx)) + .to_glib() +} + +unsafe extern "C" fn client_pre_setup_request( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + ctx: *mut gst_rtsp_server_sys::GstRTSPContext, +) -> gst_rtsp_sys::GstRTSPStatusCode +where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.pre_setup_request(&wrap, &from_glib_borrow(ctx)) + .to_glib() +} + +unsafe extern "C" fn client_pre_play_request( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + ctx: *mut gst_rtsp_server_sys::GstRTSPContext, +) -> gst_rtsp_sys::GstRTSPStatusCode +where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.pre_play_request(&wrap, &from_glib_borrow(ctx)) + .to_glib() +} + +unsafe extern "C" fn client_pre_pause_request( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + ctx: *mut gst_rtsp_server_sys::GstRTSPContext, +) -> gst_rtsp_sys::GstRTSPStatusCode +where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.pre_pause_request(&wrap, &from_glib_borrow(ctx)) + .to_glib() +} + +unsafe extern "C" fn client_pre_teardown_request( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + ctx: *mut gst_rtsp_server_sys::GstRTSPContext, +) -> gst_rtsp_sys::GstRTSPStatusCode +where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.pre_teardown_request(&wrap, &from_glib_borrow(ctx)) + .to_glib() +} + +unsafe extern "C" fn client_pre_set_parameter_request( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + ctx: *mut gst_rtsp_server_sys::GstRTSPContext, +) -> gst_rtsp_sys::GstRTSPStatusCode +where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.pre_set_parameter_request(&wrap, &from_glib_borrow(ctx)) + .to_glib() +} + +unsafe extern "C" fn client_pre_get_parameter_request( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + ctx: *mut gst_rtsp_server_sys::GstRTSPContext, +) -> gst_rtsp_sys::GstRTSPStatusCode +where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.pre_get_parameter_request(&wrap, &from_glib_borrow(ctx)) + .to_glib() +} + +unsafe extern "C" fn client_pre_announce_request( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + ctx: *mut gst_rtsp_server_sys::GstRTSPContext, +) -> gst_rtsp_sys::GstRTSPStatusCode +where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.pre_announce_request(&wrap, &from_glib_borrow(ctx)) + .to_glib() +} + +unsafe extern "C" fn client_pre_record_request( + ptr: *mut gst_rtsp_server_sys::GstRTSPClient, + ctx: *mut gst_rtsp_server_sys::GstRTSPContext, +) -> gst_rtsp_sys::GstRTSPStatusCode +where + T: RTSPClientImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPClient = from_glib_borrow(ptr); + + imp.pre_record_request(&wrap, &from_glib_borrow(ctx)) + .to_glib() +} diff --git a/gstreamer-rtsp-server/src/subclass/rtsp_media_factory.rs b/gstreamer-rtsp-server/src/subclass/rtsp_media_factory.rs index 13bd52050..026f989cc 100644 --- a/gstreamer-rtsp-server/src/subclass/rtsp_media_factory.rs +++ b/gstreamer-rtsp-server/src/subclass/rtsp_media_factory.rs @@ -284,8 +284,7 @@ where let pipeline: *mut gst_sys::GstPipeline = imp .create_pipeline(&wrap, &from_glib_borrow(media)) - .to_glib_none() - .0; + .to_glib_full(); // FIXME We somehow need to ensure the pipeline actually stays alive... gobject_sys::g_object_set_qdata_full( diff --git a/gstreamer-rtsp-server/src/subclass/rtsp_server.rs b/gstreamer-rtsp-server/src/subclass/rtsp_server.rs new file mode 100644 index 000000000..78e13e874 --- /dev/null +++ b/gstreamer-rtsp-server/src/subclass/rtsp_server.rs @@ -0,0 +1,92 @@ +// Copyright (C) 2020 Sebastian Dröge +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use gst_rtsp_server_sys; + +use glib::subclass::prelude::*; +use glib::translate::*; + +use RTSPServer; +use RTSPServerClass; + +pub trait RTSPServerImpl: RTSPServerImplExt + ObjectImpl + Send + Sync + 'static { + fn create_client(&self, server: &RTSPServer) -> Option<::RTSPClient> { + self.parent_create_client(server) + } + + fn client_connected(&self, server: &RTSPServer, client: &::RTSPClient) { + self.parent_client_connected(server, client); + } +} + +pub trait RTSPServerImplExt { + fn parent_create_client(&self, server: &RTSPServer) -> Option<::RTSPClient>; + + fn parent_client_connected(&self, server: &RTSPServer, client: &::RTSPClient); +} + +impl RTSPServerImplExt for T { + fn parent_create_client(&self, server: &RTSPServer) -> Option<::RTSPClient> { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPServerClass; + let f = (*parent_class) + .create_client + .expect("No `create_client` virtual method implementation in parent class"); + from_glib_full(f(server.to_glib_none().0)) + } + } + + fn parent_client_connected(&self, server: &RTSPServer, client: &::RTSPClient) { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_rtsp_server_sys::GstRTSPServerClass; + if let Some(f) = (*parent_class).client_connected { + f(server.to_glib_none().0, client.to_glib_none().0) + } + } + } +} +unsafe impl IsSubclassable for RTSPServerClass { + fn override_vfuncs(&mut self) { + >::override_vfuncs(self); + unsafe { + let klass = &mut *(self as *mut Self as *mut gst_rtsp_server_sys::GstRTSPServerClass); + klass.create_client = Some(server_create_client::); + klass.client_connected = Some(server_client_connected::); + } + } +} + +unsafe extern "C" fn server_create_client( + ptr: *mut gst_rtsp_server_sys::GstRTSPServer, +) -> *mut gst_rtsp_server_sys::GstRTSPClient +where + T: RTSPServerImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPServer = from_glib_borrow(ptr); + + imp.create_client(&wrap).to_glib_full() +} + +unsafe extern "C" fn server_client_connected( + ptr: *mut gst_rtsp_server_sys::GstRTSPServer, + client: *mut gst_rtsp_server_sys::GstRTSPClient, +) where + T: RTSPServerImpl, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: RTSPServer = from_glib_borrow(ptr); + + imp.client_connected(&wrap, &from_glib_borrow(client)); +}