Android AI 巡逻车SurfaceView 视频拉流问题以及解决方案总结

219 阅读2分钟

AI 城市巡查主画面

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))

ANR Log Message, Click Here !

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

解决问题

    1. 使用try catch finally{unlockCanvasAndPost} 结构处理 异常
    1. 绘制的时候线程不要一直的跑,休眠个20-100 MS 节约资源
    1. 添加标志位isDrawing在销毁的时候提前置位,在lockCanvas的时候判断是否要进行绘制
    1. 在切换按钮调用setISDrawing=false;并休眠20MS 保证lockCanvas()和unlockCanvasAndPost 成对执行完

为什么前期会使用推帧而不是RTSP 编码实现

早期的AI盒子性能不够,定时间隔提取了摄像头数据分析后通过Wi-Fi 推送到和App,盒子中没有RTSP 服务端功能,后期采用高性能盒子后画面处理同时能推送RTSP 流