我有一个应用程序,我想在其中处理相机中的每个给定帧以做一些ARCore的工作。因此,我有一个实现GLSurfaceView.Renderer
的类,并且在这个类中有onDrawFrame(GL10 gl)
方法。在这种方法中,我想使用Android位图,因此我调用以下代码从当前帧中获取位图:
private Bitmap getTargetImageBitmapOpenGL(int cx, int cy, int w, int h) {
try {
if (currentTargetImageBitmap == null) {
currentTargetImageBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
byteBuffer = ByteBuffer.allocateDirect(w * h * 4);
byteBuffer.order(ByteOrder.nativeOrder());
}
// cy = height - cy;
if ((cx + w / 2) > width) {
Log.e(TAG, "TargetImage CenterPoint invalid A: " + cx + " " + cy);
cx = width - w / 2;
}
if ((cx - w / 2) < 0) {
Log.e(TAG, "TargetImage CenterPoint invalid B: " + cx + " " + cy);
cx = w / 2;
}
if ((cy + h / 2) > height) {
Log.e(TAG, "TargetImage CenterPoint invalid C: " + cx + " " + cy);
cy = height - h / 2;
}
if ((cy - h / 2) < 0) {
Log.e(TAG, "TargetImage CenterPoint invalid D: " + cx + " " + cy);
cy = h / 2;
}
int x = cx - w / 2;
int y = cy - h / 2;
GLES20.glReadPixels(x, y, w, h, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE,
byteBuffer);
IntBuffer currentTargetImagebuffer = byteBuffer.asIntBuffer();
currentTargetImagebuffer.rewind();
currentTargetImageBitmap.copyPixelsFromBuffer(currentTargetImagebuffer);
return currentTargetImageBitmap;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
此方法大约需要90毫秒,这绝对太慢,无法实时处理每个传入的帧,这是我需要做的,因为onDrawFrame(GL10 gl)
方法也将该帧绘制到表面视图。知道为什么这么慢吗?如果我只能读取其他每一帧的像素,但将每一帧绘制到我的SurfaceView,也就足够了。我试图在AsyncTask.execute()
中调用显示的方法,但是另一个线程无法通过GLES20.glReadPixels()
方法读取,因为它不是GL线程。
答案 0 :(得分:0)
许多现代GPU都可以对YUV进行本地解码;问题是如何使YUV表面进入OpenGL ES,因为这通常不是Open GL ES要做的。大多数操作系统(包括Android)可让您通过EGL_image_external
扩展名将外部表面直接导入OpenGL ES,并且可以使用自动颜色转换将这些外部表面标记为YUV。
更好的是,所有这些都是零副本;相机缓冲区可以直接由GPU导入和访问。
这种Android的导入机制是通过SurfaceTexture
类的,此处描述了必要的用法:https://source.android.com/devices/graphics/arch-st