免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5110 | 回复: 0

[图形界面] 分析 JPEG 图像文件时出错(Not a JPEG file: starts with 0xec 0x80) [复制链接]

论坛徽章:
0
发表于 2014-11-05 14:12 |显示全部楼层
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <linux/types.h>
#include <linux/videodev2.h>
#include <malloc.h>
#include <math.h>
#include <string.h>
#include <sys/mman.h>
#include <errno.h>
#include <assert.h>



typedef struct
{
        void *start;
        int length;
}BUFTYPE;

BUFTYPE *user_buf;
int n_buffer = 0;

//打开摄像头设备
int open_camer_device()
{
        int fd;

        if((fd = open("/dev/video0",O_RDWR | O_NONBLOCK)) < 0)
        {
                perror("Fail to open";
                exit(EXIT_FAILURE);
        }

        return fd;
}

int init_mmap(int fd)
{
        int i = 0;
        struct v4l2_requestbuffers reqbuf;

        bzero(&reqbuf,sizeof(reqbuf));
        reqbuf.count = 4;
        reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        reqbuf.memory = V4L2_MEMORY_MMAP;

        //申请视频缓冲区(这个缓冲区位于内核空间,需要通过mmap映射)
        //这一步操作可能会修改reqbuf.count的值,修改为实际成功申请缓冲区个数
        if(-1 == ioctl(fd,VIDIOC_REQBUFS,&reqbuf))
        {
                perror("Fail to ioctl 'VIDIOC_REQBUFS'";
                exit(EXIT_FAILURE);
        }

        n_buffer = reqbuf.count;

        printf("n_buffer = %d\n",n_buffer);

        user_buf = calloc(reqbuf.count,sizeof(*user_buf));
        if(user_buf == NULL){
                fprintf(stderr,"Out of memory\n";
                exit(EXIT_FAILURE);
        }

        //将内核缓冲区映射到用户进程空间
        for(i = 0; i < reqbuf.count; i ++)
        {
                struct v4l2_buffer buf;

                bzero(&buf,sizeof(buf));
                buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                buf.memory = V4L2_MEMORY_MMAP;
                buf.index = i;
                //查询申请到内核缓冲区的信息
                if(-1 == ioctl(fd,VIDIOC_QUERYBUF,&buf))
                {
                        perror("Fail to ioctl : VIDIOC_QUERYBUF";
                        exit(EXIT_FAILURE);
                }

                user_buf[i].length = buf.length;
                user_buf[i].start =
                        mmap(
                                        NULL,/*start anywhere*/
                                        buf.length,
                                        PROT_READ | PROT_WRITE,
                                        MAP_SHARED,
                                        fd,buf.m.offset
                                );
                if(MAP_FAILED == user_buf[i].start)
                {
                        perror("Fail to mmap";
                        exit(EXIT_FAILURE);
                }
        }

        return 0;
}

//初始化视频设备
int init_camer_device(int fd)
{
        struct v4l2_fmtdesc fmt;
        struct v4l2_capability cap;
        struct v4l2_format stream_fmt;
        int ret;

        //当前视频设备支持的视频格式
        memset(&fmt,0,sizeof(fmt));
        fmt.index = 0;
        fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

        while((ret = ioctl(fd,VIDIOC_ENUM_FMT,&fmt)) == 0)
        {
                fmt.index ++ ;

                printf("{pixelformat = %c%c%c%c},description = '%s'\n",
                                fmt.pixelformat & 0xff,(fmt.pixelformat >> &0xff,
                                (fmt.pixelformat >> 16) & 0xff,(fmt.pixelformat >> 24)&0xff,
                                fmt.description);
        }

        //查询视频设备驱动的功能
        ret = ioctl(fd,VIDIOC_QUERYCAP,&cap);
        if(ret < 0){
                perror("FAIL to ioctl VIDIOC_QUERYCAP";
                exit(EXIT_FAILURE);
        }

        //判断是否是一个视频捕捉设备
        if(!(cap.capabilities & V4L2_BUF_TYPE_VIDEO_CAPTURE))
        {
                printf("The Current device is not a video capture device\n";
                exit(EXIT_FAILURE);

        }

        //判断是否支持视频流形式
        if(!(cap.capabilities & V4L2_CAP_STREAMING))
        {
                printf("The Current device does not support streaming i/o\n";
                exit(EXIT_FAILURE);
        }

        //设置摄像头采集数据格式,如设置采集数据的
        //长,宽,图像格式(JPEG,YUYV,MJPEG等格式)
        stream_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        stream_fmt.fmt.pix.width = 640;
        stream_fmt.fmt.pix.height = 480;
        stream_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;
        stream_fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;

        if(-1 == ioctl(fd,VIDIOC_S_FMT,&stream_fmt))
        {
                perror("Fail to ioctl";
                exit(EXIT_FAILURE);
        }


        //初始化视频采集方式(mmap)
        init_mmap(fd);

        return 0;
}

int start_capturing(int fd)
{
        unsigned int i;
        enum v4l2_buf_type type;

        //将申请的内核缓冲区放入一个队列中
        for(i = 0;i < n_buffer;i ++)
        {
                struct v4l2_buffer buf;

                bzero(&buf,sizeof(buf));
                buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                buf.memory = V4L2_MEMORY_MMAP;
                buf.index = i;

                if(-1 == ioctl(fd,VIDIOC_QBUF,&buf))
                {
                        perror("Fail to ioctl 'VIDIOC_QBUF'";
                        exit(EXIT_FAILURE);
                }
        }

        //开始采集数据
        type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        if(-1 == ioctl(fd,VIDIOC_STREAMON,&type))
        {
                printf("i = %d.\n",i);
                perror("Fail to ioctl 'VIDIOC_STREAMON'");
                exit(EXIT_FAILURE);
        }

        return 0;
}

//将采集好的数据放到文件中
int process_image(void *addr,int length)
{
        FILE *fp;
        static int num = 0;
        char picture_name[20];

        sprintf(picture_name,"picture_%d.jpg",num ++);

        if((fp = fopen(picture_name,"w")) == NULL)
        {
                perror("Fail to fopen");
                exit(EXIT_FAILURE);
        }

        printf("len=%d\n",length);
        fwrite(addr,length,1,fp);
        usleep(500);

        fclose(fp);

        return 0;
}

int read_frame(int fd)
{
        struct v4l2_buffer buf;
        unsigned int i;

        bzero(&buf,sizeof(buf));
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_MMAP;

        //从队列中取缓冲区
        if(-1 == ioctl(fd,VIDIOC_DQBUF,&buf))
        {
                perror("Fail to ioctl 'VIDIOC_DQBUF'");
                exit(EXIT_FAILURE);
        }

        assert(buf.index < n_buffer);
        //读取进程空间的数据到一个文件中
        process_image(user_buf[buf.index].start,user_buf[buf.index].length);

        if(-1 == ioctl(fd,VIDIOC_QBUF,&buf))
        {
                perror("Fail to ioctl 'VIDIOC_QBUF'");
                exit(EXIT_FAILURE);
        }

        return 1;
}

int mainloop(int fd)
{
        int count = 1;

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

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

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

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

                        if(-1 == r)
                        {
                                if(EINTR == errno)
                                        continue;

                                perror("Fail to select");
                                exit(EXIT_FAILURE);
                        }

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

                        if(read_frame(fd))
                                break;
                }
        }

        return 0;
}

void stop_capturing(int fd)
{
        enum v4l2_buf_type type;

        type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        if(-1 == ioctl(fd,VIDIOC_STREAMOFF,&type))
        {
                perror("Fail to ioctl 'VIDIOC_STREAMOFF'");
                exit(EXIT_FAILURE);
        }

        return;
}

void uninit_camer_device()
{
        unsigned int i;

        for(i = 0;i < n_buffer;i ++)
        {
                if(-1 == munmap(user_buf[i].start,user_buf[i].length))
                {
                        exit(EXIT_FAILURE);
                }
        }

        free(user_buf);

        return;
}

void close_camer_device(int fd)
{
        if(-1 == close(fd))
        {
                perror("Fail to close fd");
                exit(EXIT_FAILURE);
        }

        return;
}

int main()
{
        int fd;

        fd = open_camer_device();

        init_camer_device(fd);

        start_capturing(fd);

        mainloop(fd);

        stop_capturing(fd);

        uninit_camer_device(fd);

        close_camer_device(fd);

        return 0;
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP