From 43f5a10f9c75c69fadccdf9d88e0102bd0ecaa5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sat, 8 Dec 2018 11:45:23 +0200 Subject: [PATCH] Add API for mapping GL buffers as VideoFrameRef in addition to a full VideoFrame --- gstreamer-gl/src/gl_video_frame.rs | 62 ++++++++++++++++++++++++++++++ gstreamer-video/src/video_frame.rs | 18 +++++++++ 2 files changed, 80 insertions(+) diff --git a/gstreamer-gl/src/gl_video_frame.rs b/gstreamer-gl/src/gl_video_frame.rs index 680f6c12e..62ec01883 100644 --- a/gstreamer-gl/src/gl_video_frame.rs +++ b/gstreamer-gl/src/gl_video_frame.rs @@ -26,10 +26,35 @@ pub trait VideoFrameGLExt { info: &VideoInfo, ) -> Result, gst::Buffer>; + fn from_buffer_ref_readable_gl<'a, 'b>( + buffer: &'a gst::BufferRef, + info: &'b VideoInfo, + ) -> Option>; + fn get_texture_id(&self, idx: u32) -> Option; } impl VideoFrameGLExt for VideoFrame { + fn from_buffer_readable_gl( + buffer: gst::Buffer, + info: &VideoInfo, + ) -> Result, gst::Buffer> { + VideoFrameRef::<&gst::BufferRef>::from_buffer_readable_gl(buffer, info) + } + + fn from_buffer_ref_readable_gl<'a, 'b>( + buffer: &'a gst::BufferRef, + info: &'b VideoInfo, + ) -> Option> { + VideoFrameRef::<&gst::BufferRef>::from_buffer_ref_readable_gl(buffer, info) + } + + fn get_texture_id(&self, idx: u32) -> Option { + self.as_video_frame_ref().get_texture_id(idx) + } +} + +impl<'a> VideoFrameGLExt for VideoFrameRef<&'a gst::BufferRef> { fn from_buffer_readable_gl( buffer: gst::Buffer, info: &VideoInfo, @@ -67,6 +92,43 @@ impl VideoFrameGLExt for VideoFrame { } } + fn from_buffer_ref_readable_gl<'b, 'c>( + buffer: &'b gst::BufferRef, + info: &'c VideoInfo, + ) -> Option> { + skip_assert_initialized!(); + + let n_mem = match buffer_n_gl_memory(buffer) { + Some(n) => n, + None => return None, + }; + + // FIXME: planes are not memories, in multiview use case, + // number of memories = planes * views, but the raw memory is + // not exposed in videoframe + if n_mem != info.n_planes() { + return None; + } + + unsafe { + let mut frame = mem::zeroed(); + let res: bool = from_glib(gst_video_ffi::gst_video_frame_map( + &mut frame, + info.to_glib_none().0 as *mut _, + buffer.as_mut_ptr(), + gst_video_ffi::GST_VIDEO_FRAME_MAP_FLAG_NO_REF + | gst_ffi::GST_MAP_READ + | ffi::GST_MAP_GL as u32, + )); + + if !res { + None + } else { + Some(VideoFrameRef::from_glib_borrow(&frame)) + } + } + } + fn get_texture_id(&self, idx: u32) -> Option { let len = buffer_n_gl_memory(self.buffer())?; diff --git a/gstreamer-video/src/video_frame.rs b/gstreamer-video/src/video_frame.rs index 5b15122bb..32fbbaaac 100644 --- a/gstreamer-video/src/video_frame.rs +++ b/gstreamer-video/src/video_frame.rs @@ -345,6 +345,15 @@ impl<'a> VideoFrameRef<&'a gst::BufferRef> { &self.0 } + pub unsafe fn from_glib_borrow(frame: *const ffi::GstVideoFrame) -> Self { + assert!(!frame.is_null()); + + let frame = ptr::read(frame); + let info = ::VideoInfo(ptr::read(&frame.info)); + let buffer = gst::BufferRef::from_ptr(frame.buffer); + VideoFrameRef(frame, Some(buffer), info, false) + } + pub fn from_buffer_ref_readable<'b>( buffer: &'a gst::BufferRef, info: &'b ::VideoInfo, @@ -523,6 +532,15 @@ impl<'a> VideoFrameRef<&'a gst::BufferRef> { } impl<'a> VideoFrameRef<&'a mut gst::BufferRef> { + pub unsafe fn from_glib_borrow_mut(frame: *mut ffi::GstVideoFrame) -> Self { + assert!(!frame.is_null()); + + let frame = ptr::read(frame); + let info = ::VideoInfo(ptr::read(&frame.info)); + let buffer = gst::BufferRef::from_mut_ptr(frame.buffer); + VideoFrameRef(frame, Some(buffer), info, false) + } + pub fn from_buffer_ref_writable<'b>( buffer: &'a mut gst::BufferRef, info: &'b ::VideoInfo,