Android Camera API1预览回调接口Camera.PreviewCallback

本文详细介绍了Android Camera API1中预览回调接口的三种方式:setPreviewCallback、setOneShotPreviewCallback和setPreviewCallbackWithBuffer,强调了内存管理和线程安全的重要性。setPreviewCallback会导致onPreviewFrame在主线程中运行,可能阻塞UI,需在子线程中打开相机。setOneShotPreviewCallback只回调一次,而setPreviewCallbackWithBuffer配合addCallbackBuffer使用能提高效率并管理内存。文章还提到了缓冲区大小的计算方法,并提醒在使用setPreviewCallbackWithBuffer时必须手动添加缓冲区。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PreviewCallback接口如:

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

三个预览回调接口的方法:

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);//将此缓冲区添加到预览回调缓冲区队列中
}

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

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

    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,然后从缓冲区队列中移除此缓冲区。

      参考文档:

           https://blog.youkuaiyun.com/lb377463323/article/details/53338045

           https://blog.youkuaiyun.com/superman4933/article/details/55045676

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值