Qt V4L2摄像头编程

V4L2(Video for Linux 2)是一个用于Linux操作系统的视频捕捉和输出框架。它提供了一组API和驱动程序接口,用于与摄像头设备进行交互和控制。

如果你想进行V4L2摄像头编程,你可以按照以下步骤进行:

1. 确保你的摄像头设备已连接到计算机上并正确识别。你可以使用`ls /dev/video*`命令来检查设备是否存在。

2. 创建一个C或C++程序,并包含V4L2的头文件。例如,在C++中,你可以包含 `<linux/videodev2.h>` 头文件。

3. 打开摄像头设备文件。你可以使用`open()`函数来打开设备文件,例如`/dev/video0`。

4. 查询摄像头设备的能力和属性。使用`ioctl()`函数和`VIDIOC_QUERYCAP`命令来获取设备的能力和属性信息。

5. 配置摄像头的捕捉参数。使用`ioctl()`函数和`VIDIOC_S_FMT`命令来设置图像格式、分辨率和帧率等参数。

6. 请求和映射摄像头的视频缓冲区。使用`ioctl()`函数和`VIDIOC_REQBUFS`命令来请求摄像头的视频缓冲区,并使用`mmap()`函数将缓冲区映射到用户空间。

7. 启动视频流捕捉。使用`ioctl()`函数和`VIDIOC_STREAMON`命令来启动视频流捕捉。

8. 捕捉图像数据。使用`ioctl()`函数和`VIDIOC_DQBUF`命令来从摄像头的视频缓冲区中获取图像数据。

9. 处理和使用图像数据。你可以对图像数据进行处理、存储或者展示。

10. 释放视频缓冲区并停止视频流捕捉。使用`ioctl()`函数和`VIDIOC_STREAMOFF`命令停止视频流捕捉,并使用`munmap()`函数释放视频缓冲区的映射。

11. 关闭摄像头设备。使用`close()`函数关闭设备文件。

v4l2camera没有使用多路复用.c


#include <stdio.h>
#include <linux/videodev2.h>  //V4L2对应的头文件
#include <stropts.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <string.h>
#include <unistd.h>
#define W 640
#define H 480

//自定义结构体,用来存放每个缓冲块的首地址和大小
struct bufmsg
{
  void *start;  //缓冲块的首地址
  int somelen;  //缓冲块的大小
};

//封装函数--》把一组YUV--》转换ARGB数据
int yuvtoargb(int y,int u,int v)
{
  int r,g,b;
  int pix;
  r = 1164*(y-16)/1000 + 1596*(v-128)/1000;
  g = 1164*(y-16)/1000 + 813*(v-128)/1000 - 391*(u-128)/1000;
  b = 1164*(y-16)/1000 + 2018*(u-128)/1000;
  
  //修正计算结果 0---255之间
  if(r>255)
    r=255;
  if(g>255)
    g=255;
  if(b>255)
    b=255;
  if(r<0)
    r=0;
  if(g<0)
    g=0;
  if(b<0)
    b=0;
  
  //把rgb拼接得到ARGB
  pix=0x00<<24|r<<16|g<<8|b;
  return pix;
}

