opengl 如何使用gstreamer crates从BufferRef中提取GL纹理id?

mrphzbgm  于 2023-08-04  发布在  其他
关注(0)|答案(2)|浏览(144)

我正在开发一个工具,使用GL将视频中的帧渲染到纹理贴图网格上。我已经有一个GL应用程序与一个单一的图像(PNG)工作。现在我正在尝试使用gstreamer来解码视频。
我从appsink example开始。
我已经把解码后的视频通过glupload传输到了一个appsink中。现在我需要将从appsink.pull_sample().get_buffer()得到的BufferRef转换为GL纹理id(u32),以便将其传递给gl::BindTexture(gl::TEXTURE_2D, tex)等GL函数。我在appsink上使用了set_caps(),以确保缓冲区具有memory:GLMemory功能,因此它最好是一个纹理,而不是脱离GPU。
如何使用Rust的gstreamergstreamer-* crate从BufferRef中提取GL纹理id?

oiopk7p5

oiopk7p51#

在C中从GstGLMemory检索纹理需要用特殊的GST_MAP_GL标志MapGstGLMemory本身。用于MapOpenGL纹理的特定接口目前还没有类似的rust。在https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/581中的相关领域中有一些工作可以帮助改善在rust中使用GStreamer OpenGL的情况。
如果您只需要对纹理进行可读访问,那么VideoFrame上有一个扩展trait VideoFrameGLExt,可以访问OpenGL纹理。https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/blob/master/examples/src/bin/glupload.rs提供的gstreamer-rs存储库中的glupload示例中有VideoFrameGLExt的用法。VideoFrameGLExt trait当前在https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/blob/master/gstreamer-gl/src/gl_video_frame.rs中实现
下面的代码应该适用于只读访问:

// buffer: gst::Buffer
// info: gst::VideoInfo
if let Ok(frame) = gst_video::VideoFrame::from_buffer_readable_gl(buffer, &info) {
    if let Some(texture) = frame.get_texture_id(0) {
        // use texture somehow
    }
}

字符集
如果您还需要写入纹理,则当前未公开,并且需要写入手动绑定。

dfty9e19

dfty9e192#

这些天我使用的代码是

/// This code is missing from the gstreamer rust bindings as of 2023-July
pub unsafe fn map_gl(buffer: &mut Buffer) -> Option<GstMapInfo> {
    let mut map_info = MaybeUninit::uninit();
    unsafe {
        let ret = gst_buffer_map(
            buffer.as_mut_ptr(),
            map_info.as_mut_ptr(),
            gst::ffi::GST_MAP_READ | gstgl::ffi::GST_MAP_GL as u32,
        );
        if ret != 0 {
            Some(map_info.assume_init())
        } else {
            None
        }
    }
}

pub fn get_gl_memory(bref: &BufferRef, idx: u32) -> Option<&GLMemoryRef> {
    let n = bref.n_memory();
    if idx >= n {
        return None;
    }

    bref.peek_memory(idx).downcast_memory_ref::<GLMemory>()
}

//
pub fn x(buffer: &mut Buffer) -> (GLuint, GLuint) {
    // the buffer isn't guaranteed to live on GPU until we map it using MAP_GL
    let map = unsafe { map_gl(buffer) };
    if let Some(mut map) = map {
        unsafe { gst_buffer_unmap(buffer.as_mut_ptr(), &mut map as *mut _) }
    }

    let gl_mem = get_gl_memory(buffer, 0).unwrap();
    let tex_id = gl_mem.texture_id();
    let gl_target = gl_mem.texture_target().to_gl();
    (tex_id, gl_target)
}

字符集
虽然来自YStreet00的解决方案工作得很好,如果您可以方便地访问gst::VideoInfo的话。

相关问题