IMX6ULL平台采集usb摄像头显示

#include <stdio.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <sys/ioctl.h>

#include <fcntl.h>

#include <stdlib.h>

#include <unistd.h>

#include <linux/videodev2.h>

#include <string.h>

#include <sys/mman.h>

#include <linux/fb.h>

#include <errno.h>


 

int lcdfd =0;

unsigned short *lcdptr = NULL;

int lcd_w,lcd_h,i,j;


 

static int convert_yuyv_to_rgb(unsigned char *inBuf, unsigned char *outBuf,int imgWidth,int imgHeight)

{

       int rows,cols;

       int y,u,v,r,g,b;

       unsigned char *YUVdata,*RGBdata;

       int Ypos,Upos,Vpos;//in the inBuf's postion

       YUVdata= inBuf;

       RGBdata = outBuf;

       Ypos=0;

       Upos=Ypos+1;

       Vpos=Upos+2;

       for(rows=0;rows<imgHeight;rows++)

       {

              for(cols=0;cols<imgWidth;cols++)

              {

                     y=YUVdata[Ypos];

                     u=YUVdata[Upos]-128;

                     v=YUVdata[Vpos]-128;

                     //r= y+1.4075*v;

                     //g= y-0.3455*u-0.7169*v;

                     //b= y+1.779*u;

                     r=y+ v+ (v*103>>8);

                     g=y- (u*88>>8) - (v*183>>8);

                     b=y+ u + (u*198>>8);

                                         

                     r=r>255?255:(r<0?0:r);

                     g=g>255?255:(g<0?0:g);

                     b=b>255?255:(b<0?0:b);    

                     

                     *(RGBdata++)=( ((g & 0x1C) << 3) | ( r >> 3) );

                     *(RGBdata++)=( (b & 0xF8) | ( g >> 5) );

                     

                     Ypos+=2;

                     if(!(cols& 0x01))//if cols%2!=0

                     {

                            Upos=Ypos+1;

                            Vpos=Upos+2;

                     }

              }

       }

       return 0;

}

void lcd_show_rgb(unsigned char *rgbdata,int w,int h)

{

   unsigned short *ptr = lcdptr;

    for(i = 0;i < h; i++)

     {

        for(j = 0; j < w; j++)

        {

            memcpy(ptr+j,rgbdata+j*2,2);

        }

            ptr += lcd_w;

            rgbdata += w*2;

    }  

}

int main(void)