//封装函数--》把一帧画面数据中所有的YUYV数据转换成ARGB数据
//参数:yuv --》指向一帧yuyv画面首地址
//      argbbuf --》存放转换得到的完整的ARGB数据
//allyuvtoargb(array[i].start,argbbuf)
/*
  yuv[0]--第一个Y
  yuv[1]--      U
  yuv[2]--第二个Y
  yuv[3]--      V
*/
int allyuvtoargb(char *yuv,int *argbbuf)
{
  int i,j;
  for(i=0,j=0; i<W*H; i+=2,j+=4)
  {
    //一组YUYV转换得到两组ARGB数据
    argbbuf[i]=yuvtoargb(yuv[j],yuv[j+1],yuv[j+3]);
    argbbuf[i+1]=yuvtoargb(yuv[j+2],yuv[j+1],yuv[j+3]);
  }
  return 0;
}
int main()
{
  int camerafd;
  int ret;
  int i,j;
  int lcdfd;
  int *lcdmem;
  
  //打开lcd
  lcdfd=open("/dev/fb0",O_RDWR);
  if(lcdfd==-1)
  {
    perror("打开lcd失败!\n");
    return -1;
  }
  
  //映射得到lcd的首地址
  lcdmem=mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcdfd,0);
  if(lcdmem==NULL)
  {
    perror("映射lcd失败了!\n");
    return -1;
  }
  
  //打开摄像头的驱动
  camerafd=open("/dev/video7",O_RDWR);
  if(camerafd==-1)
  {
    perror("打开摄像头失败!\n");
    return -1;
  }
  
  //设置摄像头采集格式
  struct v4l2_format myfmt;
  bzero(&myfmt,sizeof(myfmt));
  myfmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
  myfmt.fmt.pix.width=W;
  myfmt.fmt.pix.height=H;
  myfmt.fmt.pix.pixelformat=V4L2_PIX_FMT_YUYV;
  ret=ioctl(camerafd,VIDIOC_S_FMT,&myfmt);
  if(ret==-1)
  {
    perror("设置采集格式失败!\n");
    return -1;
  }
  
  //申请4个缓冲块
  struct v4l2_requestbuffers mybuf;
  bzero(&mybuf,sizeof(mybuf));
  mybuf.count=4;  //4个缓冲块
  mybuf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
  mybuf.memory=V4L2_MEMORY_MMAP;
  ret=ioctl(camerafd,VIDIOC_REQBUFS,&mybuf);
  if(ret==-1)
  {
    perror("申请缓冲块失败!\n");
    return -1;
  }
  
  //分配缓冲块顺便映射得到4个缓冲块的首地址
  struct v4l2_buffer otherbuf;
  //定义结构体数组存放4个缓冲块的首地址和大小
  struct bufmsg array[4];
  
  for(i=0; i<4; i++)
  {
    bzero(&otherbuf,sizeof(otherbuf));
    otherbuf.index=i;  //索引号
    otherbuf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
    otherbuf.memory=V4L2_MEMORY_MMAP;
    ret=ioctl(camerafd,VIDIOC_QUERYBUF,&otherbuf);
    if(ret==-1)
    {
      perror("分配缓冲块失败!\n");
      return -1;
    }
    //顺便映射得到4个缓冲块的首地址
    array[i].somelen=otherbuf.length;
    array[i].start=mmap(NULL,otherbuf.length,PROT_READ|PROT_WRITE,MAP_SHARED,camerafd,otherbuf.m.offset);
    if(array[i].start==NULL)
    {
      perror("映射缓冲块失败了!\n");
      return -1;
    }
    //顺便发送入队申请(一旦摄像头启动了,立马把画面入队)
    ret=ioctl(camerafd,VIDIOC_QBUF,&otherbuf);
    if(ret==-1)
    {
      perror("入队失败!\n");
      return -1;
    }
  }
  
  //启动摄像头捕捉
  enum v4l2_buf_type mytype;
  mytype=V4L2_BUF_TYPE_VIDEO_CAPTURE;
  ret=ioctl(camerafd,VIDIOC_STREAMON,&mytype);
  if(ret==-1)
  {
    perror("启动摄像头捕捉失败!\n");
    return -1;
  }
  
  //定义一个数组存放转换得到的一帧完整的ARGB数据
  int argbbuf[W*H];
  
  //让摄像头画面循环出队,入队形成视频流在lcd上显示出来
  while(1)
  {
    for(i=0; i<4; i++)
    {
      //出队
      bzero(&otherbuf,sizeof(otherbuf));
      otherbuf.index=i;  //索引号
      otherbuf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
      otherbuf.memory=V4L2_MEMORY_MMAP;
      ret=ioctl(camerafd,VIDIOC_DQBUF,&otherbuf);
      if(ret==-1)
      {
        perror("出队失败!\n");
        return -1;
      }
      //出队画面(在结构体数组里面存放着)在lcd上显示出来
      //array[i].start --》  当前出队的画面数据(YUV格式)首地址
      //array[i].somelen --》当前出队的画面数据大小
      //YUV格式无法直接在lcd上显示,原因是lcd只能显示ARGB数据
      /*
      第一行数据:  argbbuf[0]--argbbuf[W-1]
                   lcdmem
        第二行数据:  argbbuf[W]--argbbuf[2*W-1]
                   lcdmem+下一行
      */
      allyuvtoargb(array[i].start,argbbuf);
      //把argbbuf中的数据填充到lcd对应的位置
      for(j=0; j<H; j++)
        memcpy(lcdmem+800*j,&argbbuf[W*j],W*4);
      //入队 
      ret=ioctl(camerafd,VIDIOC_QBUF,&otherbuf);
      if(ret==-1)
      {
        perror("入队失败!\n");
        return -1;
      }
    }
  }
  
  //收尾
  ret=ioctl(camerafd,VIDIOC_STREAMOFF,&mytype);
  if(ret==-1)
  {
    perror("关闭摄像头捕捉失败!\n");
    return -1;
  }
  munmap(lcdmem,800*480*4);
  for(i=0; i<4; i++)
    munmap(array[i].start,array[i].somelen);
  close(lcdfd);
  close(camerafd);
  return 0;
}

