Add manual changes for the new/changed 1.24 APIs

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1244>
This commit is contained in:
Sebastian Dröge 2023-04-06 21:10:36 +03:00
parent 4d787df819
commit a11e5cfd75
18 changed files with 631 additions and 27 deletions

View file

@ -52,6 +52,15 @@ status = "generate"
[[object.function]]
name = "phys_memory_get_phys_addr"
manual = true
[[object.function]]
name = "is_drm_dumb_memory"
manual = true
[[object.function]]
name = "drm_dumb_memory_get_handle"
manual = true
[[object.function]]
name = "drm_dumb_memory_export_dmabuf"
manual = true
[[object]]
name = "GstAllocators.DmaBufAllocator"
@ -64,6 +73,21 @@ cfg_condition = "target_os = \"linux\""
name = "alloc_with_flags"
manual = true
[[object]]
name = "GstAllocators.DRMDumbAllocator"
status = "generate"
cfg_condition = "target_os = \"linux\""
[[object.function]]
name = "alloc"
manual = true
[[object.function]]
name = "new_with_fd"
manual = true
[[object.function]]
name = "new_with_device_path"
[object.function.return]
nullable_return_is_error = "Failed to create allocator"
[[object]]
name = "GstAllocators.FdAllocator"
status = "generate"

View file

@ -0,0 +1,81 @@
use std::{fmt, mem, os::unix::prelude::IntoRawFd};
use glib::{translate::*, Cast};
use gst::{Memory, MemoryRef};
use crate::{DRMDumbAllocator, DmaBufMemory};
gst::memory_object_wrapper!(
DRMDumbMemory,
DRMDumbMemoryRef,
gst::ffi::GstMemory,
|mem: &gst::MemoryRef| { unsafe { from_glib(ffi::gst_is_drm_dumb_memory(mem.as_mut_ptr())) } },
Memory,
MemoryRef
);
impl fmt::Debug for DRMDumbMemory {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
DRMDumbMemoryRef::fmt(self, f)
}
}
impl fmt::Debug for DRMDumbMemoryRef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
MemoryRef::fmt(self, f)
}
}
impl DRMDumbMemoryRef {
#[doc(alias = "gst_drm_dumb_memory_get_handle")]
pub fn fd(&self) -> u32 {
skip_assert_initialized!();
unsafe { ffi::gst_drm_dumb_memory_get_handle(self.as_mut_ptr()) }
}
#[doc(alias = "gst_drm_dumb_memory_export_dmabuf")]
pub fn export_dmabuf(&self) -> Result<DmaBufMemory, glib::BoolError> {
skip_assert_initialized!();
unsafe {
Option::<DmaBufMemory>::from_glib_full(ffi::gst_drm_dumb_memory_export_dmabuf(
self.as_mut_ptr(),
))
.ok_or_else(|| glib::bool_error!("Failed to export as dmabuf"))
}
}
}
impl DRMDumbAllocator {
#[doc(alias = "gst_drm_dumb_allocator_new_with_fd")]
#[doc(alias = "new_with_fd")]
pub fn with_fd<A: IntoRawFd>(drm_fd: A) -> Result<DRMDumbAllocator, glib::BoolError> {
assert_initialized_main_thread!();
unsafe {
Option::<gst::Allocator>::from_glib_full(ffi::gst_drm_dumb_allocator_new_with_fd(
drm_fd.into_raw_fd(),
))
.map(|o| o.unsafe_cast())
.ok_or_else(|| glib::bool_error!("Failed to create allocator"))
}
}
#[doc(alias = "gst_drm_dumb_allocator_alloc")]
pub unsafe fn alloc(
&self,
drm_fourcc: u32,
width: u32,
height: u32,
) -> Result<(gst::Memory, u32), glib::BoolError> {
skip_assert_initialized!();
let mut out_pitch = mem::MaybeUninit::uninit();
Option::<_>::from_glib_full(ffi::gst_drm_dumb_allocator_alloc(
self.to_glib_none().0,
drm_fourcc,
width,
height,
out_pitch.as_mut_ptr(),
))
.ok_or_else(|| glib::bool_error!("Failed to allocate memory"))
.map(|mem| (mem, unsafe { out_pitch.assume_init() }))
}
}

