Android Camera的预览回调接口PreviewCallback使用

 原文章:https://blog.csdn.net/lb377463323/article/details/53338045

首先定义一个类实现Camera.PreviewCallback接口,然后在它的onPreviewFrame(byte[] data, Camera camera)方法中即可接收到每一帧的预览数据,也就是参数data。 

然后使用setPreviewCallback()、setOneShotPreviewCallback或setPreviewCallbackWithBuffer()注册回调接口,下面介绍一下这些方法: 
1,void setPreviewCallback (Camera.PreviewCallback cb) 
一旦使用此方法注册预览回调接口,onPreviewFrame()方法会一直被调用,直到camera preview销毁

注意,onPreviewFrame()方法跟Camera.open()是运行于同一个线程,所以为了防止onPreviewFrame()会阻塞UI线程,将Camera.open()放置在子线程中运行。

2,void setOneShotPreviewCallback (Camera.PreviewCallback cb) 
使用此方法注册预览回调接口时,会将下一帧数据回调给onPreviewFrame()方法,调用完成后这个回调接口将被销毁。也就是只会回调一次预览帧数据。 
3,void setPreviewCallbackWithBuffer (Camera.PreviewCallback cb) 
它跟setPreviewCallback的工作方式一样,但是要求指定一个字节数组作为缓冲区,用于预览帧数据,这样能够更好的管理预览帧数据时使用的内存。它一般搭配addCallbackBuffer方法使用,伪代码如下:

byte[] mPreBuffer = new byte[size];//首先分配一块内存作为缓冲区,size的计算方式见第四点中
mCamera.addCallbackBuffer(mPreBuffer);
mCamera.setPreviewCallbackWithBuffer(Camera.PreviewCallback cb);
mCamera.startPreview();

@Override
public void onPreviewFrame(byte[] data, Camera camera) {
    if (mPreBuffer == null) {
        mPreBuffer = new byte[size];
    }
    mCamera.addCallbackBuffer(mPreBuffer);//将此缓冲区添加到预览回调缓冲区队列中
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

setPreviewCallbackWithBuffer需要在startPreview()之前调用,因为setPreviewCallbackWithBuffer使用时需要指定一个字节数组作为缓冲区,用于预览帧数据,所以我们需要在setPreviewCallbackWithBuffer之前调用addCallbackBuffer,这样onPreviewFrame的data才有值。

总结一下,设置addCallbackBuffer的地方有两个,一个是在startPreview之前,一个是在onPreviewFrame中,这两个都需要调用,如果在onPreviewFrame中不调用,那么预览帧数据就不会回调给onPreviewFrame了

4,void addCallbackBuffer (byte[] callbackBuffer) 
添加一个预分配的缓冲区到预览回调缓冲区队列中。应用程序可一添加一个或多个缓冲器到这个队列中。当预览帧数据到达时并且缓冲区队列仍然有至少一个可用的缓冲区时,这个 缓冲区将会被消耗掉然后从队列中移除,然后这个缓冲区会调用预览回调接口。如果预览帧数据到达时没有剩余的缓冲区,这帧数据将会被丢弃。当缓冲区中的数据处理完成后,应用程序应该将这个缓冲区添加回缓冲区队列中。 
对于非YV12的格式,缓冲区的Size是预览图像的宽、高和每个像素的字节数的乘积。宽高可以使用getPreviewSize()方法获取。每个像素的字节数可以使用ImageFormat.getBitsPerPixel(mCameraParameters.getPreviewFormat()) / 8获取。 
对于YU12的格式,缓冲区的Size可以使用setPreviewFormat(int)里面的公式计算,具体详见官方文档。 
这个方法只有在使用setPreviewCallbackWithBuffer(PreviewCallback)时才有必要使用。当使用setPreviewCallback(PreviewCallback) 或者setOneShotPreviewCallback(PreviewCallback)时,缓冲区会自动分配。当提供的缓冲区如果太小了,不能支持预览帧数据时,预览回调接口将会return null,然后从缓冲区队列中移除此缓冲区。

猜你喜欢

转载自blog.csdn.net/hello_jiangdong/article/details/80966652