修复FFMPEG在运存小的平台打开UVC摄像头内存不够导致程序崩溃问题(RV1106G2 125mb内存版本FFMPEG打开USB摄像头崩溃解决记录)

问题出现背景

在近期的开发中,提出了需要使用RV1106G2板卡接入USB摄像头采集图像并转推RTSP视频流的需求,针对摄像头打开的实现,我第一时间想到的就是利用FFMPEG来打开摄像头,DEMO程序很快就写好了,在PC端电脑运行的非常好,但是一移植到RV1106平台上,就发现一但程序执行到打开摄像头的环节时,会报Out of memory导致程序的崩溃甚至连带内核一起报错死机。

运行平台及软件版本

平台:Rockchip RV1106G2 SoloLinker-A V2
FFMPEG: ffmpeg4.3 ZLmediakit修改支持HEVC RTMP的版本GITHUB地址

解决过程

针对该问题,首先我使用了v4l2-ctl --list-formats-ext命令来查看USB摄像头支持的分辨率格式,然后换用了更小的分辨率来打开USB摄像头,发现了如果采用小的分辨率来打开(如640x480,800x600),程序并没有任何问题,一切正常,但是如果打开的分辨率提高到1000x***这一档往上,程序立刻当场崩溃死机。
面对这情况,我了解到了FFMPEG底层实际上是调用V4L2来打开UVC设备的,于是我采用了更加底层的V4L2来实现采集摄像头程序,然后发现了如果采用V4L2来打开摄像头,打开4K分辨率的画面采集都没有问题,但是使用V4L2来编程需要自己对图像的缓存进行分配,由此我也了解了V4L2对内存的申请,故转过头来我怀疑是FFMPEG源码里对V4L2内存申请部分出了问题。

解决问题

通过对FFMPEG V4L2源码的解读,最终定位到了问题的出现点。
在FFMPEG的v4l2.c
FFMPEG使用v4l2_ioctl(s->fd, VIDIOC_REQBUFS, &req)申请内核帧缓存区时,申请的默认大小是
static const int desired_video_buffers = 256;
一次性在内核申请了256帧的缓存,而在RV1106G2这样的小运存平台上,如果采用的分辨率是720P,那么它会一次性在内核申请了256张MJPEG 720P的缓存区,这大小超过了RV1106G2的运存,就会导致程序连带着内核一起崩溃!
解决的方法也很简单,在FFMPEG的v4l2.c中,把第42行的

static const int desired_video_buffers = 256;

改小点就行了,我这边改成了

static const int desired_video_buffers = 6;

修改之后,重新编译FFMPEG就可以正常打开高分辨率的UVC摄像头采集图像了。

FFMPEG打开UVC摄像头

    AVDictionary *options = NULL;
    av_dict_set(&options,"video_size","1280x720",0);  //800x600 //640x480
    av_dict_set(&options, "input_format", "mjpeg", 0);
    av_dict_set(&options,"framerate","30",0);
    if (avformat_open_input (&fmtCtx, configSetting->srcFileUri, inputFmt, &options) < 0){
        printf("can not open_input_file\n");         
        return;    
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值