View file

@ -37,6 +37,13 @@ mod dma_buf_allocator;
#[cfg_attr(feature = "dox", doc(cfg(target_os = "linux")))]
pub use dma_buf_allocator::*;
#[cfg(any(all(feature = "v1_24", target_os = "linux"), feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(all(feature = "v1_24", target_os = "linux"))))]
mod drm_dumb_allocator;
#[cfg(any(all(feature = "v1_24", target_os = "linux"), feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(all(feature = "v1_24", target_os = "linux"))))]
pub use drm_dumb_allocator::*;
mod phys_memory;
pub use phys_memory::*;

View file

@ -104,6 +104,11 @@ final_type = true
# Action signal
ignore = true
[[object.signal]]
name = "propose-allocation"
# Action signal
ignore = true
[[object.property]]
name = "emit-signals"
# Use callbacks instead

View file

@ -26,6 +26,8 @@ pub struct AppSinkCallbacks {
Box<dyn FnMut(&AppSink) -> Result<gst::FlowSuccess, gst::FlowError> + Send + 'static>,
>,
new_event: Option<Box<dyn FnMut(&AppSink) -> bool + Send + 'static>>,
propose_allocation:
Option<Box<dyn FnMut(&AppSink, &mut gst::query::Allocation) -> bool + Send + 'static>>,
panicked: AtomicBool,
callbacks: ffi::GstAppSinkCallbacks,
}
@ -41,6 +43,7 @@ impl AppSinkCallbacks {
new_preroll: None,
new_sample: None,
new_event: None,
propose_allocation: None,
}
}
}
@ -56,6 +59,8 @@ pub struct AppSinkCallbacksBuilder {
Box<dyn FnMut(&AppSink) -> Result<gst::FlowSuccess, gst::FlowError> + Send + 'static>,
>,
new_event: Option<Box<dyn FnMut(&AppSink) -> bool + Send + 'static>>,
propose_allocation:
Option<Box<dyn FnMut(&AppSink, &mut gst::query::Allocation) -> bool + Send + 'static>>,
}
impl AppSinkCallbacksBuilder {
@ -90,6 +95,18 @@ impl AppSinkCallbacksBuilder {
}
}
pub fn new_propose_allocation<
F: FnMut(&AppSink) -> Result<gst::FlowSuccess, gst::FlowError> + Send + 'static,
>(
self,
new_sample: F,
) -> Self {
Self {
new_sample: Some(Box::new(new_sample)),
..self
}
}
#[cfg(any(feature = "v1_20", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))]
pub fn new_event<F: FnMut(&AppSink) -> bool + Send + 'static>(self, new_event: F) -> Self {
@ -99,18 +116,34 @@ impl AppSinkCallbacksBuilder {
}
}
#[cfg(any(feature = "v1_24", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_24")))]
pub fn propose_allocation<
F: FnMut(&AppSink, &mut gst::query::Allocation) -> bool + Send + 'static,
>(
self,
propose_allocation: F,
) -> Self {
Self {
propose_allocation: Some(Box::new(propose_allocation)),
..self
}
}
#[must_use = "Building the callbacks without using them has no effect"]
pub fn build(self) -> AppSinkCallbacks {
let have_eos = self.eos.is_some();
let have_new_preroll = self.new_preroll.is_some();
let have_new_sample = self.new_sample.is_some();
let have_new_event = self.new_event.is_some();
let have_propose_allocation = self.propose_allocation.is_some();
AppSinkCallbacks {
eos: self.eos,
new_preroll: self.new_preroll,
new_sample: self.new_sample,
new_event: self.new_event,
propose_allocation: self.propose_allocation,
panicked: AtomicBool::new(false),
callbacks: ffi::GstAppSinkCallbacks {
eos: if have_eos { Some(trampoline_eos) } else { None },
@ -129,7 +162,12 @@ impl AppSinkCallbacksBuilder {
} else {
None
},
_gst_reserved: [ptr::null_mut(), ptr::null_mut(), ptr::null_mut()],
propose_allocation: if have_propose_allocation {
Some(trampoline_propose_allocation)
} else {
None
},
_gst_reserved: [ptr::null_mut(), ptr::null_mut()],
},
}
}
@ -266,6 +304,48 @@ unsafe extern "C" fn trampoline_new_event(
ret.into_glib()
}
unsafe extern "C" fn trampoline_propose_allocation(
appsink: *mut ffi::GstAppSink,
query: *mut gst::ffi::GstQuery,
callbacks: gpointer,
) -> glib::ffi::gboolean {
let callbacks = callbacks as *mut AppSinkCallbacks;
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
if (*callbacks).panicked.load(Ordering::Relaxed) {
let element: Borrowed<AppSink> = from_glib_borrow(appsink);
gst::subclass::post_panic_error_message(element.upcast_ref(), element.upcast_ref(), None);
return false.into_glib();
}
let ret = if let Some(ref mut propose_allocation) = (*callbacks).propose_allocation {
let query = match gst::QueryRef::from_mut_ptr(query).view_mut() {
gst::QueryViewMut::Allocation(allocation) => allocation,
_ => unreachable!(),
};
let result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
propose_allocation(&element, query)
}));
match result {
Ok(result) => result,
Err(err) => {
(*callbacks).panicked.store(true, Ordering::Relaxed);
gst::subclass::post_panic_error_message(
element.upcast_ref(),
element.upcast_ref(),
Some(err),
);
false
}
}
} else {
false
};
ret.into_glib()
}
unsafe extern "C" fn destroy_callbacks(ptr: gpointer) {
let _ = Box::<AppSinkCallbacks>::from_raw(ptr as *mut _);
}

