video2lcd_opencv2在JZ2440上实现椭圆检测

一.   linux下V4L2一般操作流程(视频设备):


1. 打开设备文件。 int fd=open(”/dev/video0″,O_RDWR);
2. 取得设备的capability,看看设备具有什么功能,比如是否具有视频输入,或者音频输入输出等。


VIDIOC_QUERYCAP,struct v4l2_capability
3. 选择视频输入,一个视频设备可以有多个视频输入。VIDIOC_S_INPUT,struct v4l2_input
4. 设置视频的制式和帧格式,制式包括PAL,NTSC,帧的格式个包括宽度和高度等。
VIDIOC_S_STD,VIDIOC_S_FMT,struct v4l2_std_id,struct v4l2_format
5. 向驱动申请帧缓冲,一般不超过5个。struct v4l2_requestbuffers
6. 将申请到的帧缓冲映射到用户空间,这样就可以直接操作采集到的帧了,而不必去复制。mmap
7. 将申请到的帧缓冲全部入队列,以便存放采集到的数据.VIDIOC_QBUF,struct v4l2_buffer
8. 开始视频的采集。VIDIOC_STREAMON
9. 出队列以取得已采集数据的帧缓冲,取得原始采集数据。VIDIOC_DQBUF
10. 将缓冲重新入队列尾,这样可以循环采集。VIDIOC_QBUF
11. 停止视频的采集。VIDIOC_STREAMOFF
12. 关闭视频设备。close(fd);


#define VIDEO_FORMAT V4L2_PIX_FMT_YUYV
#define BUFFER_COUNT 4

typedef struct VideoBuffer {
    void   *start; //视频缓冲区的起始地址
    size_t  length;//缓冲区的长度
} VideoBuffer;

什么是位图文件
VideoBuffer framebuf[BUFFER_COUNT];  


v4l2编程步骤:


1,// 获取驱动信息
       ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);


控制命令VIDIOC_QUERYCAP
功能:查询设备驱动的功能;
参数说明:参数类型为V4L2的能力描述类型struct v4l2_capability;
struct v4l2_capability {
        __u8    driver[16];     //i.e. "bttv"            //驱动名称,
        __u8    card[32];       // i.e. "Hauppauge WinTV"         //
        __u8    bus_info[32];   // "PCI:" + pci_name(pci_dev)     //PCI总线信息
        __u32   version;        // should use KERNEL_VERSION() 
        __u32   capabilities;   // Device capabilities         //设备能力
        __u32   reserved[4];
};
cap 定义为v4l2_capability结构体
通过  ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);便可得到驱动信息
可使用printf(" driver: %s\n", cap.driver);打印出相关信息;


2,//获取当前视频设备支持的视频格式


truct v4l2_fmtdesc {
        __u32               index;             // Format number      
        enum v4l2_buf_type  type;              // buffer type        
        __u32               flags;
        __u8                description[32];   // Description string 
        __u32               pixelformat;       // Format fourcc      
        __u32               reserved[4];
};


struct v4l2_fmtdesc fmtdesc;
ret=ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc);
//如果fmtdesc的index适合该设备,则ret=0;


3,//设置视频设备的视频数据格式
控制命令 :VIDIOC_S_FMT
struct v4l2_format fmt;


参数说明:参数类型为V4L2的视频数据格式类型struct v4l2_format;
struct v4l2_format {
        enum v4l2_buf_type type;    //数据流类型,必须永远是V4L2_BUF_TYPE_VIDEO_CAPTURE
        union {
                struct v4l2_pix_format          pix;     // V4L2_BUF_TYPE_VIDEO_CAPTURE 
                struct v4l2_window              win;     // V4L2_BUF_TYPE_VIDEO_OVERLAY 
                struct v4l2_vbi_format          vbi;     // V4L2_BUF_TYPE_VBI_CAPTURE 
                struct v4l2_sliced_vbi_format   sliced;  // V4L2_BUF_TYPE_SLICED_VBI_CAPTURE 
                __u8    raw_data[200];                   // user-defined 
        } fmt;
};
struct v4l2_pix_format {
        __u32                   width;         // 宽,必须是16的倍数
        __u32                   height;        // 高,必须是16的倍数
        __u32                   pixelformat;   // 视频数据存储类型,例如是YUV4:2:2还是RGB
        enum v4l2_field       field;
        __u32                   bytesperline;
        __u32                   sizeimage;
        enum v4l2_colorspace colorspace;
        __u32                   priv;
};
返回值说明: 执行成功时,函数返回值为 0;

 fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;   //V4L2_FIELD_ANY


4,请求V4L2驱动分配视频缓冲区(申请V4L2视频驱动分配内存)
重要的结构体
struct v4l2_buffer {
        __u32                   index;
        enum v4l2_buf_type      type;
        __u32                   bytesused;
        __u32                   flags;
        enum v4l2_field         field;
        struct timeval          timestamp;
        struct v4l2_timecode    timecode;
        __u32                   sequence;
        // memory location
        enum v4l2_memory        memory;
        union {
                __u32           offset;
                unsigned long   userptr;
        } m;
        __u32                   length;
        __u32                   input;
        __u32                   reserved;
};


该步骤比较复杂:
ret = ioctl(fd , VIDIOC_QUERYBUF, &buf); //获得内存缓冲区的信息
//然后mmap buffer
                   例如:
 framebuf[i].length = buf.length;//framebuf是程序最前面定义的一个结构体类型的数据
  framebuf[i].start =  mmap(0, buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 


buf.m.offset);
         if (framebuf[i].start == MAP_FAILED) {
             printf("mmap (%d) failed: %s\n", i, strerror(errno));
             return;
        }
 
再然后:
memset(&buf, 0, sizeof(struct buf));
        buf.index = i;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_MMAP;
        ret = ioctl(fd , VIDIOC_QBUF, &buf);
        if (ret < 0) {
            printf("VIDIOC_QBUF (%d) failed (%d)\n", i, ret);
            return;
        }
映射到framebuf的4个地址;

最后在改完video2lcd_opencv2(椭圆检测)成功,在修改过程中本来使用fread()函数将buf里边的像素数据读出了


,但是读出来的.jpg文件用UE总打开总是全零,最后采用fwrite()函数将buf里边的数据写给一个.jpg文件,才成功得


到一个完整的.jpg文件,具体原因在我调试fwrite是猜想可能是我使用fread里边读的mode不对,没有使用rb试试,

也有可能是内核空间mmap到用户空间,不能fread(有点扯)



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值