gl: export GLMemory getter methods on GLVideoFrame

also change `as_non_null_ptr()` to `as_raw()`

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1312>
This commit is contained in:
Anders Hellerup Madsen 2023-10-01 11:11:52 +02:00
parent 6eb01dc916
commit f8effdda61
4 changed files with 90 additions and 83 deletions

View file

@ -667,7 +667,7 @@ pub(crate) fn main_loop(app: App) -> Result<(), Error> {
if let Some(frame) = curr_frame.as_ref() { if let Some(frame) = curr_frame.as_ref() {
let sync_meta = frame.buffer().meta::<gst_gl::GLSyncMeta>().unwrap(); let sync_meta = frame.buffer().meta::<gst_gl::GLSyncMeta>().unwrap();
sync_meta.wait(&shared_context); sync_meta.wait(&shared_context);
if let Some(texture) = frame.texture_id(0) { if let Ok(texture) = frame.texture_id(0) {
gl.draw_frame(texture as gl::types::GLuint); gl.draw_frame(texture as gl::types::GLuint);
} }
} }

View file

@ -10,7 +10,66 @@ pub enum Readable {}
pub enum Writable {} pub enum Writable {}
// TODO: implement copy for videoframes. This would need to go through all the individual // TODO: implement copy for videoframes. This would need to go through all the individual
// memoryies and copy them. Some GL textures can be copied, others cannot. // memories and copy them. Some GL textures can be copied, others cannot.
pub trait IsGLVideoFrame: IsVideoFrame + Sized {}
mod sealed {
pub trait Sealed {}
impl<T: super::IsGLVideoFrame> Sealed for T {}
}
pub trait GLVideoFrameExt: sealed::Sealed + IsGLVideoFrame {
#[inline]
fn memory(&self, idx: u32) -> Result<&GLMemoryRef, glib::BoolError> {
if idx >= self.info().n_planes() {
return Err(glib::bool_error!(
"Memory index higher than number of memories"
));
}
unsafe {
let ptr = self.as_raw().map[idx as usize].memory;
if ffi::gst_is_gl_memory(ptr) == glib::ffi::GTRUE {
Ok(GLMemoryRef::from_ptr(ptr as _))
} else {
Err(glib::bool_error!("Memory is not a GLMemory"))
}
}
}
#[inline]
#[doc(alias = "get_texture_id")]
fn texture_id(&self, idx: u32) -> Result<u32, glib::BoolError> {
Ok(self.memory(idx)?.texture_id())
}
#[inline]
#[doc(alias = "get_texture_format")]
fn texture_format(&self, idx: u32) -> Result<crate::GLFormat, glib::BoolError> {
Ok(self.memory(idx)?.texture_format())
}
#[inline]
#[doc(alias = "get_texture_height")]
fn texture_height(&self, idx: u32) -> Result<i32, glib::BoolError> {
Ok(self.memory(idx)?.texture_height())
}
#[inline]
#[doc(alias = "get_texture_target")]
fn texture_target(&self, idx: u32) -> Result<crate::GLTextureTarget, glib::BoolError> {
Ok(self.memory(idx)?.texture_target())
}
#[inline]
#[doc(alias = "get_texture_width")]
fn texture_width(&self, idx: u32) -> Result<i32, glib::BoolError> {
Ok(self.memory(idx)?.texture_width())
}
}
impl<O: IsGLVideoFrame> GLVideoFrameExt for O {}
pub struct GLVideoFrame<T> { pub struct GLVideoFrame<T> {
frame: gst_video::ffi::GstVideoFrame, frame: gst_video::ffi::GstVideoFrame,
@ -25,40 +84,14 @@ unsafe impl<T> Sync for GLVideoFrame<T> {}
impl<T> IsVideoFrame for GLVideoFrame<T> { impl<T> IsVideoFrame for GLVideoFrame<T> {
#[inline] #[inline]
fn as_non_null_ptr(&self) -> std::ptr::NonNull<gst_video::ffi::GstVideoFrame> { fn as_raw(&self) -> &gst_video::ffi::GstVideoFrame {
std::ptr::NonNull::from(&self.frame) &self.frame
} }
} }
impl<T> IsGLVideoFrame for GLVideoFrame<T> {}
impl<T> GLVideoFrame<T> { impl<T> GLVideoFrame<T> {
#[inline]
#[doc(alias = "get_texture_id")]
pub fn texture_id(&self, idx: u32) -> Option<u32> {
self.as_video_frame_gl_ref().texture_id(idx)
}
pub fn memory(&self, idx: u32) -> Option<&GLMemoryRef> {
if idx >= buffer_n_gl_memory(self.buffer())? {
return None;
}
unsafe {
let ptr = (*self.as_ptr()).map[idx as usize].memory as _;
Some(GLMemoryRef::from_ptr(ptr))
}
}
pub fn memory_mut(&self, idx: u32) -> Option<&mut GLMemoryRef> {
if idx >= buffer_n_gl_memory(self.buffer())? {
return None;
}
unsafe {
let ptr = (*self.as_ptr()).map[idx as usize].memory as _;
Some(GLMemoryRef::from_mut_ptr(ptr))
}
}
#[inline] #[inline]
pub fn into_buffer(self) -> gst::Buffer { pub fn into_buffer(self) -> gst::Buffer {
unsafe { unsafe {
@ -210,6 +243,11 @@ impl GLVideoFrame<Writable> {
} }
} }
#[inline]
pub fn memory_mut(&self, idx: u32) -> Result<&mut GLMemoryRef, glib::BoolError> {
unsafe { Ok(GLMemoryRef::from_mut_ptr(self.memory(idx)?.as_ptr() as _)) }
}
#[inline] #[inline]
pub fn buffer_mut(&mut self) -> &mut gst::BufferRef { pub fn buffer_mut(&mut self) -> &mut gst::BufferRef {
unsafe { gst::BufferRef::from_mut_ptr(self.frame.buffer) } unsafe { gst::BufferRef::from_mut_ptr(self.frame.buffer) }
@ -227,10 +265,13 @@ unsafe impl<T> Sync for GLVideoFrameRef<T> {}
impl<T> IsVideoFrame for GLVideoFrameRef<T> { impl<T> IsVideoFrame for GLVideoFrameRef<T> {
#[inline] #[inline]
fn as_non_null_ptr(&self) -> std::ptr::NonNull<gst_video::ffi::GstVideoFrame> { fn as_raw(&self) -> &gst_video::ffi::GstVideoFrame {
std::ptr::NonNull::from(&self.frame) &self.frame
} }
} }
impl<T> IsGLVideoFrame for GLVideoFrameRef<T> {}
// TODO implement Debug for GLVideoFrameRef // TODO implement Debug for GLVideoFrameRef
impl<'a> GLVideoFrameRef<&'a gst::BufferRef> { impl<'a> GLVideoFrameRef<&'a gst::BufferRef> {
@ -307,35 +348,6 @@ impl<'a> GLVideoFrameRef<&'a gst::BufferRef> {
} }
} }
} }
pub fn texture_id(&self, idx: u32) -> Option<u32> {
let len = buffer_n_gl_memory(self.buffer())?;
if idx >= len {
return None;
}
// FIXME: planes are not memories
if idx > self.n_planes() {
return None;
}
unsafe {
let ptr = (*self.as_ptr()).data[idx as usize] as *const u32;
Some(*ptr)
}
}
pub fn memory(&self, idx: u32) -> Option<&GLMemoryRef> {
if idx >= buffer_n_gl_memory(self.buffer())? {
return None;
}
unsafe {
let ptr = (*self.as_ptr()).map[idx as usize].memory as _;
Some(GLMemoryRef::from_ptr(ptr))
}
}
} }
impl<'a> GLVideoFrameRef<&'a mut gst::BufferRef> { impl<'a> GLVideoFrameRef<&'a mut gst::BufferRef> {
@ -424,15 +436,9 @@ impl<'a> GLVideoFrameRef<&'a mut gst::BufferRef> {
&mut self.frame &mut self.frame
} }
pub fn memory_mut(&self, idx: u32) -> Option<&mut GLMemoryRef> { #[inline]
if idx >= buffer_n_gl_memory(self.buffer())? { pub fn memory_mut(&self, idx: u32) -> Result<&mut GLMemoryRef, glib::BoolError> {
return None; unsafe { Ok(GLMemoryRef::from_mut_ptr(self.memory(idx)?.as_ptr() as _)) }
}
unsafe {
let ptr = (*self.as_ptr()).map[idx as usize].memory as _;
Some(GLMemoryRef::from_mut_ptr(ptr))
}
} }
} }

View file

@ -38,7 +38,7 @@ mod gl_display;
mod gl_sync_meta; mod gl_sync_meta;
pub mod gl_video_frame; pub mod gl_video_frame;
pub use crate::gl_sync_meta::*; pub use crate::gl_sync_meta::*;
pub use crate::gl_video_frame::{GLVideoFrame, GLVideoFrameRef, Readable}; pub use crate::gl_video_frame::{GLVideoFrame, GLVideoFrameExt, GLVideoFrameRef};
mod gl_base_memory; mod gl_base_memory;
pub use self::gl_base_memory::*; pub use self::gl_base_memory::*;
mod gl_memory; mod gl_memory;
@ -56,6 +56,7 @@ pub mod prelude {
pub use crate::{ pub use crate::{
auto::traits::*, context::ContextGLExt, gl_context::GLContextExtManual, auto::traits::*, context::ContextGLExt, gl_context::GLContextExtManual,
gl_display::GLDisplayExtManual, gl_framebuffer::GLFramebufferExtManual, gl_display::GLDisplayExtManual, gl_framebuffer::GLFramebufferExtManual,
gl_video_frame::GLVideoFrameExt, gl_video_frame::IsGLVideoFrame,
}; };
} }

View file

@ -8,13 +8,13 @@ pub enum Readable {}
pub enum Writable {} pub enum Writable {}
pub trait IsVideoFrame { pub trait IsVideoFrame {
fn as_non_null_ptr(&self) -> std::ptr::NonNull<ffi::GstVideoFrame>; fn as_raw(&self) -> &ffi::GstVideoFrame;
} }
impl<T> IsVideoFrame for VideoFrame<T> { impl<T> IsVideoFrame for VideoFrame<T> {
#[inline] #[inline]
fn as_non_null_ptr(&self) -> std::ptr::NonNull<ffi::GstVideoFrame> { fn as_raw(&self) -> &ffi::GstVideoFrame {
std::ptr::NonNull::from(&self.frame) &self.frame
} }
} }
@ -46,13 +46,13 @@ mod sealed {
pub trait VideoFrameExt: sealed::Sealed + IsVideoFrame { pub trait VideoFrameExt: sealed::Sealed + IsVideoFrame {
#[inline] #[inline]
fn as_ptr(&self) -> *const ffi::GstVideoFrame { fn as_ptr(&self) -> *const ffi::GstVideoFrame {
self.as_non_null_ptr().as_ptr() as _ self.as_raw() as _
} }
#[inline] #[inline]
fn info(&self) -> &crate::VideoInfo { fn info(&self) -> &crate::VideoInfo {
unsafe { unsafe {
let frame = self.as_non_null_ptr().as_ref(); let frame = self.as_raw();
let info = &frame.info as *const ffi::GstVideoInfo as *const crate::VideoInfo; let info = &frame.info as *const ffi::GstVideoInfo as *const crate::VideoInfo;
&*info &*info
} }
@ -60,17 +60,17 @@ pub trait VideoFrameExt: sealed::Sealed + IsVideoFrame {
#[inline] #[inline]
fn flags(&self) -> crate::VideoFrameFlags { fn flags(&self) -> crate::VideoFrameFlags {
unsafe { from_glib(self.as_non_null_ptr().as_ref().flags) } unsafe { from_glib(self.as_raw().flags) }
} }
#[inline] #[inline]
fn id(&self) -> i32 { fn id(&self) -> i32 {
unsafe { self.as_non_null_ptr().as_ref().id } self.as_raw().id
} }
#[inline] #[inline]
fn buffer(&self) -> &gst::BufferRef { fn buffer(&self) -> &gst::BufferRef {
unsafe { gst::BufferRef::from_ptr(self.as_non_null_ptr().as_ref().buffer) } unsafe { gst::BufferRef::from_ptr(self.as_raw().buffer) }
} }
#[inline] #[inline]
@ -534,8 +534,8 @@ pub struct VideoFrameRef<T> {
impl<T> IsVideoFrame for VideoFrameRef<T> { impl<T> IsVideoFrame for VideoFrameRef<T> {
#[inline] #[inline]
fn as_non_null_ptr(&self) -> std::ptr::NonNull<ffi::GstVideoFrame> { fn as_raw(&self) -> &ffi::GstVideoFrame {
std::ptr::NonNull::from(&self.frame) &self.frame
} }
} }