View file

@ -385,8 +385,8 @@ manual_traits = ["BaseSrcExtManual"]
[[object.function]]
name = "new_segment"
# Segment parameter
manual = true
[object.function.return]
bool_return_is_error = "Failed to update segment"
[[object]]
name = "GstBase.BaseTransform"

View file

@ -20,11 +20,6 @@ pub trait BaseSrcExtManual: 'static {
&self,
) -> Result<(bool, Option<gst::ClockTime>, Option<gst::ClockTime>), glib::BoolError>;
#[cfg(any(feature = "v1_18", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
#[doc(alias = "gst_base_src_new_segment")]
fn new_segment(&self, segment: &gst::Segment) -> Result<(), glib::BoolError>;
fn src_pad(&self) -> &gst::Pad;
}
@ -78,23 +73,6 @@ impl<O: IsA<BaseSrc>> BaseSrcExtManual for O {
}
}
#[cfg(any(feature = "v1_18", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
fn new_segment(&self, segment: &gst::Segment) -> Result<(), glib::BoolError> {
unsafe {
let ret = from_glib(ffi::gst_base_src_new_segment(
self.as_ref().to_glib_none().0,
segment.to_glib_none().0,
));
if ret {
Ok(())
} else {
Err(glib::bool_error!("Failed to configure new segment"))
}
}
}
fn src_pad(&self) -> &gst::Pad {
unsafe {
let elt = &*(self.as_ptr() as *const ffi::GstBaseSrc);

View file

@ -366,6 +366,11 @@ status = "generate"
[object.function.return]
nullable_return_is_error = "Failed to create window"
[[object.function]]
name = "ensure_context"
# inout parameter
manual = true
[[object]]
name = "GstGL.GLDisplayType"
status = "generate"

View file

@ -3,6 +3,46 @@ use crate::{GLContext, GLDisplay};
use glib::prelude::*;
use glib::translate::*;
pub trait GLDisplayExtManual: 'static {
#[cfg(any(feature = "v1_24", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_24")))]
#[doc(alias = "gst_gl_display_ensure_context")]
fn ensure_context(
&self,
other_context: Option<&impl IsA<GLContext>>,
context: &mut Option<GLContext>,
) -> Result<(), glib::Error>;
}
impl<O: IsA<GLDisplay>> GLDisplayExtManual for O {
#[cfg(any(feature = "v1_24", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_24")))]
fn ensure_context(
&self,
other_context: Option<&impl IsA<GLContext>>,
context: &mut Option<GLContext>,
) -> Result<(), glib::Error> {
unsafe {
let mut err = std::ptr::null_mut();
let res = ffi::gst_gl_display_ensure_context(
self.as_ref().to_glib_none().0,
other_context.map(AsRef::as_ref).to_glib_none().0,
context as *mut Option<GLContext> as *mut Option<*mut ffi::GstGLContext>
as *mut *mut ffi::GstGLContext,
&mut err,
);
if res == glib::ffi::GFALSE {
*context = None;
Err(from_glib_full(err))
} else {
debug_assert!(err.is_null());
Ok(())
}
}
}
}
impl GLDisplay {
#[doc(alias = "gst_gl_display_get_gl_context_for_thread")]
pub fn get_gl_context_for_current_thread(

View file

@ -53,7 +53,7 @@ pub mod prelude {
pub use crate::{
auto::traits::*, context::ContextGLExt, gl_context::GLContextExtManual,
gl_video_frame::VideoFrameGLExt,
gl_display::GLDisplayExtManual, gl_video_frame::VideoFrameGLExt,
};
}

View file

@ -73,6 +73,7 @@ manual = [
"GstVideo.VideoColorRange",
"GstVideo.VideoFormatInfo",
"GstVideo.VideoInfo",
"GstVideo.VideoInfoDmaDrm",
"GstVideo.VideoMeta",
"GstVideo.VideoTimeCode",
"GstVideo.VideoTimeCodeInterval",

View file

@ -53,6 +53,12 @@ mod video_format_info;
pub use crate::video_format_info::*;
mod video_info;
pub use crate::video_info::*;
#[cfg(any(feature = "v1_24", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_24")))]
mod video_info_dma_drm;
#[cfg(any(feature = "v1_24", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_24")))]
pub use crate::video_info_dma_drm::*;
pub mod video_frame;
pub use crate::video_frame::{VideoFrame, VideoFrameRef};
mod video_overlay;

View file

@ -0,0 +1,277 @@
// Take a look at the license at the top of the repository in the LICENSE file.
use std::{fmt, marker::PhantomData, mem, ops, ptr, str};
use glib::translate::*;
use gst::prelude::*;
use crate::{VideoFormat, VideoInfo};
#[doc(alias = "gst_video_dma_drm_fourcc_from_format")]
pub fn dma_drm_fourcc_from_format(v: VideoFormat) -> Result<u32, glib::BoolError> {
skip_assert_initialized!();
unsafe {
let res = ffi::gst_video_dma_drm_fourcc_from_format(v.into_glib());
if res == 0 {
Err(glib::bool_error!("Unsupported video format"))
} else {
Ok(res)
}
}
}
#[doc(alias = "gst_video_dma_drm_fourcc_to_format")]
pub fn dma_drm_fourcc_to_format(v: u32) -> Result<VideoFormat, glib::BoolError> {
skip_assert_initialized!();
unsafe {
let res = ffi::gst_video_dma_drm_fourcc_to_format(v);
if res == ffi::GST_VIDEO_FORMAT_UNKNOWN {
Err(glib::bool_error!("Unsupported fourcc"))
} else {
Ok(from_glib(res))
}
}
}
#[doc(alias = "gst_video_dma_drm_fourcc_to_string")]
pub fn dma_drm_fourcc_to_string(fourcc: u32, modifier: u64) -> glib::GString {
skip_assert_initialized!();
unsafe {
glib::GString::from_glib_full(ffi::gst_video_dma_drm_fourcc_to_string(fourcc, modifier))
}
}
#[doc(alias = "gst_video_dma_drm_fourcc_from_string")]
pub fn dma_drm_fourcc_from_str(v: &str) -> Result<(u32, u64), glib::BoolError> {
skip_assert_initialized!();
unsafe {
let mut modifier = mem::MaybeUninit::uninit();
let res =
ffi::gst_video_dma_drm_fourcc_from_string(v.to_glib_none().0, modifier.as_mut_ptr());
if res == 0 {
Err(glib::bool_error!("Can't parse fourcc string"))
} else {
Ok((res, modifier.assume_init()))
}
}
}
#[doc(alias = "GstVideoInfoDmaDrm")]
#[derive(Clone)]
#[repr(transparent)]
pub struct VideoInfoDmaDrm(pub(crate) ffi::GstVideoInfoDmaDrm);
impl ops::Deref for VideoInfoDmaDrm {
type Target = VideoInfo;
fn deref(&self) -> &Self::Target {
unsafe { &*(&self.0.vinfo as *const ffi::GstVideoInfo as *const VideoInfo) }
}
}
impl fmt::Debug for VideoInfoDmaDrm {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("VideoInfoDmaDrm")
.field("info", &**self)
.field("drm_fourcc", &self.0.drm_fourcc)
.field("drm_modifier", &self.0.drm_modifier)
.finish()
}
}
impl VideoInfoDmaDrm {
pub fn new(info: VideoInfo, fourcc: u32, modifier: u64) -> VideoInfoDmaDrm {
assert_initialized_main_thread!();
VideoInfoDmaDrm(ffi::GstVideoInfoDmaDrm {
vinfo: info.0,
drm_fourcc: fourcc,
drm_modifier: modifier,
_gst_reserved: [0; 20],
})
}
#[inline]
pub fn is_valid(&self) -> bool {
!self.0.vinfo.finfo.is_null()
&& self.0.vinfo.width > 0
&& self.0.vinfo.height > 0
&& self.0.vinfo.size > 0
}
#[doc(alias = "gst_video_info_dma_drm_from_caps")]
pub fn from_caps(caps: &gst::CapsRef) -> Result<Self, glib::error::BoolError> {
skip_assert_initialized!();
unsafe {
let mut info = mem::MaybeUninit::uninit();
if from_glib(ffi::gst_video_info_dma_drm_from_caps(
info.as_mut_ptr(),
caps.as_ptr(),
)) {
Ok(Self(info.assume_init()))
} else {
Err(glib::bool_error!(
"Failed to create VideoInfoDmaDrm from caps"
))
}
}
}
#[doc(alias = "gst_video_info_dma_drm_to_caps")]
pub fn to_caps(&self) -> Result<gst::Caps, glib::error::BoolError> {
unsafe {
let result = from_glib_full(ffi::gst_video_info_dma_drm_to_caps(
&self.0 as *const _ as *mut _,
));
match result {
Some(c) => Ok(c),
None => Err(glib::bool_error!(
"Failed to create caps from VideoInfoDmaDrm"
)),
}
}
}
#[inline]
pub fn fourcc(&self) -> u32 {
self.0.drm_fourcc
}
#[inline]
pub fn modifier(&self) -> u64 {
self.0.drm_modifier
}
}
impl PartialEq for VideoInfoDmaDrm {
#[doc(alias = "gst_video_info_is_equal")]
fn eq(&self, other: &Self) -> bool {
unsafe {
from_glib(ffi::gst_video_info_is_equal(&self.0.vinfo, &other.0.vinfo))
&& self.0.drm_fourcc == other.0.drm_fourcc
&& self.0.drm_modifier == other.0.drm_modifier
}
}
}
impl Eq for VideoInfoDmaDrm {}
unsafe impl Send for VideoInfoDmaDrm {}
unsafe impl Sync for VideoInfoDmaDrm {}
impl glib::types::StaticType for VideoInfoDmaDrm {
#[inline]
fn static_type() -> glib::types::Type {
unsafe { glib::translate::from_glib(ffi::gst_video_info_dma_drm_get_type()) }
}
}
impl glib::value::ValueType for VideoInfoDmaDrm {
type Type = Self;
}
#[doc(hidden)]
unsafe impl<'a> glib::value::FromValue<'a> for VideoInfoDmaDrm {
type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
unsafe fn from_value(value: &'a glib::Value) -> Self {
skip_assert_initialized!();
from_glib_none(glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0)
as *mut ffi::GstVideoInfoDmaDrm)
}
}
#[doc(hidden)]
impl glib::value::ToValue for VideoInfoDmaDrm {
fn to_value(&self) -> glib::Value {
let mut value = glib::Value::for_value_type::<Self>();
unsafe {
glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0,
self.to_glib_none().0 as *mut _,
)
}
value
}
fn value_type(&self) -> glib::Type {
Self::static_type()
}
}
#[doc(hidden)]
impl glib::value::ToValueOptional for VideoInfoDmaDrm {
fn to_value_optional(s: Option<&Self>) -> glib::Value {
skip_assert_initialized!();
let mut value = glib::Value::for_value_type::<Self>();
unsafe {
glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0,
s.to_glib_none().0 as *mut _,
)
}
value
}
}
#[doc(hidden)]
impl From<VideoInfoDmaDrm> for glib::Value {
fn from(v: VideoInfoDmaDrm) -> glib::Value {
skip_assert_initialized!();
glib::value::ToValue::to_value(&v)
}
}
#[doc(hidden)]
impl glib::translate::Uninitialized for VideoInfoDmaDrm {
#[inline]
unsafe fn uninitialized() -> Self {
mem::zeroed()
}
}
#[doc(hidden)]
impl glib::translate::GlibPtrDefault for VideoInfoDmaDrm {
type GlibType = *mut ffi::GstVideoInfoDmaDrm;
}
#[doc(hidden)]
impl<'a> glib::translate::ToGlibPtr<'a, *const ffi::GstVideoInfoDmaDrm> for VideoInfoDmaDrm {
type Storage = PhantomData<&'a Self>;
#[inline]
fn to_glib_none(&'a self) -> glib::translate::Stash<'a, *const ffi::GstVideoInfoDmaDrm, Self> {
glib::translate::Stash(&self.0, PhantomData)
}
fn to_glib_full(&self) -> *const ffi::GstVideoInfoDmaDrm {
unimplemented!()
}
}
#[doc(hidden)]
impl glib::translate::FromGlibPtrNone<*const ffi::GstVideoInfoDmaDrm> for VideoInfoDmaDrm {
#[inline]
unsafe fn from_glib_none(ptr: *const ffi::GstVideoInfoDmaDrm) -> Self {
Self(ptr::read(ptr))
}
}
#[doc(hidden)]
impl glib::translate::FromGlibPtrNone<*mut ffi::GstVideoInfoDmaDrm> for VideoInfoDmaDrm {
#[inline]
unsafe fn from_glib_none(ptr: *mut ffi::GstVideoInfoDmaDrm) -> Self {
Self(ptr::read(ptr))
}
}
#[doc(hidden)]
impl glib::translate::FromGlibPtrFull<*mut ffi::GstVideoInfoDmaDrm> for VideoInfoDmaDrm {
#[inline]
unsafe fn from_glib_full(ptr: *mut ffi::GstVideoInfoDmaDrm) -> Self {
let info = from_glib_none(ptr);
glib::ffi::g_free(ptr as *mut _);
info
}
}

View file

@ -24,7 +24,6 @@ generate = [
"GstWebRTC.WebRTCDTLSTransportState",
"GstWebRTC.WebRTCError",
"GstWebRTC.WebRTCFECType",
"GstWebRTC.WebRTCICE",
"GstWebRTC.WebRTCICECandidateStats",
"GstWebRTC.WebRTCICEComponent",
"GstWebRTC.WebRTCICEConnectionState",
@ -66,6 +65,14 @@ name = "GstWebRTC.WebRTCDTLSTransport"
status = "generate"
final_type = true
[[object]]
name = "GstWebRTC.WebRTCICE"
status = "generate"
[[object.function]]
name = "add_candidate"
# ABI breakage in 1.24 needs working around
manual = true
[[object]]
name = "GstWebRTC.WebRTCICETransport"
status = "generate"

View file

@ -22,6 +22,9 @@ pub use crate::auto::*;
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))]
mod web_rtc_ice_candidate_stats;
mod web_rtc_session_description;
#[cfg(any(feature = "v1_22", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))]
mod web_rtcice;
// Re-export all the traits in a prelude module, so that applications
// can always "use gst_webrtc::prelude::*" without getting conflicts