v4l2camera使用了多路复用.c:

#include <stdio.h>
#include <linux/videodev2.h>  //V4L2对应的头文件
#include <stropts.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>

#define W 640
#define H 480

//自定义结构体,用来存放每个缓冲块的首地址和大小
struct bufmsg
{
  void *start;  //缓冲块的首地址
  int somelen;  //缓冲块的大小
};

//封装函数--》把一组YUV--》转换ARGB数据
int yuvtoargb(int y,int u,int v)
{
  int r,g,b;
  int pix;
  r = 1164*(y-16)/1000 + 1596*(v-128)/1000;
  g = 1164*(y-16)/1000 + 813*(v-128)/1000 - 391*(u-128)/1000;
  b = 1164*(y-16)/1000 + 2018*(u-128)/1000;
  
  //修正计算结果 0---255之间
  if(r>255)
    r=255;
  if(g>255)
    g=255;
  if(b>255)
    b=255;
  if(r<0)
    r=0;
  if(g<0)
    g=0;
  if(b<0)
    b=0;
  
  //把rgb拼接得到ARGB
  pix=0x00<<24|r<<16|g<<8|b;
  return pix;
}

//封装函数--》把一帧画面数据中所有的YUYV数据转换成ARGB数据
//参数:yuv --》指向一帧yuyv画面首地址
//      argbbuf --》存放转换得到的完整的ARGB数据
//allyuvtoargb(array[i].start,argbbuf)
/*
  yuv[0]--第一个Y
  yuv[1]--      U
  yuv[2]--第二个Y
  yuv[3]--      V
*/
int allyuvtoargb(char *yuv,int *argbbuf)
{
  int i,j;
  for(i=0,j=0; i<W*H; i+=2,j+=4)
  {
    //一组YUYV转换得到两组ARGB数据
    argbbuf[i]=yuvtoargb(yuv[j],yuv[j+1],yuv[j+3]);
    argbbuf[i+1]=yuvtoargb(yuv[j+2],yuv[j+1],yuv[j+3]);
  }
  return 0;
}
int main()
{
  int camerafd;
  int ret;
  int i,j;
  int lcdfd;
  int *lcdmem;
  
  //打开lcd
  lcdfd=open("/dev/fb0",O_RDWR);
  if(lcdfd==-1)
  {
    perror("打开lcd失败!\n");
    return -1;
  }
  
  //映射得到lcd的首地址
  lcdmem=mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcdfd,0);
  if(lcdmem==NULL)
  {
    perror("映射lcd失败了!\n");
    return -1;
  }
  
  //打开摄像头的驱动
  camerafd=open("/dev/video7",O_RDWR);
  if(camerafd==-1)
  {
    perror("打开摄像头失败!\n");
    return -1;
  }
  
  //设置摄像头采集格式
  struct v4l2_format myfmt;
  bzero(&myfmt,sizeof(myfmt));
  myfmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
  myfmt.fmt.pix.width=W;
  myfmt.fmt.pix.height=H;
  myfmt.fmt.pix.pixelformat=V4L2_PIX_FMT_YUYV;
  ret=ioctl(camerafd,VIDIOC_S_FMT,&myfmt);
  if(ret==-1)
  {
    perror("设置采集格式失败!\n");
    return -1;
  }
  
  //申请4个缓冲块
  struct v4l2_requestbuffers mybuf;
  bzero(&mybuf,sizeof(mybuf));
  mybuf.count=4;  //4个缓冲块
  mybuf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
  mybuf.memory=V4L2_MEMORY_MMAP;
  ret=ioctl(camerafd,VIDIOC_REQBUFS,&mybuf);
  if(ret==-1)
  {
    perror("申请缓冲块失败!\n");
    return -1;
  }
  
  //分配缓冲块顺便映射得到4个缓冲块的首地址
  struct v4l2_buffer otherbuf;
  //定义结构体数组存放4个缓冲块的首地址和大小
  struct bufmsg array[4];
  
  for(i=0; i<4; i++)
  {
    bzero(&otherbuf,sizeof(otherbuf));
    otherbuf.index=i;  //索引号
    otherbuf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
    otherbuf.memory=V4L2_MEMORY_MMAP;
    ret=ioctl(camerafd,VIDIOC_QUERYBUF,&otherbuf);
    if(ret==-1)
    {
      perror("分配缓冲块失败!\n");
      return -1;
    }
    //顺便映射得到4个缓冲块的首地址
    array[i].somelen=otherbuf.length;
    array[i].start=mmap(NULL,otherbuf.length,PROT_READ|PROT_WRITE,MAP_SHARED,camerafd,otherbuf.m.offset);
    if(array[i].start==NULL)
    {
      perror("映射缓冲块失败了!\n");
      return -1;
    }
    //顺便发送入队申请(一旦摄像头启动了,立马把画面入队)
    ret=ioctl(camerafd,VIDIOC_QBUF,&otherbuf);
    if(ret==-1)
    {
      perror("入队失败!\n");
      return -1;
    }
  }
  
  //启动摄像头捕捉
  enum v4l2_buf_type mytype;
  mytype=V4L2_BUF_TYPE_VIDEO_CAPTURE;
  ret=ioctl(camerafd,VIDIOC_STREAMON,&mytype);
  if(ret==-1)
  {
    perror("启动摄像头捕捉失败!\n");
    return -1;
  }
  
  //定义一个数组存放转换得到的一帧完整的ARGB数据
  int argbbuf[W*H];
  
  //定义集合存放要监测的文件描述符
  fd_set myset;
  FD_ZERO(&myset);
  FD_SET(camerafd,&myset);

  //让摄像头画面循环出队,入队形成视频流在lcd上显示出来
  while(1)
  {
    for(i=0; i<4; i++)
    {
      //监测摄像头队列中是否有数据可读
      ret=select(camerafd+1,&myset,NULL,NULL,NULL);
      if(ret>0)  //说明摄像头的缓冲区中有画面入队了
      {
        //出队
        bzero(&otherbuf,sizeof(otherbuf));
        otherbuf.index=i;  //索引号
        otherbuf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
        otherbuf.memory=V4L2_MEMORY_MMAP;
        ret=ioctl(camerafd,VIDIOC_DQBUF,&otherbuf);
        if(ret==-1)
        {
          perror("出队失败!\n");
          return -1;
        }
        //出队画面(在结构体数组里面存放着)在lcd上显示出来
        //array[i].start --》  当前出队的画面数据(YUV格式)首地址
        //array[i].somelen --》当前出队的画面数据大小
        //YUV格式无法直接在lcd上显示,原因是lcd只能显示ARGB数据
        /*
        第一行数据:  argbbuf[0]--argbbuf[W-1]
               lcdmem
        第二行数据:  argbbuf[W]--argbbuf[2*W-1]
               lcdmem+下一行
        */
        allyuvtoargb(array[i].start,argbbuf);
        //把argbbuf中的数据填充到lcd对应的位置
        for(j=0; j<H; j++)
          memcpy(lcdmem+800*j,&argbbuf[W*j],W*4);
        //入队 
        ret=ioctl(camerafd,VIDIOC_QBUF,&otherbuf);
        if(ret==-1)
        {
          perror("入队失败!\n");
          return -1;
        }
      }
      
    }
  }
  
  //收尾
  ret=ioctl(camerafd,VIDIOC_STREAMOFF,&mytype);
  if(ret==-1)
  {
    perror("关闭摄像头捕捉失败!\n");
    return -1;
  }
  munmap(lcdmem,800*480*4);
  for(i=0; i<4; i++)
    munmap(array[i].start,array[i].somelen);
  close(lcdfd);
  close(camerafd);
  return 0;
}

