免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1819 | 回复: 0
打印 上一主题 下一主题

[图形界面] 段错误 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-11-06 14:26 |只看该作者 |倒序浏览
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>              /* low-level i/o */
#include <unistd.h>
#include <errno.h>
#include <assert.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <stdbool.h>

#include <linux/videodev2.h>
#include <linux/fb.h>

#define CLEAR(x) memset(&(x), 0, sizeof(x))

struct buffer {
        void   *start;
        size_t  length;
};

static char *dev_name1;
static char *dev_name2;
static int  fd1 = -1;
static int        fd2 = -1;

struct buffer          *buffers;
static unsigned int     n_buffers;
static char *fb_buffer;
static unsigned long screensize;

static char *yuv_buffer;
static char *rgb_buffer;


static int force_format=false;
static int frame_count =1000;

static void errno_exit(const char *s)
{
        fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno));
        exit(EXIT_FAILURE);
}

static int xioctl(int fh, int request, void *arg)
{
        int r;

        do {
                r = ioctl(fh, request, arg);
        } while (-1 == r && EINTR == errno);

        return r;
}
/*
static void process_image(const void *p, int size)
{
        unsigned short *fb;
        unsigned short *rgb;
        unsigned long height = 480;
        if(size>screensize)
                size=screensize;

        //move
        memcpy(yuv_buffer,p,size);

        //proc
        memcpy(rgb_buffer,yuv_buffer,size);

        //move
        memcpy(fb_buffer,yuv_buffer,size);


        //move
        rgb=(unsigned short*)rgb_buffer;
        fb=(unsigned short*)fb_buffer;
        while(height--)
        {
                memcpy(fb,rgb,1280);
                fb+=640;
                rgb+=640;
        }


        fflush(stderr);
        fprintf(stderr, ".";
        fflush(stdout);
}
*/
static  void YUV2RGB(unsigned char Y,unsigned char U,unsigned char V,
                                        unsigned char *R,unsigned char *G,unsigned char *B)