View file

@ -0,0 +1,79 @@
// Take a look at the license at the top of the repository in the LICENSE file.
use glib::{prelude::*, translate::*};
use crate::{WebRTCICE, WebRTCICEStream};
pub trait WebRTCICEExtManual: 'static {
#[doc(alias = "gst_webrtc_ice_add_candidate")]
fn add_candidate(&self, stream: &impl IsA<WebRTCICEStream>, candidate: &str);
#[cfg(any(feature = "v1_24", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_24")))]
#[doc(alias = "gst_webrtc_ice_add_candidate")]
fn add_candidate_full(
&self,
stream: &impl IsA<WebRTCICEStream>,
candidate: &str,
promise: Option<&gst::Promise>,
);
}
impl<O: IsA<WebRTCICE>> WebRTCICEExtManual for O {
fn add_candidate(&self, stream: &impl IsA<WebRTCICEStream>, candidate: &str) {
#[cfg(not(feature = "v1_24"))]
unsafe {
use std::{mem, ptr};
if gst::version() < (1, 23, 0, 0) {
let func = mem::transmute::<
unsafe extern "C" fn(
*mut ffi::GstWebRTCICE,
*mut ffi::GstWebRTCICEStream,
*const std::os::raw::c_char,
*mut gst::ffi::GstPromise,
),
unsafe extern "C" fn(
*mut ffi::GstWebRTCICE,
*mut ffi::GstWebRTCICEStream,
*const std::os::raw::c_char,
),
>(ffi::gst_webrtc_ice_add_candidate);
func(
self.as_ref().to_glib_none().0,
stream.as_ref().to_glib_none().0,
candidate.to_glib_none().0,
);
} else {
ffi::gst_webrtc_ice_add_candidate(
self.as_ref().to_glib_none().0,
stream.as_ref().to_glib_none().0,
candidate.to_glib_none().0,
ptr::null_mut(),
);
}
}
#[cfg(feature = "v1_24")]
{
self.add_candidate_full(stream, candidate, None);
}
}
#[cfg(any(feature = "v1_24", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_24")))]
fn add_candidate_full(
&self,
stream: &impl IsA<WebRTCICEStream>,
candidate: &str,
promise: Option<&gst::Promise>,
) {
unsafe {
ffi::gst_webrtc_ice_add_candidate(
self.as_ref().to_glib_none().0,
stream.as_ref().to_glib_none().0,
candidate.to_glib_none().0,
promise.to_glib_none().0,
);
}
}
}

View file

@ -1238,6 +1238,15 @@ manual_traits = ["ElementExtManual"]
# Needs integration into subclassing infrastructure
ignore = true
[[object.function]]
name = "decorate_stream_id_printf"
# Varargs
ignore = true
[[object.function]]
name = "decorate_stream_id_printf_valist"
# Varargs
ignore = true
[[object]]
name = "Gst.ElementFactory"
status = "generate"

View file

@ -32,6 +32,8 @@ bitflags! {
const ENCRYPTOR = ffi::GST_ELEMENT_FACTORY_TYPE_ENCRYPTOR;
#[doc(alias = "GST_ELEMENT_FACTORY_TYPE_HARDWARE")]
const HARDWARE = ffi::GST_ELEMENT_FACTORY_TYPE_HARDWARE;
#[doc(alias = "GST_ELEMENT_FACTORY_TYPE_TIMESTAMPER")]
const TIMESTAMPER = ffi::GST_ELEMENT_FACTORY_TYPE_TIMESTAMPER;
#[doc(alias = "GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO")]
const MEDIA_VIDEO = ffi::GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO;