LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 2891|回复: 1

求助:关于V4L2的图像抓取程序

[复制链接]
发表于 2008-7-2 08:46:19 | 显示全部楼层 |阅读模式
我现在在学习V4L2的图像捕捉程序,用的是v4l2文档中的video capture example,并修改了其中process_image函数。已经没有了编译错误。所有的函数都是返回成功。但是捕捉出来的图像是黑的。我估计问题可能是出在2个地方:
1. 格式不对。
#define  WIDTH  320
#define  HEIGHT 240

static void
init_device                     (void)
{
    struct v4l2_capability cap;
    struct v4l2_cropcap cropcap;
    struct v4l2_crop crop;
    struct v4l2_format fmt;

     //printf("init_device : start\n");
        if (-1 == xioctl (fd, VIDIOC_QUERYCAP, &cap)) {
                if (EINVAL == errno) {
                        fprintf (stderr, "%s is no V4L2 device\n",
                                 dev_name);
                        exit (EXIT_FAILURE);
                } else {
                        errno_exit ("VIDIOC_QUERYCAP");
                }
        }

        if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
                fprintf (stderr, "%s is no video capture device\n",
                         dev_name);
                exit (EXIT_FAILURE);
        }
        /* Select video input, video standard and tune here. */


        CLEAR (cropcap);

        cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

        if (0 == xioctl (fd, VIDIOC_CROPCAP, &cropcap)) {
                crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                crop.c = cropcap.defrect; /* reset to default */

                if (-1 == xioctl (fd, VIDIOC_S_CROP, &crop)) {
                        switch (errno) {
                        case EINVAL:
                                /* Cropping not supported. */
                                break;
                        default:
                                /* Errors ignored. */
                                break;
                        }
                }
        } else {
                /* Errors ignored. */
        }


        CLEAR (fmt);

        fmt.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        fmt.fmt.pix.width       = WIDTH;
        fmt.fmt.pix.height      = HEIGHT;
        fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;
        fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;

        if (-1 == xioctl (fd, VIDIOC_S_FMT, &fmt))
                errno_exit ("VIDIOC_S_FMT");

        /* Note VIDIOC_S_FMT may change width and height. */

        /* Buggy driver paranoia. */
        min = fmt.fmt.pix.width * 2;
        if (fmt.fmt.pix.bytesperline < min)
                fmt.fmt.pix.bytesperline = min;
        min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
        if (fmt.fmt.pix.sizeimage < min)
                fmt.fmt.pix.sizeimage = min;

        init_mmap ();
        printf("init_device : end\n");
}
请高手帮我看看有什么错误。






2.赋错了缓冲区。
程序定义了一个buffer的结构体。
struct buffer {
        void *                  start;
        size_t                  length;
};
struct buffer *         buffers         = NULL;



static void
start_capturing                 (void)
{
        unsigned int i;
        enum v4l2_buf_type type;

         for (i = 0; i < n_buffers; ++i) {
                struct v4l2_buffer buf;

                CLEAR (buf);

                buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                buf.memory      = V4L2_MEMORY_MMAP;
                buf.index       = i;

                if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
                    errno_exit ("VIDIOC_QBUF");
        }//end for
               
        type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

        if (-1 == xioctl (fd, VIDIOC_STREAMON, &type))
                        errno_exit ("VIDIOC_STREAMON");
        printf("start_capturing : end\n");
}




static void
init_mmap                        (void)
{
        struct v4l2_requestbuffers req;
        printf("init_mmap : start\n");
        CLEAR (req);

        req.count               = 4;
        req.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        req.memory              = V4L2_MEMORY_MMAP;

        if (-1 == xioctl (fd, VIDIOC_REQBUFS, &req)) {
                if (EINVAL == errno) {
                        fprintf (stderr, "%s does not support "
                                 "memory mapping\n", dev_name);
                        exit (EXIT_FAILURE);
                } else {
                        errno_exit ("VIDIOC_REQBUFS");
                }
        }

        if (req.count < 2) {
                fprintf (stderr, "Insufficient buffer memory on %s\n",
                         dev_name);
                exit (EXIT_FAILURE);
        }

        buffers = calloc (req.count, sizeof (*buffers));

        if (!buffers) {
                fprintf (stderr, "Out of memory\n");
                exit (EXIT_FAILURE);
        }

        for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
                struct v4l2_buffer buf;

                CLEAR (buf);

                buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                buf.memory      = V4L2_MEMORY_MMAP;
                buf.index       = n_buffers;

                if (-1 == xioctl (fd, VIDIOC_QUERYBUF, &buf))
                        errno_exit ("VIDIOC_QUERYBUF");

                buffers[n_buffers].length = buf.length;
                buffers[n_buffers].start =
                        mmap (NULL /* start anywhere */,
                              buf.length,
                              PROT_READ | PROT_WRITE /* required */,
                              MAP_SHARED /* recommended */,
                              fd, buf.m.offset);
                                if (-1 == buffers[n_buffers].start)
                                        printf("mmap is failed\n");
                //        errno_exit ("mmap");
        }
                printf("init_mmap : end\n");
}







接着是在main_loop()函数中调用read_frame()
static int
read_frame                        (void)
{
        struct v4l2_buffer buf;
        unsigned int i;
        printf("read_frame : start\n");

        CLEAR (buf);

                    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                    buf.memory = V4L2_MEMORY_MMAP;

                    if (-1 == xioctl (fd, VIDIOC_DQBUF, &buf)) {
                            switch (errno) {
                            case EAGAIN:
                                    return 0;

                                        case EIO:
                                                /* Could ignore EIO, see spec. */

                                                /* fall through */

                                        default:
                                                errno_exit ("VIDIOC_DQBUF");
                        }
                }

                assert (buf.index < n_buffers);
///////////////////////////////
              process_image (buffers[buf.index].start);

                if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
                        errno_exit ("VIDIOC_QBUF");
        return 1;
}






然后是process_image()函数
static void
process_image(void * p)
{
                //fputc ('.', stdout);
        //fflush (stdout);
        char *address = NULL;
     FILE *  fp;
     char *filename = "filename";       //文件名

   fp=fopen(filename,"w");
     if(fp==NULL){
           perror("open file failure");
           exit(-1);
     }

     fprintf(fp,"6\n%d %d\n255\n",WIDTH,HEIGHT);  
     address = (unsigned char *)p;//+ buf->length;
     if( address==(char *)NULL){  
           perror(" get mapaddress Failed!");
           exit(-1);
     }
     else   
           printf(" get mapaddress SUCCESS!\n");

     fwrite(address,WIDTH,3*HEIGHT,fp);
     fclose(fp);
}

请高手帮忙看一下。
发表于 2008-7-17 18:53:07 | 显示全部楼层

v4l2编程

不知道楼上的大哥问题解决了没有,现在我也在做这块的编程,
在VIDEO CAPTURE  EXAMPLE 例子编译通过,在目标板上运行后,出现 VIDIOC_STREAMON error 16, Device or resource busy

,不知道是什么原因,期待你的回答
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表