/*static  void YUV2RGB(int Y,int U,int V,
                                        int *R,int *G,int *B)*/
{
/*
        *R=Y+1.4075*(V-12;
        *G=Y-0.3455*(U-12-0.7169*(V-12;
        *B=Y+1.779*(U-12;
*/

        *R=Y+(V-12+((V-12*103>>;
        *G=Y-((U-12*88>>-((V-12*183>>8);
        *B=Y+(U-128)+((U-128)*198>>8);
}

static void process_image(const unsigned long *from, int size)
{
        unsigned long *to =(unsigned long*)fb_buffer;

        unsigned char Y0;
        unsigned char U0;
        unsigned char Y1;
        unsigned char V0;

        unsigned char R0;
        unsigned char G0;
        unsigned char B0;
        unsigned char R1;
        unsigned char G1;
        unsigned char B1;

        size>>=2;
        while(size--)
        {
                Y0=(*from & 0x000000FF)>>0;
                U0=128;                                                        //white and black
                //U0=(*from & 0x0000FF00)>>8;        //colorful
                Y1=(*from & 0x00FF0000)>>16;
                V0=128;                                                        //white and blcak
                //V0=(*from & 0xFF000000)>>24;        //colorful
                YUV2RGB(Y0,U0,V0,&R0,&G0,&B0);
                YUV2RGB(Y1,U0,V0,&R1,&G1,&B1);

                *to = (R0&0x1F)<<11 | (G0&0x3F)<<5 |(B0&0x1F)<<0;
                *to |= ((R1&0x1F)<<11 | (G1&0x3F)<<5 |(B1&0x1F)<<0)<<16;

                from++;
                to++;
        }
}

static int read_frame(void)
{
        struct v4l2_buffer buf;

        CLEAR(buf);
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_MMAP;
        if (-1 == xioctl(fd1, VIDIOC_DQBUF, &buf))
        {
                switch (errno)
                {
                        case EAGAIN:
                                return 0;
                        case EIO:
                        default:
                                errno_exit("VIDIOC_DQBUF";
                }
        }

        assert(buf.index < n_buffers);

        process_image(buffers[buf.index].start, buf.bytesused);

        if (-1 == xioctl(fd1, VIDIOC_QBUF, &buf))
                errno_exit("VIDIOC_QBUF";

        return 1;
}

static void mainloop(void)
{
        unsigned int count;

        count = frame_count;
        while (count-- > 0) {
                for (; {
                        fd_set fds;
                        struct timeval tv;
                        int r;

                        FD_ZERO(&fds);
                        FD_SET(fd1, &fds);

                        /* Timeout. */
                        tv.tv_sec = 2;
                        tv.tv_usec = 0;

                        r = select(fd1 + 1, &fds, NULL, NULL, &tv);

                        if (-1 == r) {
                                if (EINTR == errno)
                                        continue;
                                errno_exit("select";
                        }

                        if (0 == r) {
                                fprintf(stderr, "select timeout\n";
                                exit(EXIT_FAILURE);
                        }

                        if (read_frame())
                                break;
                        /* EAGAIN - continue select loop. */
                }
        }
}

static void stop_capturing(void)
{
        enum v4l2_buf_type type;

        type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        if (-1 == xioctl(fd1, VIDIOC_STREAMOFF, &type))
                errno_exit("VIDIOC_STREAMOFF";
}

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

        for (i = 0; i < n_buffers; ++i)
        {
                CLEAR(buf);
                buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                buf.memory = V4L2_MEMORY_MMAP;
                buf.index = i;
                if (-1 == xioctl(fd1, VIDIOC_QBUF, &buf))
                        errno_exit("VIDIOC_QBUF";
        }

        type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        if (-1 == xioctl(fd1, VIDIOC_STREAMON, &type))
                errno_exit("VIDIOC_STREAMON";

}

static void uninit_device(void)
{
        unsigned int i;

        for (i = 0; i < n_buffers; ++i)
                if (-1 == munmap(buffers[i].start, buffers[i].length))
                        errno_exit("munmap";

        if(-1 == munmap(fb_buffer,screensize))
                errno_exit("munmap");

        free(buffers);
        free(rgb_buffer);
        free(yuv_buffer);
}

static void init_mmap(void)
{
        struct v4l2_requestbuffers req;
        struct v4l2_buffer buf;

        //VIDIOC_REQBUFS
        CLEAR(req);
        req.count = 4;
        req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        req.memory = V4L2_MEMORY_MMAP;
        if(-1 == xioctl(fd1, VIDIOC_REQBUFS, &req))
        {
                if (EINVAL == errno)
                {
                        fprintf(stderr, "%s does not support ""memory mapping\n", dev_name1);
                        exit(EXIT_FAILURE);
                }
                else
                        errno_exit("VIDIOC_REQBUFS");
        }
        if(req.count < 2)
        {
                fprintf(stderr, "Insufficient buffer memory on %s\n",dev_name1);
                exit(EXIT_FAILURE);
        }

        //VIDIOC_QUERYBUF
        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)
        {
                CLEAR(buf);
                buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                buf.memory      = V4L2_MEMORY_MMAP;
                buf.index       = n_buffers;
                if (-1 == xioctl(fd1, 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 */,
                                                                fd1, buf.m.offset);
                if (MAP_FAILED == buffers[n_buffers].start)
                {
                        errno_exit("mmap");
                }
        }//now n_buffers is 4

        //fbmmap
        fb_buffer=(char*)mmap(NULL,screensize,PROT_READ | PROT_WRITE,MAP_SHARED,fd2,0);
        if(MAP_FAILED == fb_buffer)
        {
                errno_exit("mmap");
        }

        //malloc the yuv_buffer
        yuv_buffer = (char*)malloc(screensize);
        if (!yuv_buffer)
        {
                fprintf(stderr, "Out of memory\n");
                exit(EXIT_FAILURE);
        }

        //malloc the rgb_buffer
        rgb_buffer = (char*)malloc(screensize);
        if (!rgb_buffer)
        {
                fprintf(stderr, "Out of memory\n");
                exit(EXIT_FAILURE);
        }
}

static void init_device(void)
{
        struct v4l2_capability cap;
        struct v4l2_format fmt;
        struct fb_fix_screeninfo finfo;
        struct fb_var_screeninfo vinfo;

        CLEAR(cap);
        if (-1 == xioctl(fd1, VIDIOC_QUERYCAP, &cap))
        {
                if (EINVAL == errno)
                {
                        fprintf(stderr, "%s is no V4L2 device\n",dev_name1);
                        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_name1);
                exit(EXIT_FAILURE);
        }
        if (!(cap.capabilities & V4L2_CAP_STREAMING))
        {
                fprintf(stderr, "%s does not support streaming i/o\n",dev_name1);
                exit(EXIT_FAILURE);
        }

        CLEAR(fmt);
        fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        if (force_format)
        {
                fmt.fmt.pix.width       = 640;
                fmt.fmt.pix.height      = 480;
                fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
                fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;
                if (-1 == xioctl(fd1, VIDIOC_S_FMT, &fmt))
                        errno_exit("VIDIOC_S_FMT");
        }
        else
        {
                if (-1 == xioctl(fd1, VIDIOC_G_FMT, &fmt))
                        errno_exit("VIDIOC_G_FMT");
        }
        fprintf(stdout,"<------------camera infomation------------->\n");
        fprintf(stdout,"device driver=%s\n",cap.driver);
        fprintf(stdout,"device name=%s\n",cap.card);
        fprintf(stdout,"bus_infomation=%s\n",cap.bus_info);
        fprintf(stdout,"image_width=%d\n",fmt.fmt.pix.width);
        fprintf(stdout,"image_height=%d\n",fmt.fmt.pix.height);
        fprintf(stdout,"pixel_format=%d\n",fmt.fmt.pix.pixelformat);
        fprintf(stdout,"\n");


        CLEAR(finfo);
        if(-1 == xioctl(fd2,FBIOGET_FSCREENINFO,&finfo))
                errno_exit("FBIOGET_FSCREENINFO");

        CLEAR(vinfo);
        if(-1 == xioctl(fd2,FBIOGET_VSCREENINFO,&vinfo))
                errno_exit("FBIOGET_VSCREENINFO");
        screensize = vinfo.xres*vinfo.yres*vinfo.bits_per_pixel/8;

        fprintf(stdout,"<------------screen infomation------------->\n");
        fprintf(stdout,"id=%s\n",finfo.id);
        fprintf(stdout,"x=%d\n",vinfo.xres);
        fprintf(stdout,"y=%d\n",vinfo.yres);
        fprintf(stdout,"bpp=%d\n",vinfo.bits_per_pixel);
        fprintf(stdout,"redoffset=%d,redlength=%d,msb_right=%d\n",
                        vinfo.red.offset,vinfo.red.length,vinfo.red.msb_right);
        fprintf(stdout,"greenoffset=%d,greenlength=%d,msb_right=%d\n",
                        vinfo.green.offset,vinfo.green.length,vinfo.green.msb_right);
        fprintf(stdout,"blueoffset=%d,bluelength=%d,msb_right=%d\n",
                        vinfo.blue.offset,vinfo.blue.length,vinfo.blue.msb_right);
        fprintf(stdout,"screensize=%d\n",screensize);

        init_mmap();
}

static void close_device(void)
{
        if (-1 == close(fd1))
                errno_exit("close");
        fd1 = -1;

        if (-1 == close(fd2))
                errno_exit("close");
        fd2 = -1;
}

static void open_device(void)
{

        fd1 = open(dev_name1, O_RDWR /* required */ | O_NONBLOCK, 0);
        if (-1 == fd1)
        {
                fprintf(stderr, "Cannot open '%s': %d, %s\n",dev_name1, errno, strerror(errno));
                exit(EXIT_FAILURE);
        }

        fd2 = open(dev_name2,O_RDWR,0);
        if(-1 == fd2)
        {
                fprintf(stderr, "Cannot open '%s': %d, %s\n",dev_name2, errno, strerror(errno));
                exit(EXIT_FAILURE);
        }
}

int main(int argc, char **argv)
{
        dev_name1 = "/dev/video0";
        dev_name2 = "/dev/fb0";

        open_device();
        init_device();
        start_capturing();
        mainloop();
        stop_capturing();
        uninit_device();
        close_device();
        fprintf(stderr, "\n");
        return 0;
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP