2020-12-07

V4L2编程以及LCD显示

头文件;

#include<stdio.h>

#include<sys/types.h>

#include<sys/stat.h>

#include<fcntl.h>

#include<stdlib.h>

#include<unistd.h>

#include<sys/ioctl.h>

#include<linux/videodev2.h>

#include<sys/mman.h>

//#include<jpeglib.h>

#include<string.h>

#include<linux/fb.h>

 

查看摄像头支持照片的格式

//2获取摄像头支持的格式ioctl(文件描述符,命令,与命令对应的结构体)

     //struct v412_fmtdesc v4fmt;

  /*   struct v4l2_fmtdesc   v4fmt;         

     v4fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

     int i=0;

   while(1){

       v4fmt.index = i++;

     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]);

       printf("reserved=%d\n",v4fmt.reserved[0]);

   }*/

 

 

YUYV格式转化

void yuyv_to_rgb(unsigned char *yuyvdata,unsigned char *rgbdata,int w,int h)

{

 

  int r1,g1,b1;

  int r2,g2,b2;

  for(int i=0;i<w*h/2;i++)

   {

char data[4];

memcpy(data,yuyvdata+i*4,4);

unsigned char Y0=data[0];

unsigned char U0=data[1];

unsigned char Y1=data[2];

unsigned char V1=data[3];

 

       r1 = Y0+1.4075*(V1-128);if(r1>255)r1=255;if(r1<0)r1=0;

       g1 = Y0-0.3455*(U0-128)-0.7169*(V1-128);if(g1>255)g1=255;if(g1<0)g1=0;

       b1 = Y0+1.779*(U0-128);if(b1>255)b1=255;if(b1<0)b1=0;

 

       r2 = Y1+1.4075*(V1-128);if(r2>255)r2=255;if(r2<0)r2=0;

       g2 = Y1-0.3455*(U0-128)-0.7169*(V1-128);if(g2>255)g2=255;if(g2<0)g2=0;

       b2 = Y1+1.779*(U0-128);if(b2>255)b2=255;if(b2<0)b2=0;

 

       rgbdata[i*6+0]=r1;

       rgbdata[i*6+1]=g1;

       rgbdata[i*6+2]=b1;

       rgbdata[i*6+3]=r2;

       rgbdata[i*6+4]=g2;

       rgbdata[i*6+5]=b2;

 

}

调取本地LCD进行显示

int lcdfd =0;

unsigned int *lcdptr =NULL;

int lcd_w=800,lcd_h=480;

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

{

    unsigned int *ptr =lcdptr;

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

{

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

   {

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

 

    }

ptr+=lcd_w;

rgbdata+=w*3;

        }

 

}

 

V4l2编程具体流程

//1打开设备

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

     if(fd<0)

        {

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

           return -1;

        }

 

//2获取摄像头支持的格式ioctl(文件描述符,命令,与命令对应的结构体)

     //struct v412_fmtdesc v4fmt;

  /*   struct v4l2_fmtdesc   v4fmt;         

     v4fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

     int i=0;

   while(1){

       v4fmt.index = i++;

     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]);

       printf("reserved=%d\n",v4fmt.reserved[0]);

   }*/

//3设置采集格式

    struct v4l2_format   vfmt;  

    vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;//摄像头采集

    vfmt.fmt.pix.width = 640;//设置宽

    vfmt.fmt.pix.height = 480;//设置高

   vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;//设置视频采集格式

  //   vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;

    int ret = ioctl(fd,VIDIOC_S_FMT,&vfmt);

    if(ret<0)

     {

perror("设置格式失败");

     }

 

 

//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映射

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

   unsigned int size[4];

   struct v4l2_buffer mapbuffer;

   //初始化type ,index

   mapbuffer.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;//摄像头采集

 

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

   {

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("开启失败");

     }

    //定义一个空间存储解码后的RGB数据

   unsigned char rgbdata[640*480*3];

while(1)

{

       // 从队列中提取一帧数

     struct  v4l2_buffer readbuffer;

     readbuffer.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;

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

      if(ret<0)

     {

perror("提取失败");

     }      

//     FILE *file = fopen("my.jpeg","w");

   //  mptr[readbuffer,index]

//     fwrite(mptr[readbuffer.index],readbuffer.length,1,file);

//     close(file);

  

     //显示到lcd上

     

{

         yuyv_to_rgb(mptr[readbuffer.index],rgbdata,640,480);//吧JPEG数据解码为rgb数据

 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(int i=0;i<4;i++)

      {

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

      }

 

  //9关闭设备

     close(fd);

     return 0;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值