目录
三、从 SurfaceTexture 获取 OpenGL 纹理句柄
四、 如何使用 gstreamer crates 从 BufferRef 中提取 GL 纹理 id?
五、Android OpenGLES从textureID获取cloor数据
一、说明
原因是的目标不是缓冲区,而是特定类型的纹理对象。 OpenGL 术语中进行这种区分是为了消除任何混淆。纹理对象包含数据存储,缓冲区对象也是如此。
二、(OpenGL) 如何读回纹理缓冲区?
2.1 问题针对:
函数 glGetBufferSubData 是否适用于纹理缓冲区和常规缓冲区?我目前正在尝试诊断为什么我的纹理没有出现,并且在利用 glGetBufferSubData 检查缓冲区时,我收到了无意义的信息。
struct TypeGLtexture //Associate texture data with a GL buffer
{
TypeGLbufferID GLbuffer;
TypeImageFile ImageFile;
void GenerateGLbuffer ()
{
if (GLbuffer.isActive==true || ImageFile.GetPixelArray().size()==0) return;
GLbuffer.isActive=true;
GLbuffer.isTexture=true;
GLbuffer.Name="Texture Buffer";
GLbuffer.ElementCount=ImageFile.GetPixelArray().size();
glEnable(GL_TEXTURE_2D);
glGenTextures (1,&GLbuffer.ID); //instantiate ONE buffer object and return its handle/ID
glBindTexture (GL_TEXTURE_2D,GLbuffer.ID); //connect the object to the GL_TEXTURE_2D docking point
glTexImage2D (GL_TEXTURE_2D,0,GL_RGB,ImageFile.GetProperties().width, ImageFile.GetProperties().height,0,GL_RGB,GL_UNSIGNED_BYTE,&(ImageFile.GetPixelArray()[0]));
if(ImageFile.GetProperties().width==6){
cout<<"Actual Data"<
应用后 glGetTexImage(GL_TEXTURE_2D,0,GL_RGB,GL_UNSIGNED_BYTE,read);
,数据显示变化,如 中所示:
2.2 解决方案
是的,这适用于纹理缓冲区,如果这实际上是其中之一的话。
该glGetBufferSubData (...)
函数迎合缓冲区对象。然而,在这种情况下,您正在处理一个纹理对象。如果您尝试使用 API glGetError (...)
来验证错误状态,您可能会收到 API 错误。这是因为 GL_TEXTURE_2D
不是纹理对象缓冲区目标。
遗憾的是,术语似乎存在混淆。此外,还存在一种缓冲区纹理,它是一种独特的 1D 纹理,使您能够将缓冲区对象用作受限类型的纹理。
建议不要宽松地使用术语“缓冲区”,而应将其视为“数据存储”。 OpenGL 也使用这个术语来防止任何混淆。纹理对象和缓冲区对象都有自己的数据存储。需要注意的是,除非您创建纹理缓冲区对象将它们链接在一起,否则这两个概念是分开的。
2.3 从纹理对象读回数据比这复杂得多。
在OpenGL中,在访问像素数据之前需要定义像素格式和数据类型。出于兼容性的目的,OpenGL 将数据从纹理的内部格式转换为请求的格式。因此,您需要寻找具有以下签名的函数。
void glGetTexImage (GLenum target,
GLint level,
GLenum format, // GL will convert to this format
GLenum type, // Using this data type per-pixel
GLvoid * img);
对于任何保存像素数据的 OpenGL 对象,您可以使用像素缓冲区对象将数据从纹理对象移动到不同的缓冲区对象。一旦您在像素缓冲区对象中获得了数据,您就可以 glGetBufferSubData (...)
按照原来的意图使用。
三、从 SurfaceTexture 获取 OpenGL 纹理句柄
3.1 问题针对
可以使用 SurfaceTexture 的 AttachToGLContext() 方法设置纹理句柄。 https://developer.android.com/reference/android/graphics/SurfaceTexture.html#attachToGLContext(int) 上的文档对此进行了解释。
获取纹理句柄似乎是不可能的,除非您拥有对可以初始化它的代码的权限。
要将 gl_texture_external_oes 纹理复制到 RGB GL_TEXTURE_2D,我需要纹理 ID。否则,我将不得不在TextureView 上使用GetBitmap,这会导致GPU 到CPU,然后返回GPU 复制。如果我可以直接在 OpenGL 中复制,就可以避免这个过程。
3.2 解决方案:
要在 OpenGL ES 上下文中建立外部图像和纹理名称之间的连接,必须首先调用 glGenTextures()
生成纹理名称,然后使用 SurfaceTexture.attachToGLContext(int texName)
将图像绑定到它。
完成初始步骤后,可以通过外部采样器在着色器中使用 SurfaceTexture,从而无需创建新纹理。避免将其转换为仅使用一次的算法的新纹理,因为这在带宽和功耗方面效率低下。
四、 如何使用 gstreamer crates 从 BufferRef 中提取 GL 纹理 id?
4.1 问题针对
我当前的项目涉及利用 GL 将视频帧显示到纹理映射的网格上。在此之前,我已经成功创建了一个可处理单个 PNG 图像的 GL 应用程序。目前,我的目标是使用 gstreamer 解码视频。
我从 appsink 示例开始。
成功将解码的视频通过管道传输 glupload
到 appsink 后,下一步是将 BufferRef
获得的 转换 appsink.pull_sample().get_buffer()
为 GL 纹理 id (a u32
),以便可以将其传递给 GL 函数,例如 gl::BindTexture(gl::TEXTURE_2D, tex)
.为了实现这一点, set_caps()
在 appsink 上使用,以确保缓冲区具有所需的功能 memory:GLMemory
,并且是纹理而不是 GPU 外的缓冲区。
gstreamer
在 Rust 中,在和 等板条箱的帮助下 gstreamer-*
,从 a 获取 GL 纹理 id 的过程是什么 BufferRef
?
4.2 解决方案一:
为了从 GstGLMemory
C 中的 a 中检索纹理,需要 GstGLMemory
使用特殊 GST_MAP_GL
标志来映射 a 。然而,这种映射 OpenGL 纹理的特定方法在 Rust 中尚不可用。尽管如此,相关领域仍在开展工作,以改善 Rust 中 GStreamer OpenGL 使用情况,可以在 https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/581 中找到。
要获得对纹理的可读访问,您可以利用 VideoFrameGLExt
上找到的 扩展特征 VideoFrame
。存储库中的 glupload 示例可以看到一个实际示例 gstreamer-rs
,该示例使用 VideoFrameGLExt
.该 VideoFrameGLExt
特征目前已在 VideoFrame
.
以下代码预计可用于以只读模式访问数据。
// 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
}
}
如果还需要写入纹理,则需要写入手动绑定,因为它当前未公开。
4.3 解决方案2:
最终起作用的代码是。
fn get_gl_memory(bref: &BufferRef, idx: u32) -> Option<*mut GstGLMemory> {
unsafe {
let n = gst_sys::gst_buffer_n_memory(bref.as_ptr() as *mut _);
if idx >= n {
return None;
}
let mem = gst_sys::gst_buffer_peek_memory(bref.as_ptr() as *mut _, idx);
if 0 != gst_gl_sys::gst_is_gl_memory(mem) {
Some(mem as *mut _)
} else {
None
}
}
}
//
let gl_mem = get_gl_memory(buffer, 0).unwrap();
let gl_mem = unsafe { &*gl_mem };
let tex_id = gl_mem.tex_id;
只要您能够轻松到达 .ystreet00 提供的解决方案就是有效的 gst::VideoInfo
。
五、Android OpenGLES从textureID获取cloor数据
5.1 问题针对
我的问题涉及从 Android 上的textureID 获取颜色数据。
我的目的是利用 openGLES 获取真实的像素数据并随后对其进行更改。
Gallerydata 包含我的代码,除了 glgeterror 的值为 0 之外,所有字节均为零。
我不确定原因。有才华横溢的人可以帮助我吗?
byte[] Galleydata = new byte[GalleyWidth*GalleyHeight*4];
ByteBuffer buffer = ByteBuffer.wrap(Galleydata);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texturePtr);
GLES20.glReadPixels(0,0,GalleyWidth,GalleyHeight,GLES20.GL_RGBA,GLES20.GL_UNSIGNED_BYTE,buffer);
buffer.get(Galleydata);
5.2 解决方案
该函数 glReadPixels
从帧缓冲区检索像素。要使用此功能,您必须首先使用任何 glDraw*
方法渲染纹理。通常,您需要渲染两个三角形,因为四边形没有得到广泛支持,并且它们的支持仅限于扩展。