HarmonyOS 鸿蒙Next中相机无法稳定获取视频帧

HarmonyOS 鸿蒙Next中相机无法稳定获取视频帧 我写了一个demo,只有打开相机,并预览,同时获取视频帧数据,hilog中大量报错:

<buffer_queue.cpp:320-RequestBufferDebugInfoLocked>: all buffer are using, uniqueId: 257560598806528, Released: 0 Requested: 3 Flushed: 1 Acquired: 4
<buffer_queue.cpp:320-RequestBufferDebugInfoLocked>: all buffer are using, uniqueId: 257560598806528, Released: 0 Requested: 2 Flushed: 2 Acquired: 4

这个报错应该就是CPU性能不够了,可是我这个应用什么都没干,就只是打开相机,然后获取视频帧数据,一个复杂的运算都没有,这是什么原因呢?

我调低相机参数的宽高,就可以明显改善这个问题了,难道CPU连这点分辨率都支持不了?

有没有可能是获取视频帧数据时,必须要进行JPEG压缩和解压缩有关?

相机参数:宽:2560,高:1440,最大帧率:30,设备类型:nova 12 Pro,软件版本:6.0.0.130。

demo下载地址:https://gitee.com/chen_yi_ze/test-hongmengs-camera


更多关于HarmonyOS 鸿蒙Next中相机无法稳定获取视频帧的实战教程也可以访问 https://www.itying.com/category-93-b0.html

8 回复

尊敬的开发者,您好, 关于您反馈的问题,这个日志并非异常报错信息,只是记录BufferQueue轮转状态用的。 日志中Acquired:4表示消费端持有4个buffer未被释放,看了代码使用了双路预览,只要在使用过程中注意及时释放buffer即可,一般不会对业务造成影响。释放buffer可参考自定义相机预览中的步骤6

更多关于HarmonyOS 鸿蒙Next中相机无法稳定获取视频帧的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


大哥,性能不够了呀,大量丢帧了,视频卡成PPT了,我释放buffer了。找个懂视频的专家过来。

尊敬的开发者,您好, 关于您反馈的问题,

  1. 我在本地使用pura80pro+运行了一遍你提供的代码,Profiler工具显示当设备温度跑到43°C时,预览帧率也并未出现下降的现象
  2. <buffer_queue.cpp>报错实际上并不影响预览结果
  3. 检查代码之后发现有如下问题:
try {
  img = await this.imageReceiver?.readNextImage();
    if (img) {
      // 获取图像组件(YUV数据)
      const components = await img.getComponent( image.ComponentType.JPEG );
      let p_width = img.size.width;
      let p_height = img.size.height;
      img.release(); // 务必释放图像资源,防止内存泄漏

      this.CreatePixelMap( components, p_width, p_height );
    }
} catch (err) {
  console.error(`处理帧数据失败: ${err.code} - ${err.message}`);
} finally {
}

代码中先调用了‘img.release();’后调用了‘this.CreatePixelMap( components, p_width, p_height );’,但在release()时components可能就已经被销毁了,建议将img.release()放到imageArrival回调的最后来处理,并保证并发方法的调用时序。 4. demo中能看到的处理逻辑有限,麻烦您排查下其他地方的逻辑问题。 如果确实有双路预览需求,实现时请参考官方文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/camera-dual-channel-preview

预览画面没有卡顿,但是我获取到的视频流是卡顿的,例如,预览是一秒30帧,但是我获取到的视频流就只有一秒10帧左右了。

经过与数位华为官方工程师沟通了两天,终于是彻底解决了,总结如下:

1、之所以会卡顿,是因为我的demo代码和官方的demo代码,在每次获取到视频帧时都使用了createPixelMap,这个函数非常耗时,所以导致相机队列阻塞,从而导致丢帧,去掉这个函数就不丢帧了。

2、我其实是为了获取到相机源始的yuv数据,在调用img.getComponent后,获取到的Component.byteBuffer就是源始的yuv数据,不需要再createPixelMap了,且img.getComponent的第一个参数image.ComponentType.JPEG是没有意义的。

3、在拿到源始的yuv数据后,如果要做其他处理,华为官方工程师还是建议用C语言来做,这样性能会好很多。

这个问题为何无人解答?

在鸿蒙Next中,相机视频帧获取不稳定常因未正确配置VideoOutput的帧率参数或使用同步操作阻塞了帧回调。使用ImageReceiveron('imageArrival')异步回调,并确保Surface尺寸与相机输出匹配,可减少丢帧。同时检查是否启用了多摄像头或高分辨率模式导致帧率下降。

您遇到的这个问题并非 CPU 性能不足,而是视频帧未及时释放导致缓冲区阻塞

报错 all buffer are using 表示缓冲池中的所有图像缓冲区都处于 Acquired 状态,系统已无法分配新的缓冲区给相机数据流。从日志看 Released:0,说明没有一帧被主动释放。常见原因是您在图像回调中拿到 image(或 PixelMap)后,使用完没有调用 image.release() 把缓冲区归还给相机服务,导致缓冲区迅速耗尽。

即使没有复杂运算,只要持续回调却不释放,几帧之后就会报错阻塞。降低分辨率只是减小单帧数据量,让缓冲池消耗变慢,看似“改善”但并未解决根本问题。

这与 JPEG 编解码无关,标准预览流输出的是 YUV 原始格式,不会自动进行 JPEG 压缩。请检查您 ImageReceiverSurfaceonImageArrival 回调中,获取帧数据后是否添加了 image.release() 调用。补上释放逻辑,即可稳定获取 2560×1440@30fps 的视频帧。

回到顶部