> 文档中心 > 鸿蒙Camera实时循环帧捕获要注意管理内存

鸿蒙Camera实时循环帧捕获要注意管理内存

在做一个实时人脸识别的项目遇到一个坑:提示内存OOM问题。之前发过帖子

https://developer.huawei.com/consumer/cn/forum/topic/0201850940742030057?fid=0102683795438680754&pid=0304853536638170167

先说结论吧:Camera循环帧捕获时要及时管理内存。

1.创建初始项目参照CameraDemo(示例中虽然有给到循环帧捕获但是没有给到ImageArrivalListener的处理示例)https://developer.harmonyos.com/cn/docs/documentation/doc-guides/media-camera-guidelines-0000000000031782

我们在点击按钮时注意两点:

1把triggerSingleCapture换成triggerLoopingCapture

2要注意addSurface是add了两个不同的surface,一个是展示预览画面,一个是回调捕获图像的surface。如果只add一个Surface,例如只增加了previewSurface, 没法触发下文所说的ImageArrivalListener事件;如果只增加了imageReceiver的Surface,画面会假死(停留在按钮刚按下捕获的图像,没有持续预览)

另外在

private void takeLoopingCapture(Component component) {    if (cameraDevice == null || imageReceiver == null) { return;    }    FrameConfig.Builder framePictureConfigBuilder = cameraDevice.getFrameConfigBuilder(FRAME_CONFIG_PICTURE);    framePictureConfigBuilder.addSurface(previewSurface);    framePictureConfigBuilder.addSurface(imageReceiver.getRecevingSurface());    FrameConfig pictureFrameConfig = framePictureConfigBuilder.build();    cameraDevice.triggerLoopingCapture(pictureFrameConfig);}复制

另外在初始化摄像头时设定方法回调。
imageReceiver.setImageArrivalListener(this::proccessImage);

它有点类似于android的Camera.PreviewCallback,用于打开摄像头时读取每一帧图片

处理图像后要及时释放内存,这才是重点。

    private synchronized void proccessImage(ImageReceiver receiver) {//获取帧图像     ohos.media.image.Image image = receiver.readNextImage();     ohos.media.image.Image.Component component = image.getComponent(ImageFormat.ComponentType.JPEG);     byte[] bytes = new byte[component.remaining()];     component.read(bytes);     ImageSource imageSource = ImageSource.create(bytes, null);     PixelMap pixelMap = imageSource.createPixelmap(new ImageSource.DecodingOptions());//处理图像例如保存...省略代码三万字//之后作release处理     image.release();     component.release();     imageSource.release();     pixelMap.release(); }});    }复制

之前没做image.release()处理,就是proccessImage整个方法为空也会提示如下

getBufferLockedCommon: Stream 1: Can't dequeue next output buffer: Connection timed out (-110)04-10 20:45:59.924 1058-27812/? E Camera3-OutputStream:  getBufferLockedCommon: Stream 1:consumerName:[ImageReceiver-1080x1920f3c9-26408-3]: dequeue buffer cost: ( 1161 ms)04-10 20:45:59.924 1058-27812/? E Camera3-OutputStream:  getBufferLockedCommon: Stream 1: Can't dequeue next output buffer: Connection timed out (-110)

我尝试过设定一个定时比如每过2s是自动捕捉图像,但没过几秒钟马上会OOM,提示如下

 java.lang.OutOfMemoryError: pthread_create (1040KB stack) failed: Out of memory 

     at java.lang.Thread.nativeCreate(Native Method) 

     at java.lang.Thread.start(Thread.java:893) 

     at com.wincent.harmonybot.slice.TestCameraAbilitySlice.takeSingleCapture(TestCameraAbilitySlice.java:200) 

综上:一定要通过release方法释放内存。

但是目前,虽然当前画面能显示,但是略显卡顿,不知道是我proccessImage里面的处理方法相对耗内存还是怎样,如果大家有更好的方案,欢迎提出。