我正在尝试将一个帧缓冲区(带有渲染缓冲区)应用于一个直接从Android摄像头获取视频帧的Surface。我正在捕捉帧并将它们保存到磁盘。
以下是代码:
String filename = file.toString();
int width = getWidth();
int height = getHeight();
ByteBuffer buf = ByteBuffer.allocateDirect(width * height * 4);
buf.order(ByteOrder.LITTLE_ENDIAN);
int[] fboId = new int[1];
int[] rendId = new int[1];
GLES20.glGenFramebuffers(1, fboId, 0);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fboId[0]);
GLES20.glGenRenderbuffers(1, rendId, 0);
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, rendId[0]);
GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER,GLES20.GL_RGBA4, width, height);
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_RENDERBUFFER,rendId[0] );
GLES20.glViewport(0,0,width, height);
Log.i(TAG, "Complete? "+ GLES20.GL_FRAMEBUFFER_COMPLETE);
GLES20.glReadPixels(0, 0, width, height,
GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buf);
GlUtil.checkGlError("glReadPixels");
buf.rewind();
BufferedOutputStream bos = null;
try {
Long startTime = System.currentTimeMillis();
bos = new BufferedOutputStream(new FileOutputStream(filename));
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bmp.copyPixelsFromBuffer(buf);
bmp.compress(Bitmap.CompressFormat.PNG, 90, bos);
bmp.recycle();
Log.i("time elapsed", String.valueOf(System.currentTimeMillis()-startTime) + " milliseconds");
} finally {
if (bos != null) bos.close();
}
Log.d(TAG, "Saved " + width + "x" + height + " frame as '" + filename + "'");
}
重要说明:这是问题的帧缓冲/渲染缓冲器实现。我知道这是因为我的代码在没有帧缓冲的情况下工作(从
中删除所有内容)int[] fboID
到
GLES20.glViewport
我从Google Grafika继承了此代码,它在没有帧缓冲区的情况下运行。我正在添加帧缓冲,因此我可以在将图像保存为位图之前快速旋转图像。 问题是:在我的Framebuffer实现中我做错了什么 产生一个3.6kb的空白帧(即使分辨率为1280x720)。
我希望这段代码能够从我的EGLSurfaceBase上下文中呈现一个帧,并将其作为位图保存到磁盘。如果代码不这样做 - 缺少什么?我看不出这个和我一直用作模板的Framebuffers的其他教程之间的区别。