打印

有熟悉v4l2的吗?碰到了个怪问题

[复制链接]
4622|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
big5|  楼主 | 2007-10-8 14:30 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
ST, mt, fm, pi, se
基于v4l2(linux 2.6)的视频采集(ARM9+TVP5150)YUV420数据,下面是我的程序:

#ifdef __cplusplus
extern "C"{
#endif

/*=======================================================================
                                        INCLUDE FILES
=======================================================================*/
/* Standard Include Files */
#include <errno.h>
    
/* Verification Test Environment Include Files */
#include <sys/types.h>    
#include <sys/stat.h>    
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>    
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <asm/types.h>
#include <linux/compiler.h>
#include <linux/videodev.h>
#include <sys/mman.h>
#include <string.h>
#include <malloc.h>
//#include <asm/arch/mxc_v4l2.h>

struct v4l2_mxc_offset {
    uint32_t u_offset;
    uint32_t v_offset;
};

#define TEST_BUFFER_NUM 3

struct testbuffer
{
        unsigned char *start;
        size_t offset;
        unsigned int length;
};

struct testbuffer buffers[TEST_BUFFER_NUM];
int g_width = 352;
int g_height = 288;
int g_capture_count = 3;
int g_rotate = 0;
int g_cap_fmt = V4L2_PIX_FMT_YUV420;
int g_camera_framerate = 30;
int g_extra_pixel = 0;

int start_capturing(int fd_v4l)
{
        unsigned int i;
        struct v4l2_buffer buf;
        enum v4l2_buf_type type;

        for (i = 0; i < TEST_BUFFER_NUM; i++)
        {
                memset(&buf, 0, sizeof (buf));
                buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                buf.index = i;
                if (ioctl(fd_v4l, VIDIOC_QUERYBUF, &buf) < 0)
                {
                        printf("VIDIOC_QUERYBUF error ");
                        return -1;
                }

                buffers.length = buf.length;
                buffers.offset = (size_t) buf.m.offset;
                buffers.start = mmap (NULL, buffers.length,
                    PROT_READ | PROT_WRITE, MAP_SHARED,
                    fd_v4l, buffers.offset);
                memset(buffers.start, 0xFF, buffers.length);
        }

        for (i = 0; i < TEST_BUFFER_NUM; i++)
        {
                memset(&buf, 0, sizeof (buf));
                buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                buf.memory = V4L2_MEMORY_MMAP;
                buf.index = i;
                buf.m.offset = buffers.offset;
                if (g_extra_pixel){
                    buf.m.offset += g_extra_pixel *
                        (g_width + 2 * g_extra_pixel) + g_extra_pixel;
                }

                if (ioctl (fd_v4l, VIDIOC_QBUF, &buf) < 0) {
                        printf("VIDIOC_QBUF error ");
                        return -1;
                }
        }

        type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        if (ioctl (fd_v4l, VIDIOC_STREAMON, &type) < 0) {
                printf("VIDIOC_STREAMON error ");
                return -1;
        }
        return 0;
}

int stop_capturing(int fd_v4l)
{
        enum v4l2_buf_type type;

        type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        return ioctl (fd_v4l, VIDIOC_STREAMOFF, &type);
}

int v4l_capture_setup(void)
{
        char v4l_device[100] = "/dev/v4l/video0";
        struct v4l2_format fmt;
        struct v4l2_control ctrl;
        struct v4l2_streamparm parm;
        int fd_v4l = 0;
        struct v4l2_mxc_offset off;
        
        if ((fd_v4l = open(v4l_device, O_RDWR, 0)) < 0)
        {
                printf("Unable to open %s ", v4l_device);
                return 0;
        }
        
        struct v4l2_crop crop;
        memset(&crop, 0, sizeof (crop));
        crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        crop.c.left = 0;
        crop.c.top = 0;
        crop.c.width = 640;
        crop.c.height = 288;    
        if (ioctl(fd_v4l, VIDIOC_S_CROP, &crop) < 0)
        {
                printf("set cropping failed ");
        }
                        
        fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
        fmt.fmt.pix.width = g_width;
        fmt.fmt.pix.height = g_height;
        if (g_extra_pixel){
            off.u_offset = (2 * g_extra_pixel + g_width) * (g_height + g_extra_pixel)
                 - g_extra_pixel + (g_extra_pixel / 2) * ((g_width / 2)
                 + g_extra_pixel) + g_extra_pixel / 2;  
            off.v_offset = off.u_offset + (g_extra_pixel + g_width / 2) *
                ((g_height / 2) + g_extra_pixel);  
            fmt.fmt.pix.bytesperline = g_width + g_extra_pixel * 2;
            fmt.fmt.pix.priv = (uint32_t) &off;
            fmt.fmt.pix.sizeimage = (g_width + g_extra_pixel * 2 )
                * (g_height + g_extra_pixel * 2) * 3 / 2;
        } else {
            fmt.fmt.pix.bytesperline = g_width;
            printf("bytesperline: %d ", fmt.fmt.pix.bytesperline);
            fmt.fmt.pix.priv = 0;
            fmt.fmt.pix.sizeimage = 0;
        }

        if (ioctl(fd_v4l, VIDIOC_S_FMT, &fmt) < 0)
        {
                printf("set format failed ");
                return 0;
        }

        parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        parm.parm.capture.timeperframe.numerator = 1;
        parm.parm.capture.timeperframe.denominator = g_camera_framerate;
        parm.parm.capture.capturemode = 0;
         
        if (ioctl(fd_v4l, VIDIOC_S_PARM, &parm) < 0)
        {
                printf("VIDIOC_S_PARM failed ");
                return -1;
        }

        // Set rotation
        ctrl.id = V4L2_CID_PRIVATE_BASE + 0;
        ctrl.value = g_rotate;
        if (ioctl(fd_v4l, VIDIOC_S_CTRL, &ctrl) < 0)
        {
                printf("set ctrl failed ");
                return 0;
        }

        struct v4l2_requestbuffers req;
        memset(&req, 0, sizeof (req));
        req.count = TEST_BUFFER_NUM;
        req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        req.memory = V4L2_MEMORY_MMAP;

        if (ioctl(fd_v4l, VIDIOC_REQBUFS, &req) < 0)
        {
                printf("v4l_capture_setup: VIDIOC_REQBUFS failed ");
                return 0;
        }

        return fd_v4l;
}

int v4l_capture_test(int fd_v4l, const char * file)
{
        struct v4l2_buffer buf;
#if TEST_OUTSYNC_ENQUE
        struct v4l2_buffer temp_buf;
#endif
        struct v4l2_format fmt;
        FILE * fd_y_file = 0;
        int count = g_capture_count;
   
        if ((fd_y_file = fopen(file, "wb")) < 0)
        {
                printf("Unable to create y frame recording file ");
                return -1;
        }

        fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        if (ioctl(fd_v4l, VIDIOC_G_FMT, &fmt) < 0)
        {
                printf("get format failed ");
                return -1;
        }
        else
        {
                printf("  Width = %d", fmt.fmt.pix.width);
                printf("  Height = %d", fmt.fmt.pix.height);
                printf("  Image size = %d ", fmt.fmt.pix.sizeimage);
                printf("  pixelformat = %d ", fmt.fmt.pix.pixelformat);
        }

        if (start_capturing(fd_v4l) < 0)
        {
                printf("start_capturing failed ");
                return -1;
        }

        while (count-- > 0) {
                memset(&buf, 0, sizeof (buf));
                buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                buf.memory = V4L2_MEMORY_MMAP;
                if (ioctl (fd_v4l, VIDIOC_DQBUF, &buf) < 0)    {
                        printf("VIDIOC_DQBUF failed. ");
                }

                fwrite(buffers[buf.index].start, fmt.fmt.pix.sizeimage, 1, fd_y_file);

#if TEST_OUTSYNC_ENQUE
                /* Testing out of order enque */
                if (count == 25) {
                    temp_buf = buf;
                    printf("buf.index %d ", buf.index);
                    continue;
                }

                if (count == 15) {
                        if (ioctl (fd_v4l, VIDIOC_QBUF, &temp_buf) < 0) {
                                printf("VIDIOC_QBUF failed ");
                                break;
                        }
                }
#endif
                if (count >= TEST_BUFFER_NUM) {
                        if (ioctl (fd_v4l, VIDIOC_QBUF, &buf) < 0) {
                                printf("VIDIOC_QBUF failed ");
                                break;
                        }
                }
                else
                        printf("buf.index %d ", buf.index);
        }

        if (stop_capturing(fd_v4l) < 0)
        {
                printf("stop_capturing failed ");
                return -1;
        }

        fclose(fd_y_file);

        close(fd_v4l);
        return 0;
}


int process_cmdline(int argc, char **argv)
{
        int i;
        
        for (i = 1; i < argc; i++) {
                if (strcmp(argv, "-w") == 0) {
                        g_width = atoi(argv[++i]);
                }
                else if (strcmp(argv, "-h") == 0) {
                        g_height = atoi(argv[++i]);
                }
                else if (strcmp(argv, "-r") == 0) {
                        g_rotate = atoi(argv[++i]);
                }
                else if (strcmp(argv, "-c") == 0) {
                        g_capture_count = atoi(argv[++i]);
                }
                else if (strcmp(argv, "-fr") == 0) {
                        g_camera_framerate = atoi(argv[++i]);
                }
                else if (strcmp(argv, "-e") == 0) {
                        g_extra_pixel = atoi(argv[++i]);
                }
                else if (strcmp(argv, "-f") == 0) {
                        i++;
                        g_cap_fmt = v4l2_fourcc(argv[0], argv[1],argv[2],argv[3]);

                        if ( (g_cap_fmt != V4L2_PIX_FMT_BGR24) &&
                             (g_cap_fmt != V4L2_PIX_FMT_BGR32) &&
                             (g_cap_fmt != V4L2_PIX_FMT_RGB565) &&
                             (g_cap_fmt != V4L2_PIX_FMT_YUV420) )
                        {
                                return -1;
                        }
                }
                else if (strcmp(argv, "-help") == 0) {
                        printf("MXC Video4Linux capture Device Test " 
                               "Syntax: mxc_v4l2_capture.out -w <capture width> " 
                               " -h <capture height> " 
                               " -r <rotation> -c <capture counter>  "
                               " -e <destination cropping: extra pixels>  " 
                               " -f <format> -fr <frame rate, 0-auto>  ");
                        return -1;
               }
        }

        printf("g_width = %d, g_height = %d ", g_width, g_height);
        
        if ((g_width == 0) || (g_height == 0)) {
                return -1;
        }
        return 0;
}

int main(int argc, char **argv)
{
        int fd_v4l;

        if (process_cmdline(argc, argv) < 0) {
                return -1;
        }
        fd_v4l = v4l_capture_setup();
        return v4l_capture_test(fd_v4l, argv[argc-1]);
}

现在采集出来的图像在垂直面上有两幅相同的。
不知道还有哪个参数不对。

相关帖子

沙发
big5|  楼主 | 2007-10-9 10:45 | 只看该作者

搞这方面的人不多吗?

刚入手开发板(20000米),把这个问题反馈给哪个JS,他居然告诉我要解决这个问题需要再花15000米,气死我了。什么技术支持也没有。

使用特权

评论回复
板凳
rockos| | 2007-10-9 14:53 | 只看该作者

Re


v4l2 specification 从0.21开始, 自带有一个测试程序, 演示了driver与application交互数据的几种方法, 你可以使用那个测试程序跑一下.

如果driver符合v4l2规范, 那个测试程序是最权威的测试结果。如果那个程序没有你说的问题,那就肯定是测试程序的问题,不用找JS,自己搞定就行了。

使用特权

评论回复
地板
big5|  楼主 | 2007-10-9 15:26 | 只看该作者

感谢您的回复

我利用了测试程序,有点不明白
我输入"./capture -m",屏幕上打了很多点,没有其他错误,这样可以证明什么?

使用特权

评论回复
5
yyxl| | 2011-7-4 18:34 | 只看该作者
源码在哪????

使用特权

评论回复
6
chl00100| | 2011-7-4 23:07 | 只看该作者
采集出来的图像在垂直面上有两幅相同   应该是配置为按场取了,找到相关地方,配置为按帧取即可;
实在找不到,自己写段代码把奇、偶两场合并为一帧也是可以的,浪费点cpu。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

91

主题

242

帖子

0

粉丝