jackieswift 发表于 2014-01-21 17:34

利用V4L读取摄像头显示错误--- v4l_grab_sync: Inappropriate ioctl for device?

利用V4L编程,获取USB摄像头信息,运行后显示错误如下:

v4l_grab_frame: Inappropriate ioctl for device
v4l_grab_sync: Inappropriate ioctl for device

具体的源代码如下:求高手指导,多谢,QQ:962519705

/*******v4l.h******/

#ifndef _V4L_H_
#define _V4L_H_

#define DEFAULT_DEVICE "/dev/video0"
#define TRUE 1
#define FALSE 0
#include <sys/stat.h>
#include <sys/mman.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <linux/videodev2.h>
#include <linux/videodev.h>

struct _v4l_struct
{
    int fd; //保存打开视频文件的设备描述符
    struct v4l2_capability capability;
    struct video_picture picture;
    struct video_mmap mmap;
    struct video_mbuf mbuf;
    unsigned char *map; //用于指向图像数据的指针
    int frame_current;
    int frame_using ;//VIDEO_MAX_FRAME 为videodev2.h中的宏定义,值为32
};

typedef struct _v4l_struct v4l_device;

extern int v4l_open(char* ,v4l_device *);
extern int v4l_close(v4l_device *);
extern int v4l_get_capability(v4l_device*);
extern int v4l_get_picture(v4l_device *);
extern int v4l_get_mbuf(v4l_device *);
extern int v4l_set_picture(v4l_device* ,int,int,int,int,int);
extern int v4l_grab_picture(v4l_device*,unsigned int);
extern int v4l_mmap_init(v4l_device*);
extern int v4l_grab_init(v4l_device*, int,int);
extern int v4l_grab_frame(v4l_device*, int);
extern int v4l_grab_sync(v4l_device*);

//使用流程
//1、打开视频设备;
//2、获得设备信息;
//3、根据需要更改设备的相关设置;
//4、获得采集到的图像数据(在这里v4l提供了两种方式,直接通过打开的设备读取数据,使用mmap内存映射的方式获取数据);
//5、对采集到的数据进行操作(如显示到屏幕,图像处理,存储成图片文件);
//6、关闭视频设备;

int v4l_open(char *dev,v4l_device *vd)
{
    if(!dev) dev=DEFAULT_DEVICE;
    if((vd->fd=open(dev,O_RDWR))<0)
    {
      perror("v4l_open:");
      return -1;
    }
    if(v4l_get_capability(vd))
      return -1;
    if(v4l_get_picture(vd))
      return -1;
    return 0;
}

int v4l_close(v4l_device *vd)
{
    close(vd->fd);
    return 0;
}

int v4l_get_capability(v4l_device *vd)
{
    if(ioctl(vd->fd, VIDIOC_QUERYCAP,&(vd->capability))<0)
    {
      perror("v4l_get_capability:");
      return -1;
    }
    return 0;
}

int v4l_get_picture(v4l_device *vd)
{
    if(ioctl(vd->fd,VIDIOCGPICT,&(vd->picture))<0)
    {
      perror("v4l_get_picture:");
      return -1;
    }
    return 0;
}

int v4l_get_mbuf(v4l_device *vd)
{
    if(ioctl(vd->fd,VIDIOCGMBUF,&(vd->mbuf))<0)
    {
      perror("v4l_get_mbuf:");
      return -1;
    }
    return 0;
}

int v4l_set_picture(v4l_device *vd,int br,int hue,int col,int cont,int white)
{
    if(br) vd->picture.brightness=br;
    if(hue) vd->picture.hue=hue;                   //video_picture存在于videodev.h中
    if(col) vd->picture.colour=col;
    if(cont) vd->picture.contrast=cont;
    if(white) vd->picture.whiteness=white;
    if(ioctl(vd->fd,VIDIOCSPICT,&(vd->picture))<0)
    {perror("v4l_set_picture:");
    return -1;
    }
    return 0;
}

/* 获得采集到的图像数据,两种方法,介绍第一种,一般用第二种
extern int v4l_grab_picture(v4l_device* ,unsigned int);

int v4l_grab_picture(v4l_device* vd, unsigned int size)
{
    if(read(vd->fd,&(vd->map),size)==0)
      return -1;
    return 0;

}
*/

int v4l_mmap_init(v4l_device *vd)
{
    if(v4l_get_mbuf(vd)<0)
      return -1;
    if((vd->map=mmap(0,vd->mbuf.size,PROT_READ|PROT_WRITE,MAP_SHARED,vd->fd,0))<0)//mbuf.size==total memory to map
    {
      perror("v4l_mmap_init:mmap");
      return -1;
    }
    return 0;
}

int v4l_grab_init(v4l_device *vd,int width,int height)
{
    vd->mmap.width=width;
    vd->mmap.height=height;
    vd->mmap.format=vd->picture.palette;
    vd->frame_current=0;
    vd->frame_using=FALSE;
    vd->frame_using=FALSE;

    return v4l_grab_frame(vd,0);
}

int v4l_grab_frame(v4l_device *vd,int frame)
{
    vd->frame_current=0; //添加的,测试无法读取摄像头信息缘由
    if(vd->frame_using)
    {
      fprintf(stderr,"v4l_grab_frame:frame %d is already used.\n",frame);
      return -1;
    }

    vd->mmap.frame=frame;
    if(ioctl(vd->fd,VIDIOCMCAPTURE,&(vd->mmap))<0)
      {
            perror("v4l_grab_frame");
            return -1;
      }
      vd->frame_using=TRUE;
      vd->frame_current=frame;
      return 0;
}

int v4l_grab_sync(v4l_device *vd)
{
    if(ioctl(vd->fd,VIDIOCSYNC,&(vd->frame_current))<0)   //sync with map grabing
    {
      perror("v4l_grab_sync");
      return -1;
    }

    vd->frame_using=FALSE;
    return 0;
}

#endif

/*********v4l.c*********/

#include "v4l.h"

v4l_device vd;

void main()
{
    vd.frame_current=0; //添加测试用
    v4l_open(DEFAULT_DEVICE,&vd);
    v4l_mmap_init(&vd);
    v4l_grab_init(&vd,320,240);
    v4l_grab_sync(&vd);//此时就已经获得了一帧图片,存在vd.map中
    while(1)
    {
      vd.frame_current^=1;
      v4l_grab_frame(&vd,vd.frame_current);
      v4l_grab_sync(&vd);
    }
      v4l_close(&vd);
}

humjb_1983 发表于 2014-01-22 09:04

对这个不熟,但是看报错信息是ioctl报的,可以确认下用法是否正确。
页: [1]
查看完整版本: 利用V4L读取摄像头显示错误--- v4l_grab_sync: Inappropriate ioctl for device?