Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/213.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android glReadPixels速度很慢_Android_Opengl Es 2.0_Android Camera2 - Fatal编程技术网

Android glReadPixels速度很慢

Android glReadPixels速度很慢,android,opengl-es-2.0,android-camera2,Android,Opengl Es 2.0,Android Camera2,我正在使用GLSURFACHEVIEW创建自定义相机预览,使用OpenGl渲染相机提供给我的帧。我已经完全实现了摄像头,并且正在努力使摄像头能够在没有fps损失和正确的高宽比等情况下工作。但是,当我需要捕获来自摄像头馈送的帧时,问题出现了,我的第一个想法是使用glReadPixles() 使用GLES20.glReadPixels()我发现一些设备会出现fps丢失,主要是屏幕分辨率更高的设备。这是有意义的,因为glReadPixels需要读取更多分辨率更高的像素 我做了一些挖掘,发现其他人在gl

我正在使用GLSURFACHEVIEW创建自定义相机预览,使用OpenGl渲染相机提供给我的帧。我已经完全实现了摄像头,并且正在努力使摄像头能够在没有fps损失和正确的高宽比等情况下工作。但是,当我需要捕获来自摄像头馈送的帧时,问题出现了,我的第一个想法是使用glReadPixles()

使用GLES20.glReadPixels()我发现一些设备会出现fps丢失,主要是屏幕分辨率更高的设备。这是有意义的,因为glReadPixels需要读取更多分辨率更高的像素

我做了一些挖掘,发现其他人在glReadPixels方面也有类似的问题,许多人建议使用PBO,使用其中两个作为双缓冲区,这样我就可以读取像素数据,而不会阻塞/暂停当前的渲染过程。我完全理解双缓冲的概念,我对OpenGL相当陌生,需要一些关于如何使双缓冲PBO工作的指导

我已经找到了一些PBO双缓冲的解决方案,但是我从来没有找到一个完整的解决方案来完全理解它如何与GLES交互

我对GLSurfaceView.Renderer.onDrawFrame()的实现


经过大量的研究和挖掘,我找到了glReadPixels的解决方案,以及如何使用PBO缓冲图像/帧以供以后处理

因此,我们需要做的第一件事是在GLES2中公开一个附加函数。 在应用程序模块中,添加一个名为cpp的新目录,然后创建一个名为GlesHelper的新c文件(或任何您想要的名称)

并粘贴以下代码:

#include <jni.h>
#include <GLES2/gl2.h>
JNIEXPORT void JNICALL


// Change
Java_com_your_full_package_name_helper_GlesHelper_glReadPixels(JNIEnv *env, jobject instance, jint x,
                                                        jint y, jint width, jint height,
                                                        jint format, jint type) {
    // TODO
    glReadPixels(x, y, width, height, format, type, 0);
}
现在打开你的app/modules build.gradle文件

externalNativeBuild {
    // Encapsulates your CMake build configurations.
    cmake {
        // Provides a relative path to your CMake build script.
        cppFlags "-std=c++11 -fexceptions"
        arguments "-DANDROID_STL=c++_shared"
    }
}
externalNativeBuild {
// Encapsulates your CMake build configurations.
    cmake {

        // Provides a relative path to your CMake build script.
        path "CMakeLists.txt"
    }
}
将其粘贴到Gradle文件的android.defaultConfig部分

externalNativeBuild {
    // Encapsulates your CMake build configurations.
    cmake {
        // Provides a relative path to your CMake build script.
        cppFlags "-std=c++11 -fexceptions"
        arguments "-DANDROID_STL=c++_shared"
    }
}
externalNativeBuild {
// Encapsulates your CMake build configurations.
    cmake {

        // Provides a relative path to your CMake build script.
        path "CMakeLists.txt"
    }
}
然后将其粘贴到Gradle文件的android部分

externalNativeBuild {
    // Encapsulates your CMake build configurations.
    cmake {
        // Provides a relative path to your CMake build script.
        cppFlags "-std=c++11 -fexceptions"
        arguments "-DANDROID_STL=c++_shared"
    }
}
externalNativeBuild {
// Encapsulates your CMake build configurations.
    cmake {

        // Provides a relative path to your CMake build script.
        path "CMakeLists.txt"
    }
}
这就是所有的MakeFile和c的东西,所有的设置都让我们转移到一些java上

在项目中创建一个与c文件中的包匹配的新文件,即 com\u your\u full\u package\u name\u helper=com.your.full.package.name.helper

确保这些匹配正确,与类名和函数名相同

你的班级应该是这样的

package com.your.full.package.name.helper;

public class GlesHelper
{
    public static native void glReadPixels(int x, int y, int width, int height, int format, int type);
}
因为我们已经向项目中添加了本机代码,所以我们需要使用System.loadLibrary(“本机库”)来加载我们的新方法

在开始下一步之前,将这些成员变量添加到渲染器中

/**
 * The PBO Ids, increase the allocate amount for more PBO's
 * The more PBO's the smoother the frame rate (to an extent)
 * Side affect of having more PBO's the frames you get from the PBO's will lag behind by the amount of pbo's
 */
private IntBuffer mPboIds = IntBuffer.allocate(2);;

/**
 * The current PBO Index
 */
private int mCurrentPboIndex = 0;

/**
 * The next PBO Index
 */
private int mNextPboIndex = 1;
所以现在我们需要初始化我们的PBO,这很简单

    // Generate the buffers for the pbo's
    GLES30.glGenBuffers(mPboIds.capacity(), mPboIds);

    // Loop for how many pbo's we have
    for (int i = 0; i < mPboIds.capacity(); i++)
    {
        // Bind the Pixel_Pack_Buffer to the current pbo id
        GLES30.glBindBuffer(GLES30.GL_PIXEL_PACK_BUFFER, mPboIds.get(i));

        // Buffer empty data, capacity is the width * height * 4
        GLES30.glBufferData(GLES30.GL_PIXEL_PACK_BUFFER, capacity, null, GLES30.GL_STATIC_READ);
    }

    // Reset the current buffer so we can draw properly
    GLES30.glBindBuffer(GLES30.GL_PIXEL_PACK_BUFFER, 0);
回到我最初的问题,我们的Redner/OnDraw方法看起来是这样的

    // Use the OpenGL Program for rendering
    GLES20.glUseProgram(mProgram);

    // If the Texture Matrix is not null
    if (textureMatrix != null)
    {
        // Apply the Matrix
        GLES20.glUniformMatrix4fv(mTexMatrixLoc, 1, false, textureMatrix, 0);
    }


    // Apply the Matrix
    GLES20.glUniformMatrix4fv(mMVPMatrixLoc, 1, false, mMvpMatrix, 0);

    // Bind the Texture
    GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureID);

    // Draw the texture
    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, GLConstants.VERTEX_NUM);

    // Unbind the Texture
    GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0);

    // Read from PBO
    readPixelsFromPBO()
我希望这能帮助那些在glReadPixels性能方面有类似问题的人,或者至少在努力实现PBO的

可能相关的: