
AI 巡逻车App 中画面如上,左上角的框是视频帧预览框,画面数据是通过Wi-Fi加载车载上的云台摄像头,大概是每秒抽取15帧进行AI 目标检测标记画红色框,通过Surface双缓冲进行绘制,视觉暂留人眼帧数识别每秒24帧后会形成动画的感觉(前期的边缘Ai 盒子和App 通信的方案是这样的,后面会修改为RTSP 拉流,但是画面会没有识别框和标注)
和右下角的地图可以位置互换切换,就是地图和视频预览的可视位置可以互换,两个都是Fragment 容器管理的。问题就在这个切换中产生了,低配的Android平板电脑画面会卡死并报告ANR,出现的Log 如下:
Input dispatching timed out
ANR Input dispatching timed out (a58c5df packeageName/packeageName.Activity (server) is not responding. Waited 5000ms for FocusEvent(hasFocus=false))
AI巡逻是一帧一帧数据分析然后使用jeromq推到平板上的,项目配置的平板电脑是联想一台价格600 左右(2023年定价)的设备,使用个人手机小米13 多次反复实现没有问题,问题代码大概如下
private void playVideoIamge() {
val data: ByteArray = jeroMQ.mSocket.recv(0);// 接收数据转为Bitmap
try {
//获得canvas对象
mCanvas = mSurfaceHolder.lockCanvas();
//绘制图
mCanvas.drawBitmap(....)
mSurfaceHolder.unlockCanvasAndPost(mCanvas);
}catch (Exception e){
}
}
出现这种问题的根本原因在于切换Fragment 的时候伴随着Surface的销毁重建过程lockCanvas() 和unlockCanvasAndPost必须保证成对的出现并且执行完,如果刚好lockCanvas 的时候切换销毁了就是导致ANR
解决问题
-
- 使用try catch finally{unlockCanvasAndPost} 结构处理 异常
-
- 绘制的时候线程不要一直的跑,休眠个20-100 MS 节约资源
-
- 添加标志位isDrawing在销毁的时候提前置位,在lockCanvas的时候判断是否要进行绘制
-
- 在切换按钮调用setISDrawing=false;并休眠20MS 保证lockCanvas()和unlockCanvasAndPost 成对执行完
为什么前期会使用推帧而不是RTSP 编码实现
早期的AI盒子性能不够,定时间隔提取了摄像头数据分析后通过Wi-Fi 推送到和App,盒子中没有RTSP 服务端功能,后期采用高性能盒子后画面处理同时能推送RTSP 流