mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git
synced 2024-12-21 23:56:33 +00:00
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:
parent
4d787df819
commit
a11e5cfd75
18 changed files with 631 additions and 27 deletions
|
@ -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"
|
||||
|
|
81
gstreamer-allocators/src/drm_dumb_allocator.rs
Normal file
81
gstreamer-allocators/src/drm_dumb_allocator.rs
Normal 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() }))
|
||||
}
|
||||
}
|
|
@ -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::*;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 _);
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -73,6 +73,7 @@ manual = [
|
|||
"GstVideo.VideoColorRange",
|
||||
"GstVideo.VideoFormatInfo",
|
||||
"GstVideo.VideoInfo",
|
||||
"GstVideo.VideoInfoDmaDrm",
|
||||
"GstVideo.VideoMeta",
|
||||
"GstVideo.VideoTimeCode",
|
||||
"GstVideo.VideoTimeCodeInterval",
|
||||
|
|
|
@ -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;
|
||||
|
|
277
gstreamer-video/src/video_info_dma_drm.rs
Normal file
277
gstreamer-video/src/video_info_dma_drm.rs
Normal 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
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
79
gstreamer-webrtc/src/web_rtcice.rs
Normal file
79
gstreamer-webrtc/src/web_rtcice.rs
Normal 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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue