鸿蒙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里面的处理方法相对耗内存还是怎样,如果大家有更好的方案,欢迎提出。