超出最小未排队缓冲区计数

Posted

技术标签:

【中文标题】超出最小未排队缓冲区计数【英文标题】:Min undequeued buffer count exceeded 【发布时间】:2014-08-13 05:02:05 【问题描述】:

我正在使用 SurfaceTexture 通过以下方式获取预览帧。

首先,我设置一个预览纹理:

camera.setPreviewTexture(new SurfaceTexture(0));

然后,在开始预览之前以及每次调用onPreviewFrame 时,我都会像这样设置回调缓冲区:

camera.addCallbackBuffer(buffer);
camera.setPreviewCallbackWithBuffer(this);

它有效。有时,我使用camera.takePicture(null, null, callback) 拍照,结果调用onPictureTaken 成功。图像被保存。由于我想在拍照后重新开始预览,所以我做了以下操作:

try

    camera.setPreviewTexture(new SurfaceTexture(0));
    camera.startPreview();

...

预览重新启动,一切似乎都很好。但是我的Logcat报如下错误,貌似重启预览后:

E/BufferQueue﹕ [unnamed-5682-5] dequeueBuffer: min undequeued buffer count (2) exceeded (dequeued=5 undequeudCount=1)

我错过了什么吗?我应该在某个时候释放旧纹理吗?

配置: Samsung Galaxy S4、Samsung Galaxy S5、Nexus 5,在 android KitKat 上运行。

编辑:我不确定它是否已链接,但一段时间后,我的应用不再拍照,并且我的 Logcat 中不断出现以下消息:

E/LocSvc_api_v02(  318): I/---> locClientSendReq line 2332         QMI_LOC_INJECT_SENSOR_DATA_REQ_V02
E/gsiff_dmn(  318): I/loc_api_resp_ind_callback: Received LocAPI Resp ind = 77
E/LocSvc_api_v02(  318): D/loc_sync_process_ind:172]: loc_sync_array not in use 
E/LocSvc_utils_q(  318): D/msg_q_rcv: Received message 0xB899D940 rv = 0
E/gsiff_dmn(  318): I/gsiff_data_task: Handling message type = 4
E/gsiff_dmn(  318): I/gsiff_daemon_inject_sensor_data_handler: Sending Sensor Data to     LocApi. opaque_id = 1226

E/LocSvc_api_v02(  318): I/---> locClientSendReq line 2332 QMI_LOC_INJECT_SENSOR_DATA_REQ_V02
E/gsiff_dmn(  318): I/loc_api_resp_ind_callback: Received LocAPI Resp ind = 77
E/LocSvc_api_v02(  318): D/loc_sync_process_ind:172]: loc_sync_array not in use 
E/mm-camera(  284): [cpp_hardware_process_frame:997] Too many cpp frames dropped!!
E/mm-camera(  284): cpp_thread_handle_process_buf_event:224] get buffer fail. drop frame id:1845 identity:0x20002

W/QCamera2HWI(  269): [CHECK_BUF_LOCK] Too many preview buffer is locked by     surfaceflinger : 29
E/mm-camera(  284): [cpp_hardware_process_frame:997] Too many cpp frames dropped!!
E/mm-camera(  284): cpp_thread_handle_process_buf_event:224] get buffer fail. drop frame     id:1846 identity:0x20002

编辑 2: 如果我始终使用相同的 SurfaceTexture(我保留为成员)而不是 new SurfaceTexture(0),那么一些错误会消失,并且应用程序继续工作。 min undequeued buffer count exceeded 错误和 Too many preview buffer is locked by surfaceflinger 警告仍然存在。

【问题讨论】:

【参考方案1】:

似乎相机在其缓冲区中保存了一些未被您的活动出队的东西。当您开始新的预览时,您必须找到清除相机缓冲区的方法。

您可以在 Android 文档中找到有关 Camera 类的信息:

如果使用 null 回调调用此方法 [setPreviewCallbackWithBuffer]、调用 setPreviewCallback(Camera.PreviewCallback) 或调用 setOneShotPreviewCallback(Camera.PreviewCallback),则缓冲区队列将被清除。

因此,在您拍照时删除回调并在重新启动预览时恢复它可能就足够了。

【讨论】:

这很有趣。不幸的是,如果我在调用takePicture() 之前添加setPreviewCallbackWithBuffer(null) 并且我在startPreview() 之前添加它,我仍然有相同的行为... 其实我什至尝试过同时添加你提出的三个方案,并没有任何改变。 您是否尝试过使用始终使用相同的 SurfaceTexture 而不是每次都创建一个新的 SurfaceTexture 来应用此解决方案? 是的,因为其他解决方案实际上产生了更多错误。

以上是关于超出最小未排队缓冲区计数的主要内容,如果未能解决你的问题,请参考以下文章

用于多线程的 NAudio:缓冲区已在播放错误时排队

丢弃用于 TCP 连接的 winsock 内部缓冲区中的排队数据

图形 - 多重缓冲:排队或最后完成?

重新启动 Clip 对象 - flush() 方法

实践中的并发循环缓冲区错误?

用Matlab模拟一个缓冲区大小为10的随机排队系统