我需要能够在屏幕上显示来自正在运行的相机实例的两个相同的预览,这可能吗?
到目前为止,我能想到的唯一方法是克隆预览表面视图。所以使用提供给onPreviewFrame的原始视频数据, 我正在为当前帧创建一个新的位图,然后将其绘制到surfaceholder画布。
在ui线程上运行时显示效果很好,但显然在创建位图时每隔几秒就会阻止UI。我现在已经将位图创建移动到一个新线程中,该线程可以解决应用程序锁定问题,但现在我的表面视图会轻微地闪烁/撕裂!
这会有用吗?或者我是否采取了错误的方式?如何阻止闪烁?
减少示例代码;
public void onPreviewFrame(byte[] data, Camera camera) {
-- new thread
// create bitmap from YUV (videoFrame)
-- UI thread
Canvas canvas = null;
try {
canvas = surfaceHolder.lockCanvas();
if (canvas != null) {
canvas.drawBitmap(videoFrame, null, new Rect(0, 0, 200, 200), null);
}
} catch (Exception e) {
mLogger.error(e.getMessage());
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
我相信这与surfaceview双缓冲区有关,我有很多解决方案但是无法阻止闪烁!
答案 0 :(得分:3)
如果你不需要在3.0之前的Android版本(Honeycomb)上运行,你可以使用SurfaceTexture输出选项和OpenGL ES来渲染多个预览。
设置一个有效的OpenGL视图有点涉及,所以你需要找到一个指南。 完成后,创建一个SurfaceTexture对象,其中包含要用于预览纹理的OpenGL纹理ID,使用setPreviewTexture而不是使用setPreviewDisplay将其传递到相机中,然后在OpenGL线程中传递,调用updateTexImage更新纹理以显示来自摄像头的最新帧(最好这样做是为了响应onFrameAvailable回调以获得最佳性能)。
然后你需要OpenGL代码为你的两个预览副本渲染两个矩形,并使用着色器在两者上绘制预览纹理。
这是一个不错的设置,但最后,你将拥有一个非常灵活的系统 - 然后你可以用各种有趣的方式为预览设置动画等。