前言
厂商提供了一个摄像头,接入后dev/video节点已生成,打开也成功了,但是黑屏,无法预览。最终查了HAL层代码才确认是厂商的摄像头属性(支持格式)导致的。
以下代码只限于Rockchip平台的,其他的平台不一样的可以绕道。
分析
1.根据打开摄像头的日志,可以发现是mjpeg解码失败导致的
CameraHal: reprocessFrame(1066): mjpeg data error!!
2.确认是格式问题后,在打开摄像头的LOG中我又发现了以下日志,从日志中可以看出驱动获取到摄像头支持的格式有(YUVYV MJPEG H264)
CameraHal: cameraCreate(354): cameraCreate(354): dlsym dec_oneframe_RkJpegDecoder sucess!
2021-01-06 10:34:47.283 238-2387/? D/CameraHal: cameraCreate(376): Camera driver: uvcvideo Card Name:UVC Camera (1d6b:0102) Driver version: 4.4.83 CameraHal version: 1.80.2
CameraHal: cameraCreate(383): mCamDriverSupportFmt: fmt = 1448695129(YUYV 4:2:2),index = 0
CameraHal: cameraCreate(383): mCamDriverSupportFmt: fmt = 1196444237(Motion-JPEG),index = 1
CameraHal: cameraCreate(383): mCamDriverSupportFmt: fmt = 875967048(H.264),index = 2
CameraHal: cameraCreate(421): cameraCreate(421): mCamDriverPreviewFmt(MJPG) is cameraHal and camera driver is also supported!!
CameraHal: cameraCreate(423): mCamDriverPreviewFmt = 1196444237
CameraHal: cameraCreate(429): cameraCreate(429): Current driver is uvcvideo, v4l2 memory is V4L2_MEMORY_MMAP
3.想查Hal层源码中是如何选择格式的,由于没有源码,无从下手,后来想到github,果然被我找到了RK3399 7.1.2的cameraHal的源码,这里是传送门
4.有源码了就好办多了,很快找到了报错的位置:CameraUsbAdapter.cpp,显然MJPEG的解码器解码失败了,摄像头过来的根本不是MJPEG标准格式
if( frame->frame_fmt == V4L2_PIX_FMT_MJPEG){
char *srcbuf = (char*)frame->vir_addr;
if((srcbuf[0] == 0xff) && (srcbuf[1] == 0xd8) && (srcbuf[2] == 0xff)){
//decoder to NV12
............
}else{
LOGE("mjpeg data error!!");
return -1;
}
5.以下为格式选择的关键代码:CameraAdapter.cpp,拿驱动拿到的摄像头信息与Hal层支持的格式进行比对,发现相同的就用,但有一个规则,如果两边都支持MJPEG,那么MJPEG格式优先。
i = 0;
while (CameraHal_SupportFmt[i]) {
LOG1("CameraHal_SupportFmt:fmt = %d,index = %d",CameraHal_SupportFmt[i],i);
j = 0;
while (mCamDriverSupportFmt[j]) {
if (mCamDriverSupportFmt[j] == CameraHal_SupportFmt[i]) {
if ((mCamDriverSupportFmt[j] == V4L2_PIX_FMT_MJPEG) && (mMjpegDecoder.state == -1))
continue;
break;
}
j++;
}
if (mCamDriverSupportFmt[j] == CameraHal_SupportFmt[i]) {
break;
}
i++;
}
处理方式
我是被摄像头厂商给坑了,原来摄像头虽然属性是支持MJPEG格式,但其实不支持。
1.如果是可以改源码的,将CameraUsbAdapter.h中的CONFIG_CAMERA_UVC_MJPEG_SUPPORT改为0就不会再支持MJPEG了,
2.如果不可以动源码,这种问题直接让厂商处理。
结论
有些厂商真的是坑死个人,既然摄像头不支持,属性上还挂着支持,真的恶心呐,恶心,我都关着门。