{

    lcdfd = open("/dev/fb0",O_RDWR);

    //获取lcd信息

    struct fb_var_screeninfo info;                      //inux/fb.h中定义

    int lret = ioctl(lcdfd,FBIOGET_VSCREENINFO,&info);  //获取lcd屏幕信息,linux/fb.h中定义

    //虚拟机ubuntu

    lcd_w = info.xres_virtual;

    lcd_h = info.yres_virtual;

    /*开发板实际屏幕

    lcd_w = info.xres;

    lcd_h = info.yres;   */

    lcdptr = (unsigned short *)mmap(NULL,lcd_w*lcd_h*2,PROT_READ|PROT_WRITE,MAP_SHARED,lcdfd,0);

    //1、打开设备/

    int fd = open("/dev/video1",O_RDWR);

    if(fd < 0)

    {

        perror("打开设备失败");

        return -1;

    }

      // 2、获取支持格式 struct v4l2_format

        int ret = ioctl(fd,VIDIOC_ENUM_FMT,&v4fmt);

        if(ret < 0){

            perror("获取失败");

            break;

        }

        printf("index=%d\n",v4fmt.index);

        printf("flags=%d\n",v4fmt.flags);

        printf("description=%s\n",v4fmt.description);

        unsigned char *p = (unsigned char *)&v4fmt.pixelformat;

        printf("pixelformat=%c%c%c%c\n",p[0],p[1],p[2],p[3]);

    }

    */

    //3、设置采集格式

    struct v4l2_format v4fmt;

    struct v4l2_streamparm streamparm = {0};

    v4fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;  //不初始化这个会出错

    v4fmt.fmt.pix.width = 640;     //宽

    v4fmt.fmt.pix.height = 480;    //高

    v4fmt.fmt.pix.pixelformat =V4L2_PIX_FMT_YUYV; //图片格式

    int ret =ioctl(fd,VIDIOC_S_FMT,&v4fmt);   //设置图片格式命令

    if(ret <0)

    {

        perror("设置失败");

    }

        /* 获取streamparm */

    streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

    ioctl(fd, VIDIOC_G_PARM, &streamparm);

    /** 判断是否支持帧率设置 **/

    if (V4L2_CAP_TIMEPERFRAME & streamparm.parm.capture.capability) {

        streamparm.parm.capture.timeperframe.numerator = 1;

        streamparm.parm.capture.timeperframe.denominator = 30;//30fps

        if (0 > ioctl(fd, VIDIOC_S_PARM, &streamparm)) {

            fprintf(stderr, "ioctl error: VIDIOC_S_PARM: %s\n", strerror(errno));

            return -1;

        }

    }

 

      //4、申请内核空间

      struct v4l2_requestbuffers reqbuffer;

      reqbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

      reqbuffer.count = 4;  //申请4个缓冲区

      reqbuffer.memory = V4L2_MEMORY_MMAP;  //内存映射方式

      ret = ioctl(fd,VIDIOC_REQBUFS,&reqbuffer);

      if(ret < 0)

      {

          perror("申请缓冲区失败");

      }

    //5、映射内核空间到用户空间去  查询内核空间VIDIOC_QUERYBUF  放回VIDIOC_QBUF  

      unsigned char *mptr[4];  //保存后用户空间的首地址

      unsigned int size[4];

      struct v4l2_buffer mapbuffer;

      mapbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;

      for(i=0;i<4;i++)    //循环查询4个内核空间

      {

          mapbuffer.index = i;

          ret = ioctl(fd,VIDIOC_QUERYBUF,&mapbuffer);//从内核空间查询一个做映射

          if(ret <0)

          {

              perror("查询空间队列失败");

          }

         mptr[i] = (unsigned char *)mmap(NULL,mapbuffer.length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,mapbuffer.m.offset);

         size[i] = mapbuffer.length;

         //通知使用完毕,放回去

          ret = ioctl(fd,VIDIOC_QBUF,&mapbuffer);

          if(ret < 0)

          {

             perror("放回失败");

          }

      }

    //6、开始采集数据

    int type =V4L2_BUF_TYPE_VIDEO_CAPTURE;

    ret = ioctl(fd,VIDIOC_STREAMON,&type);

    if(ret < 0)

    {

        perror("开始失败");

    }

        unsigned char rgbdata[640*480*2];  //一帧数据的空

         printf("lcd_w%d\n",lcd_w);

        while(1)

        {

            //从队列中提取一帧数据

            struct v4l2_buffer readbuffer;

            readbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;

            ret = ioctl(fd,VIDIOC_DQBUF,&readbuffer);

            if(ret < 0)

            {

                perror("提取失败");

            }

            //yuyv转rgb在LCD上显示

            convert_yuyv_to_rgb(mptr[readbuffer.index],rgbdata,640,480);

            lcd_show_rgb(rgbdata,640,480);

         

           //通知内核使用完毕

            ret = ioctl(fd,VIDIOC_QBUF,&readbuffer);

            if(ret < 0)

            {

             perror("放回队列失败");

            }

        }

    //7、停止采集/

    ret = ioctl(fd,VIDIOC_STREAMOFF,&type);

    //8、释放映射/

    for(i=0;i<4;i++)

    {

     munmap(mptr[i],size[i]);

    }

   //9、关闭设备/

    close(fd);

    close(lcdfd);

 return 0;

}




 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值