按比例缩小.c


#include <stdio.h>
#include <linux/videodev2.h>  //V4L2对应的头文件
#include <stropts.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>

#define W 320   
#define H 240  

//自定义结构体,用来存放每个缓冲块的首地址和大小
struct bufmsg
{
  void *start;  //缓冲块的首地址
  int somelen;  //缓冲块的大小
};

//封装函数--》把一组YUV--》转换ARGB数据
int yuvtoargb(int y,int u,int v)
{
  int r,g,b;
  int pix;
  r = 1164*(y-16)/1000 + 1596*(v-128)/1000;
  g = 1164*(y-16)/1000 + 813*(v-128)/1000 - 391*(u-128)/1000;
  b = 1164*(y-16)/1000 + 2018*(u-128)/1000;
  
  //修正计算结果 0---255之间
  if(r>255)
    r=255;
  if(g>255)
    g=255;
  if(b>255)
    b=255;
  if(r<0)
    r=0;
  if(g<0)
    g=0;
  if(b<0)
    b=0;
  
  //把rgb拼接得到ARGB
  pix=0x00<<24|r<<16|g<<8|b;
  return pix;
}

//封装函数--》把一帧画面数据中所有的YUYV数据转换成ARGB数据
//参数:yuv --》指向一帧yuyv画面首地址
//      argbbuf --》存放转换得到的完整的ARGB数据
//allyuvtoargb(array[i].start,argbbuf)
/*
  yuv[0]--第一个Y
  yuv[1]--      U
  yuv[2]--第二个Y
  yuv[3]--      V
*/
int allyuvtoargb(char *yuv,int *argbbuf)
{
  int i,j;
  for(i=0,j=0; i<W*H; i+=2,j+=4)
  {
    //一组YUYV转换得到两组ARGB数据
    argbbuf[i]=yuvtoargb(yuv[j],yuv[j+1],yuv[j+3]);
    argbbuf[i+1]=yuvtoargb(yuv[j+2],yuv[j+1],yuv[j+3]);
  }
  return 0;
}
int main()
{
  int camerafd;
  int ret;
  int i,j;
  int lcdfd;
  int *lcdmem;
  
  //打开lcd
  lcdfd=open("/dev/fb0",O_RDWR);
  if(lcdfd==-1)
  {
    perror("打开lcd失败!\n");
    return -1;
  }
  
  //映射得到lcd的首地址
  lcdmem=mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcdfd,0);
  if(lcdmem==NULL)
  {
    perror("映射lcd失败了!\n");
    return -1;
  }
  
  //打开摄像头的驱动
  camerafd=open("/dev/video7",O_RDWR);
  if(camerafd==-1)
  {
    perror("打开摄像头失败!\n");
    return -1;
  }
  
  //设置摄像头采集格式
  struct v4l2_format myfmt;
  bzero(&myfmt,sizeof(myfmt));
  myfmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
  myfmt.fmt.pix.width=W;
  myfmt.fmt.pix.height=H;
  myfmt.fmt.pix.pixelformat=V4L2_PIX_FMT_YUYV;
  ret=ioctl(camerafd,VIDIOC_S_FMT,&myfmt);
  if(ret==-1)
  {
    perror("设置采集格式失败!\n");
    return -1;
  }
  
  //申请4个缓冲块
  struct v4l2_requestbuffers mybuf;
  bzero(&mybuf,sizeof(mybuf));
  mybuf.count=4;  //4个缓冲块
  mybuf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
  mybuf.memory=V4L2_MEMORY_MMAP;
  ret=ioctl(camerafd,VIDIOC_REQBUFS,&mybuf);
  if(ret==-1)
  {
    perror("申请缓冲块失败!\n");
    return -1;
  }
  
  //分配缓冲块顺便映射得到4个缓冲块的首地址
  struct v4l2_buffer otherbuf;
  //定义结构体数组存放4个缓冲块的首地址和大小
  struct bufmsg array[4];
  
  for(i=0; i<4; i++)
  {
    bzero(&otherbuf,sizeof(otherbuf));
    otherbuf.index=i;  //索引号
    otherbuf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
    otherbuf.memory=V4L2_MEMORY_MMAP;
    ret=ioctl(camerafd,VIDIOC_QUERYBUF,&otherbuf);
    if(ret==-1)
    {
      perror("分配缓冲块失败!\n");
      return -1;
    }
    //顺便映射得到4个缓冲块的首地址
    array[i].somelen=otherbuf.length;
    array[i].start=mmap(NULL,otherbuf.length,PROT_READ|PROT_WRITE,MAP_SHARED,camerafd,otherbuf.m.offset);
    if(array[i].start==NULL)
    {
      perror("映射缓冲块失败了!\n");
      return -1;
    }
    //顺便发送入队申请(一旦摄像头启动了,立马把画面入队)
    ret=ioctl(camerafd,VIDIOC_QBUF,&otherbuf);
    if(ret==-1)
    {
      perror("入队失败!\n");
      return -1;
    }
  }
  
  //启动摄像头捕捉
  enum v4l2_buf_type mytype;
  mytype=V4L2_BUF_TYPE_VIDEO_CAPTURE;
  ret=ioctl(camerafd,VIDIOC_STREAMON,&mytype);
  if(ret==-1)
  {
    perror("启动摄像头捕捉失败!\n");
    return -1;
  }
  
  //定义一个数组存放转换得到的一帧完整的ARGB数据
  int argbbuf[W*H];
  
  //定义集合存放要监测的文件描述符
  fd_set myset;
  FD_ZERO(&myset);
  FD_SET(camerafd,&myset);

  //让摄像头画面循环出队,入队形成视频流在lcd上显示出来
  while(1)
  {
    for(i=0; i<4; i++)
    {
      //监测摄像头队列中是否有数据可读
      ret=select(camerafd+1,&myset,NULL,NULL,NULL);
      if(ret>0)  //说明摄像头的缓冲区中有画面入队了
      {
        //出队
        bzero(&otherbuf,sizeof(otherbuf));
        otherbuf.index=i;  //索引号
        otherbuf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
        otherbuf.memory=V4L2_MEMORY_MMAP;
        ret=ioctl(camerafd,VIDIOC_DQBUF,&otherbuf);
        if(ret==-1)
        {
          perror("出队失败!\n");
          return -1;
        }
        //出队画面(在结构体数组里面存放着)在lcd上显示出来
        //array[i].start --》  当前出队的画面数据(YUV格式)首地址
        //array[i].somelen --》当前出队的画面数据大小
        //YUV格式无法直接在lcd上显示,原因是lcd只能显示ARGB数据
        /*
        第一行数据:  argbbuf[0]--argbbuf[W-1]
               lcdmem
        第二行数据:  argbbuf[W]--argbbuf[2*W-1]
               lcdmem+下一行
        */
        allyuvtoargb(array[i].start,argbbuf);
        //把argbbuf中的数据填充到lcd对应的位置
        for(j=0; j<H; j++)
          memcpy(lcdmem+80+800*j,&argbbuf[W*j],W*4);
        //入队 
        ret=ioctl(camerafd,VIDIOC_QBUF,&otherbuf);
        if(ret==-1)
        {
          perror("入队失败!\n");
          return -1;
        }
      }
      
    }
  }
  
  //收尾
  ret=ioctl(camerafd,VIDIOC_STREAMOFF,&mytype);
  if(ret==-1)
  {
    perror("关闭摄像头捕捉失败!\n");
    return -1;
  }
  munmap(lcdmem,800*480*4);
  for(i=0; i<4; i++)
    munmap(array[i].start,array[i].somelen);
  close(lcdfd);
  close(camerafd);
  return 0;
}

版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。

(0)

相关推荐

发表回复

登录后才能评论