【问题标题】:YUV video displaying on CardboardView在 CardboardView 上显示 YUV 视频
【发布时间】:2015-12-23 02:05:20
【问题描述】:

我正在尝试修改 WebRTC Android http://webrtc.org/native-code/android/ 以在 Google CardboardView 中显示视频流。在 SurfaceViewRenderer.java 和 GlRectDrawer.java 源中,他们使用了这些顶点和片段着色器:

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 模式下不能像这样正确绘制:

我在禁用 VRmode 时检查了它是否正确绘制

以下代码是我的 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();
        }
    }

我仍然无法弄清楚是什么原因。我该如何解决? 提前致谢。

编辑:它似乎只正确绘制了第一个(?)帧,然后在没有纹理的情况下绘制,如上图。

【问题讨论】:

    标签: java android opengl-es glsurfaceview google-cardboard


    【解决方案1】:

    使用 OpenGL 跟踪器后,我找到了解决方案。其实很简单。

    每次在 GlRectDrawer.java 中调用 drawYuv() 时,它都会准备着色器并设置顶点属性,即顶点和纹理坐标。当在 CardboardView 中调用 onDrawEye() 时,CardboardView 会使用其他着色器和顶点属性进行失真校正。

    对于下一帧,要设置的顶点属性与 drawYuv() 中相同。原始 GlRectDrawer.java 源没有在每次调用中设置顶点数据所以我只是简单地再次设置顶点数据。

    【讨论】:

    • 嘿@kju 你能贴一些代码吗,你是如何在opengl中使用SurfaceViewRenderer.java的
    • @Shishram 我实际上使用 VideoRendererGui.java 进行绘图。我上传了CardboardRenderer.java 类,它是 Google Cardboard 的修改版本。这是相当旧的版本,因此您不必创建单独的 ImageRenders。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-24
    • 2013-12-04
    • 1970-01-01
    • 2012-01-24
    相关资源
    最近更新 更多