在Android中,对setPreviewCallback感到非常困惑,需要建议。

5
我正在开发一款Android应用程序,用于从相机中获取帧,对其进行处理,然后通过SurfaceView显示帧,并通过画布和drawBitmap在SurfaceView上绘制。请问,使用SurfaceView、位图和画布是否是最佳方法?我需要速度。
假设上述答案是肯定的,那么问题就是:我应该把以下函数放在哪里?
camera_object.setPreviewCallback(new PreviewCallback()
     public void onPreviewFrame(byte[] data, Camera camera){

我应该将它放在 onCreate() 中还是放在 surfaceCreated() 或 surfaceChanged() 中?
我的 MainActivity 类定义如下:
public class MainActivity extends Activity implements SurfaceHolder.Callback, Camera.PreviewCallback
{

在那个类中,Eclipse强制我创建一个MainActivity类中onpreviewframe的覆盖函数,如下所示:

public void onPreviewFrame(byte[] data, Camera camera){
}

但它从未被调用。我应该尝试使用这个函数吗?使用它是否更好?还是这只是Eclipse的一个东西?
请给予建议。
2个回答

8
你是否在应用程序中调用了setPreviewDisplay(), startPreview(), 和setPreviewCallback(this)?如果没有,你将无法收到任何关于onPreviewFrame()的调用。事实上,如果你正在使用SurfaceView,则回调预览缓冲区是正在显示在屏幕上的实际缓冲区的副本。因此,如果你想要显示这些复制的缓冲区,你需要创建一个新视图并覆盖它。这将是低效的。我建议你使用SurfaceTexture代替,并使用'onFrameAvailable'回调来获取帧,然后手动绘制和显示。默认的Android相机应用程序的PanoramaActivity代码中可以找到这个示例。

非常感谢您的回复。 我的做法是,我使用以下代码: surface_view = (SurfaceView) findViewById(R.id.surfaceview1); surface_holder = surface_view.getHolder(); surface_holder.addCallback(this); 以及 camera_object.startPreview(); 但我不使用camera_object.setPreviewDisplay(surface_holder);,因为我不想显示实际的帧,我只想显示来自回调的帧。我会检查一下SurfaceTexture,它看起来非常有前途。 - Mohamed Heiba
1
伙计们,我已经成功地让它工作了,而不使用setpreviewdisplay。我不想将相机帧直接渲染到surfaceview上,而是取出这些帧,使用画布进行处理和绘制。但问题是这样非常慢。如果我使用setpreviewdisplay,我的处理后的帧将与渲染的显示不同步,所以方块只会在脸部上显示2秒钟左右,期间脸部已经移动到屏幕上的其他位置,顺便说一下,我正在做人脸检测。 - Mohamed Heiba
我知道了,你说得对。通过回调接收到的帧与正在显示的不同。Onpreviewframe回调与预览帧不同步。是的,此时不需要设置预览显示。 - vikky.rk
2
但别确定它在每个设备上都能正常工作。一些硬件供应商如果未设置previewDisplay,则可能不会发送回调。这取决于实现。 - vikky.rk
是的,我知道例如HTC ONE X这样的手机如果没有设置setpreviewdisplay就永远不会工作,太疯狂了! - Mohamed Heiba
显示剩余2条评论

1

没有 camera_object.setPreviewDisplay(surface_holder);,您将无法接收相机回调;还要记得

surface_view.setVisibility(View.VISIBLE);
surface_holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

您可以将相机预览隐藏在另一个视图下面;在3.0及更高版本中,您甚至可以将表面推出屏幕(在屏幕底部以下显示)。我不确定后一种技巧是否适用于2.3.6。


嗨,我的做法是从onpreviewframe中获取帧,转换为位图,使用画布来保存表面,绘制位图图像并在位图图像上使用画布进行绘制。 - Mohamed Heiba
这样做没问题,但速度非常慢... 使用OpenGL渲染抓取的帧会显著提高速度。 - Alex Cohn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接