我正在尝试修改 WebRTC Android http://webrtc.org/native-code/android/将视频流显示到 Google CardboardView 中。在 SurfaceViewRenderer.java 和 GlRectDrawer.java来源,他们使用这些顶点和 fragment 着色器:
private static final String VERTEX_SHADER_STRING =
"varying vec2 interp_tc;\n"
+ "attribute vec4 in_pos;\n"
+ "attribute vec4 in_tc;\n"
+ "\n"
+ "uniform mat4 texMatrix;\n"
+ "\n"
+ "void main() {\n"
+ " gl_Position = in_pos;\n"
+ " interp_tc = (texMatrix * in_tc).xy;\n"
+ "}\n";
private static final String YUV_FRAGMENT_SHADER_STRING =
"precision mediump float;\n"
+ "varying vec2 interp_tc;\n"
+ "\n"
+ "uniform sampler2D y_tex;\n"
+ "uniform sampler2D u_tex;\n"
+ "uniform sampler2D v_tex;\n"
+ "\n"
+ "void main() {\n"
// CSC according to http://www.fourcc.org/fccyvrgb.php
+ " float y = texture2D(y_tex, interp_tc).r;\n"
+ " float u = texture2D(u_tex, interp_tc).r - 0.5;\n"
+ " float v = texture2D(v_tex, interp_tc).r - 0.5;\n"
+ " gl_FragColor = vec4(y + 1.403 * v, "
+ " y - 0.344 * u - 0.714 * v, "
+ " y + 1.77 * u, 1);\n"
+ "}\n";
而且看起来只是简单地画了一个矩形框
所以我认为它也适用于 CardboardView。但它在 VR 模式下不能像这样正确绘制:
我在禁用 VR 模式时检查它是否正确绘制
以下代码是我的 onDrawEye() 方法中的实际绘制代码。我只是简单地改编SurfaceViewRenderer.java代码
// Fetch and render |pendingFrame|.
final VideoRenderer.I420Frame frame;
synchronized (frameLock) {
if (pendingFrame == null) {
return;
}
frame = pendingFrame;
pendingFrame = null;
}
final long startTimeNs = System.nanoTime();
final float[] texMatrix;
synchronized (layoutLock) {
final float[] rotatedSamplingMatrix = RendererCommon.rotateTextureMatrix(frame.samplingMatrix, frame.rotationDegree);
final float[] layoutMatrix = RendererCommon.getLayoutMatrix(mirror, frameAspectRatio(), (float) layoutWidth / layoutHeight);
texMatrix = RendererCommon.multiplyMatrices(rotatedSamplingMatrix, layoutMatrix);
}
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
if (frame.yuvFrame) {
// Make sure YUV textures are allocated.
if (yuvTextures == null) {
yuvTextures = new int[3];
for (int i = 0; i < 3; i++) {
yuvTextures[i] = createTexture(GLES20.GL_TEXTURE_2D);
}
}
drawer.uploadYuvData(
yuvTextures, frame.width, frame.height, frame.yuvStrides, frame.yuvPlanes);
drawer.drawYuv(yuvTextures, texMatrix);
} else {
drawer.drawOes(frame.textureId, texMatrix);
}
VideoRenderer.renderFrameDone(frame);
synchronized (statisticsLock) {
if (framesRendered == 0) {
firstFrameTimeNs = startTimeNs;
}
++framesRendered;
renderTimeNs += (System.nanoTime() - startTimeNs);
if (framesRendered % 300 == 0) {
logStatistics();
}
}
我仍然无法弄清楚是什么原因。我该如何解决? 提前致谢。
编辑:它似乎只正确绘制了第一个(?)帧,然后像上图一样在没有纹理的情况下绘制。
最佳答案
使用 OpenGL 跟踪器后,我找到了解决方案。其实很简单。
每次在 GlRectDrawer.java 中调用 drawYuv() 时,它都会准备着色器并设置顶点属性,即顶点和纹理坐标。当在 CardboardView 的 onDrawEye() 中调用它时,CardboardView 会使用其他着色器和顶点属性进行失真校正。
对于下一帧,要设置的顶点属性与 drawYuv() 中的相同。原始 GlRectDrawer.java 源代码不会在每次调用中设置顶点数据所以我只是简单地再次设置顶点数据。
关于java - 在 CardboardView 上显示的 YUV 视频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34427483/