通过 SurfaceTexture 在 GLSurfaceView 上显示相机流
Posted
技术标签:
【中文标题】通过 SurfaceTexture 在 GLSurfaceView 上显示相机流【英文标题】:Displaying the camera stream on a GLSurfaceView via SurfaceTexture 【发布时间】:2012-10-23 10:22:13 【问题描述】:我正在尝试通过传输到 OpenGL ES 2.0 着色器的 SurfaceTexture 在 GLSurfaceView 中显示相机流。
我从这个post中获得灵感。
图像完整,但在我的平板电脑上显示不正确。 屏幕似乎分为 2x2 部分。图像显示在左上角,而其他三个部分是黑色的。
我怀疑问题出在我使用了here记录的序列返回的转换矩阵
updateTexImage();
getTransformMatrix(...);
我在顶点着色器中传输这个矩阵来为片段着色器生成纹理坐标。
顶点着色器:
attribute vec3 aPosition;
uniform mat4 uMvpTransform;
// Matrix retrieved by getTransformMatrix(...);
uniform mat4 uTexMatTransform;
varying vec2 vTexCoord;
void main(void)
gl_Position = uMvpTransform *vec4(aPosition.xyz, 1);
vec4 l_tex = uTexMatTransform*vec4(aPosition.xyz, 1);
vTexCoord=l_tex.xy;
片段着色器:
#extension GL_OES_EGL_image_external : require
varying mediump vec2 vTexCoord;
uniform samplerExternalOES uSampler;
void main(void)
mediump vec4 l_tex = texture2D(uSampler, vTexCoord);
gl_FragColor=l_tex;
纹理附加到以下正方形:
// Image container
GLfloat l_vertices[] =
-1.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f ;
有人做过类似的事情吗?
2012 年 11 月 3 日编辑:
顶点着色器的修正:
attribute vec3 aPosition;
attribute vec2 aTexCoord;
uniform mat4 uMvpTransform;
// Matrix retrieved by getTransformMatrix(...);
uniform mat4 uTexMatTransform;
varying vec2 vTexCoord;
void main(void)
gl_Position = uMvpTransform *vec4(aPosition.xyz, 1);
vec4 l_tex = uTexMatTransform*vec4(aTexCoord.xy,0, 1);
vTexCoord=l_tex.xy;
与:
// Texture
GLfloat l_texCoord[] =
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f
;
【问题讨论】:
【参考方案1】:我已成功使用 SurfaceTexture 在自定义 opengl 纹理上绘制相机帧,而无需使用 android 提供的转换矩阵。
只需尝试像普通纹理绘制那样定义索引顶点和纹理。比如这个。
const GLfloat Vertices[] = 0.5, -0.5, 0,
0.5, 0.5, 0,
-0.5, 0.5, 0,
-0.5, -0.5, 0;
const GLubyte Indices[] = 0, 1, 2,
2, 3, 0 ;
const GLfloat Textures[] = 1.,0.,
0.,0.,
0.,1.,
1.,1. ;
您应该能够像使用普通纹理一样使用表面纹理。
如果您想要执行某种 3D 投影,请参阅good post,了解如何生成正确的 MVP 矩阵。您可以使用它与顶点着色器中的位置相乘。
【讨论】:
好建议。或者我可以将正确的纹理坐标发送到着色器。我更新了顶点着色器,以便它可以帮助其他人。 那我们为什么要提供变换矩阵呢? 参见 Fabien R 编辑的“Edited nov 3, 2012”。我正在添加一个简短的答案来解决这一点。【参考方案2】:由于我有同样的问题,即使这个问题有点老了,可能值得详细说明一下“为什么使用变换矩阵”。
转换矩阵映射 SurfaceTexture 使用的特定坐标集(或更可能 当前视频源 流式传输到 SurfaceTexture...) 到标准的 OpenGL 纹理坐标。
绝对应该使用它的原因是,尽管 Startibartfast 答案适用于一个或多个特定设置,并且可能很容易实现且很诱人,当运行相同的程序时,它可能会产生奇怪的可视化错误不同的设备,具体取决于每个平台的视频驱动程序实现。
例如,在我的例子中,变换矩阵只是将内容颠倒过来(我在 Nexus 7 上将 SurfaceTexture 与 MediaPlayer 结合使用),而不是 Fabien R 指出的结果。
在 2012 年 11 月 3 日的 Fabien R 编辑中指出了使用矩阵的正确方法,我报告了一些小修饰(如使用 st 索引),并进行了小修正int/float 不匹配:
attribute vec2 uv;
varying vec2 vTexCoord;
uniform mat4 transformMatrix;
vTexCoord = (transformMatrix * vec4(uv, 0.0, 1.0)).st;
希望对你有帮助
【讨论】:
以上是关于通过 SurfaceTexture 在 GLSurfaceView 上显示相机流的主要内容,如果未能解决你的问题,请参考以下文章
Android:将 SurfaceTexture 附加到 FrameBuffer
如何以类似于相机为 SurfaceTexture 生成帧的方式生成 YUVI420 帧到 SurfaceTexture?
音视频开发系列——详解Android SurfaceTexture
Android - 在 SurfaceTexture 上绘制 YouTube 视频