gpt4 book ai didi

android - glReadPixels 在 WebRTC Android SurfaceViewRenderer 中不起作用

转载 作者:太空狗 更新时间:2023-10-29 13:15:00 25 4
gpt4 key购买 nike

我正在尝试从 WebRTC Android 应用程序保存帧。在 SurfaceViewRenderer.java它使用 GLES 着色器绘制 YUV 帧。为了保存绘制的框架,我从 grafika 添加了 saveFrame()到 SurfaceViewRenderer.java 但当我调用 saveFrame() 它不起作用(位图为空)。我以为 glReadPixels() 从当前颜色缓冲区读取像素,但它似乎没有在当前 EGLcontext 中调用?如何调用glReadPixels()保存当前帧?

我写的代码是这样的:

在 MainActivity 中我添加了这样的按钮。

button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bitmap = localSurfaceViewRender.saveFrame();
if (bitmap != null) {
Toast.makeText(getApplicationContext(), "Saved!!", Toast.LENGTH_SHORT).show();
imageView.setImageBitmap(bitmap);
}
}
});

在 SurfaceViewRenderer.java 我添加了一些方法来从当前绑定(bind)的 egl 中获取值

public int getSurfaceHeight() {
if (mHeight < 0) {
return eglBase.surfaceHeight();
} else {
return mHeight;
}
}

public int getSurfaceWidth() {
if (mWidth < 0) {
return eglBase.surfaceWidth();
} else {
return mWidth;
}
}


public Bitmap saveFrame() {
int width = eglBase.surfaceWidth();
int height = eglBase.surfaceHeight();
ByteBuffer buf = ByteBuffer.allocateDirect(width * height * 4);
buf.order(ByteOrder.LITTLE_ENDIAN);
GLES20.glFinish();
GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGB, GLES20.GL_UNSIGNED_BYTE, buf);
GlUtil.checkNoGLES2Error("glReadPixels");
buf.rewind();
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bmp.copyPixelsFromBuffer(buf);
return bmp;
}

编辑:这段代码是saveFrame的完整代码

// save as a file
public void saveFrame(final File file) {
runOnRenderThread(new Runnable() {
@Override
public void run() {
int width = eglBase.surfaceWidth();
int height = eglBase.surfaceHeight();
ByteBuffer buf = ByteBuffer.allocateDirect(width * height * 4);
buf.order(ByteOrder.LITTLE_ENDIAN);
GLES20.glFinish();
GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buf);
GlUtil.checkNoGLES2Error("glReadPixels");
buf.rewind();

// fliping by vertical
byte[] tmp = new byte[width * 4];
for (int i = 0; i < height / 2; i++) {
buf.get(tmp);
System.arraycopy(buf.array(), buf.limit() - buf.position(),
buf.array(), buf.position() - width * 4, width * 4);
System.arraycopy(tmp, 0, buf.array(), buf.limit() - buf.position(), width * 4);
}
buf.rewind();

String filename = file.toString();
BufferedOutputStream bos = null;
try {
bos = new BufferedOutputStream(new FileOutputStream(filename));
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bmp.copyPixelsFromBuffer(buf);
bmp.compress(Bitmap.CompressFormat.JPEG, 100, bos);
bmp.recycle();
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (bos != null) try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}

Log.d(TAG, "Saved " + width + "x" + height + " frame as '" + filename + "'");
}
});
}

最佳答案

glReadPixels() 函数从当前上下文中读取帧缓冲区的内容。一旦 eglSwapBuffers() 被调用,内容就消失了。

换句话说,应用无法从 SurfaceView 中读取任何内容。因此,您必须在将缓冲区提交给合成器之前读出像素。

(我实际上不确定如果您在交换缓冲区后立即调用 glReadPixels() 会发生什么......您可能会从回收缓冲区读取先前发送的帧,但您不能总是依赖它。)

您似乎是从主 UI 线程调用 glReadPixels()。如果 SurfaceView 渲染发生在不同的线程上,您将需要从同一个线程访问帧缓冲区,因为这是 EGL 上下文当前所在的位置。给定的上下文不能同时在多个线程中处于当前状态。

关于android - glReadPixels 在 WebRTC Android SurfaceViewRenderer 中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35764190/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com