UsbCamera V4L2自动适配分辨率720和480p
2017-07-18 17:48
447 查看
最近在写UsbCamera(android)发现一个博客十分有用,因为是百度排在前面的(http://blog.csdn.net/u010164190/article/details/53205079)。
但是实测下来是有些问题的(为了技术)。
根据他的代码我写的如下:
会发现log如下:
会发现allan2是不会打印的。因为我们给v4l2_frmsizeenum frmsize赋值了type为V4L2_BUF_TYPE_VIDEO_CAPTURE,于是allan2的V4L2_FRMSIZE_TYPE_STEPWISE可以去掉。同时循环很多数值也不正确,是因为ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc)的循环体frmsize.index++。这个时候,同时也已经意识到支持的分辨率这里列出这么多是不对的,而只有第一个是对的。我们直接break就好了。
但是原理上,这里有表述
http://blog.sina.com.cn/s/blog_602f87700101bf36.html 枚举设备所支持的image
format: VIDIOC_ENUM_FMT
使用ioctl VIDIOC_ENUM_FMT 依次询问,
type为:V4L2_BUF_TYPE_VIDEO_CAPTURE。
index从0开始,依次增加,直到返回. Driver会填充结构体struct
v4l2_fmtdesc的其它内容,如果index超出范围,则返回-1。
这样,则知道当前硬件支持什么样的image format.
所以,我们不需要对v4l2_frmsizeenum进行index++。只需要对fmtdesc.index++即可。
这样修改以后,是否就OK了呢?
还是不行,又发现,
循环还是有2次,为什么,最后我们聚焦到frmdesc.flags这个参数上,很容易加log知道了,其中有一次是fmtdesc.flags=V4L2_FMT_FLAG_COMPRESSED打印出来的。
所以,我们需要对V4L2_FMT_FLAG_COMPRESSED的flag进行一次过滤。
因此,我们的最终代码改成,
总结:网上找答案要不断找到真相,结合自己的测试。同时还要站在巨人的肩膀上有一点小进步。比如这里,第一个帖子,指出了方法;第二个帖子讲了一些原理;我这边又进一步整合和发现循环体的问题和flags参数的问题。
好了今天到这里。
但是实测下来是有些问题的(为了技术)。
根据他的代码我写的如下:
char v4l2_ioctl_supported_framesize(int fd) { //调试中,错误的代码 int idx = 0; char retChar = 'e'; //error if (-1 != fd) { enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; struct v4l2_fmtdesc fmtdesc; struct v4l2_frmivalenum frmival; struct v4l2_frmsizeenum frmsize; fmtdesc.index = 0; fmtdesc.type = type; LOGE("allan-1= pixelformat %x",fmtdesc.pixelformat); while (ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) == 0) { LOGE("allan0= pixelformat %x",fmtdesc.pixelformat); frmsize.pixel_format = fmtdesc.pixelformat; frmsize.index = 0; while (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) == 0) { if(frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) { LOGE("allan1= %dx%d\n", frmsize.discrete.width, frmsize.discrete.height); retChar = 'n'; }else if(frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE){ printf("allan2:%dx%d\n",frmsize.discrete.width, frmsize.discrete.height); } frmsize.index++; LOGE("doubt it..."); } fmtdesc.index++; } } return retChar; }
会发现log如下:
WebCam : allan-1= pixelformat e33706c4 WebCam : allan0= pixelformat 56595559 WebCam : allan1= 1280x720 WebCam : doubt it... WebCam : allan1= 1280x480 WebCam : doubt it... WebCam : allan1= 640x480 WebCam : doubt it... WebCam : allan1= 352x288 WebCam : doubt it... WebCam : allan1= 320x240 WebCam : doubt it... WebCam : allan1= 176x144 WebCam : doubt it... WebCam : allan1= 160x120 WebCam : doubt it... WebCam : allan0= pixelformat 47504a4d WebCam : allan1= 1280x720 WebCam : doubt it... WebCam : allan1= 1280x480 WebCam : doubt it... WebCam : allan1= 640x480 WebCam : doubt it... WebCam : allan1= 352x288 WebCam : doubt it... WebCam : allan1= 320x240 WebCam : doubt it... WebCam : allan1= 176x144 WebCam : doubt it... WebCam : allan1= 160x120 WebCam : doubt it...
会发现allan2是不会打印的。因为我们给v4l2_frmsizeenum frmsize赋值了type为V4L2_BUF_TYPE_VIDEO_CAPTURE,于是allan2的V4L2_FRMSIZE_TYPE_STEPWISE可以去掉。同时循环很多数值也不正确,是因为ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc)的循环体frmsize.index++。这个时候,同时也已经意识到支持的分辨率这里列出这么多是不对的,而只有第一个是对的。我们直接break就好了。
但是原理上,这里有表述
http://blog.sina.com.cn/s/blog_602f87700101bf36.html 枚举设备所支持的image
format: VIDIOC_ENUM_FMT
struct v4l2_fmtdesc fmtdesc; fmtdesc.index = 0; fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ret = ioctl(Handle, VIDIOC_ENUM_FMT, &fmtdesc);
使用ioctl VIDIOC_ENUM_FMT 依次询问,
type为:V4L2_BUF_TYPE_VIDEO_CAPTURE。
index从0开始,依次增加,直到返回. Driver会填充结构体struct
v4l2_fmtdesc的其它内容,如果index超出范围,则返回-1。
struct v4l2_fmtdesc { __u32 index; // 需要填充,从0开始,依次上升。 enum v4l2_buf_type type; //Camera,则填写V4L2_BUF_TYPE_VIDEO_CAPTURE __u32 flags; // 如果压缩的,则Driver 填写:V4L2_FMT_FLAG_COMPRESSED,否则为0 __u8 description[32]; // image format的描述,如:YUV 4:2:2 (YUYV) __u32 pixelformat; //所支持的格式。 如:V4L2_PIX_FMT_UYVY __u32 reserved[4]; };
这样,则知道当前硬件支持什么样的image format.
所以,我们不需要对v4l2_frmsizeenum进行index++。只需要对fmtdesc.index++即可。
这样修改以后,是否就OK了呢?
还是不行,又发现,
WebCam : allan-1= pixelformat e36bc6c4 WebCam : allan0= pixelformat 56595559 WebCam : allan1= 1280x720 WebCam : allan0= pixelformat 47504a4d WebCam : allan1= 1280x720
循环还是有2次,为什么,最后我们聚焦到frmdesc.flags这个参数上,很容易加log知道了,其中有一次是fmtdesc.flags=V4L2_FMT_FLAG_COMPRESSED打印出来的。
所以,我们需要对V4L2_FMT_FLAG_COMPRESSED的flag进行一次过滤。
因此,我们的最终代码改成,
char v4l2_ioctl_supported_framesize(int fd) { int idx = 0; char retChar = 'e'; //error if (-1 != fd) { enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; struct v4l2_fmtdesc fmtdesc; struct v4l2_frmivalenum frmival; struct v4l2_frmsizeenum frmsize; fmtdesc.index = 0; fmtdesc.type = type; while (ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) == 0) { frmsize.pixel_format = fmtdesc.pixelformat; frmsize.index = 0; //fmtdesc.flags = 0, V4L2_FMT_FLAG_COMPRESSED = 1 if(ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) == 0 && frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE && fmtdesc.flags == 0) { //LOGE("allan= %dx%d\n", frmsize.discrete.width, frmsize.discrete.height); //TODO 自行修改返回结构体,或者传入指针地址来赋值 retChar = 'n'; } fmtdesc.index++; } } return retChar; }
总结:网上找答案要不断找到真相,结合自己的测试。同时还要站在巨人的肩膀上有一点小进步。比如这里,第一个帖子,指出了方法;第二个帖子讲了一些原理;我这边又进一步整合和发现循环体的问题和flags参数的问题。
好了今天到这里。
相关文章推荐
- Linux下基于V4L2 USB Camera操作
- 嵌入式Linux下Camera编程--V4L2 (V4L2内核驱动配置、USB转串配置)
- USB Camera V4L2 视频录制——ubuntu(1)
- Tiny210 USB Camera 自动断开
- 根据 JS 自动定义页面缩放比(根据分辨率进行适配)
- cocos2d-x3.0中图片分辨率自动适配设置以及源码,原理分析。
- cocos2d-x3.0中图片分辨率自动适配设置以及源码,原理分析。
- OpenWrt在接入usb camera时自动启动mjpg-streamer
- linux下usb camera图像采集(V4l2)
- Android 屏幕适配方案,自动生成不同分辨率的值
- webview在同种分辨率的情况下,屏幕密度不一样的情况下,自动适配页面:
- OpenWrt在接入usb camera时自动启动mjpg-streamer
- linux下usb camera图像采集(V4l2)
- cocos2d-x3.0中图片分辨率自动适配设置以及源码,原理分析。
- android 常见分辨率(mdpi、hdpi 、xhdpi、xxhdpi )及屏幕适配注意事项
- iOS iPhone6 及 iPhone6 plus 适配时,显示模式的影响(截图分辨率不同)
- ---WebCam网络摄像头8 usb--v4l2 , Format............:V4L2_PIX_FMT_MJPEG
- android 自适应 多屏幕支持 --Android多分辨率适配
- Android分辨率适配
- android-percent-support-extend根据百分比高效自动适配页面库。