5008|9

1

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

2440 v4l 图片采集 问题 [复制链接]

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#include
#include

#define VIDEO_PALETTE_RAW_JPEG  20
#define VIDEO_PALETTE_JPEG 21

#define USB_VIDEO_DEV "/dev/v4l/video0"
#define FILE_NAME "/tmp/1.jpg"
#define STILL_IMAGE -1
#define VIDEO_START 0
#define VIDEO_STOP 1

static int debug = 1;

int get_jpegsize(unsigned char *buf, int size)
{
    int i;
    for(i = 1024; i < size; i++)
   {
       if ( (buf == 0xFF)&&(buf[i+1] == 0xD9)) return i+2;//jpeg文件格式中是以0xFF 0xD9结尾的,

                                                                                        //以此判断文件大小
   }
  return -1;
}

int main(int argc, char *argv[])
{   
        int usb_camera_fd = -1,framesize=0,jpegsize=0;
        char *usb_video_dev = USB_VIDEO_DEV;
        char *filename = FILE_NAME;
        FILE *fp;
        struct video_capability video_caps;
        struct video_channel    video_chan;
        struct video_picture    video_pic;   
        struct video_mbuf       video_mbuffer;
        struct video_mmap       vid_mmap;

        unsigned char *mapaddr=NULL,*framebuffer=NULL,*destbuffer=NULL;


        usb_camera_fd = open(usb_video_dev,O_RDWR);//打开设备,可读写
        if (usb_camera_fd == -1)
        {
                fprintf(stderr,"Can't open device %s",usb_video_dev);
                return 1;
        }   
        /**********************video_capability**************/
        if (ioctl(usb_camera_fd,VIDIOCGCAP,&video_caps) == -1)//get videodevice capability 获取设备基本信息
        {
                perror("Couldn't get videodevice capability");
                return -1;
        }

        if (debug)
        {
                printf("video name :             %s\n",video_caps.name);
                printf("video_caps.channels :%d\n",video_caps.channels);
                printf("video_caps.type :      0x%x\n",video_caps.type);
                printf("video maxwidth :       %d\n",video_caps.maxwidth);
                printf("video maxheight :      %d\n",video_caps.maxheight);
                printf("video minwidth :        %d\n",video_caps.minwidth);
                printf("video minheight :       %d\n",video_caps.minheight);     
        }

        /************************video_channel****************/

        /*video_chan.channel = video_caps.channels;

        if (ioctl(usb_camera_fd,VIDIOCGCHAN,&video_chan) == -1)//获取信号源的属性
        {
                perror("ioctl (VIDIOCGCAP)");
                return -1;
        }
        if (debug)
        {
                printf("video channel:           %d\n",video_chan.channel);
                printf("video channel name:  %s\n",video_chan.name);
                printf("video channel type:    %d\n",video_chan.type);
        }*/

        /*************************video_picture****************/
        if (ioctl(usb_camera_fd,VIDIOCGPICT,&video_pic) == -1)//获取设备采集的图象的各种属性
        {
                perror("ioctl (VIDIOCGPICT)");
                return -1;
        }

        /*video_pic.palette = VIDEO_PALETTE_JPEG;
        video_pic.depth = 8;
        video_pic.hue = 50110;
        video_pic.whiteness = 41380;

        if (ioctl(usb_camera_fd,VIDIOCSPICT,&video_pic) == -1)//设置设备采集的图象的属性
        {
                perror("ioctl (VIDIOCSPICT)");
                //return -1;
        }*/

        if (debug)
        {
                printf("video_pic.brightness :  %d\n",video_pic.brightness);
                printf("video_pic.colour :        %d\n",video_pic.colour);
                printf("video_pic.contrast :     %d\n",video_pic.contrast);
                printf("video_pic.depth :         %d\n",video_pic.depth);
                printf("video_pic.hue :            %d\n",video_pic.hue);
                printf("video_pic.whiteness :   %d\n",video_pic.whiteness);
                printf("video_pic.palette :        %d\n",video_pic.palette);
        }
        /************************video_mbuf**********************/
        memset(&video_mbuffer,0,sizeof(video_mbuffer));


        //初始化video_mbuf,以得到所映射的buffer的信息
        if (ioctl(usb_camera_fd,VIDIOCGMBUF,&video_mbuffer) == -1)//video_mbuf
        {
                perror("ioctl (VIDIOCGMBUF)");
                return -1;
        }
        if (debug)
        {
                printf("video_mbuffer.frames :     %d\n",video_mbuffer.frames);
                printf("video_mbuffer.offsets[0] : %d\nvideo_mbuffer.offsets[1] :%d\n",video_mbuffer.offsets          [0],video_mbuffer.offsets[1]);
                printf("video_mbuffer.size :          %d\n",video_mbuffer.size);     
        }

        //将mmap与video_mbuf绑定

        mapaddr=(unsigned char *)mmap(0,video_mbuffer.size,PROT_READ,MAP_SHARED,usb_camera_fd, 0);

        if (mapaddr < 0)
        {
                perror("v4l mmap");
                return -1;
        }
        /********************video_mmap*************************/

        vid_mmap.width = 320;
        vid_mmap.height = 240;
        vid_mmap.frame = 0;//单帧采集
        vid_mmap.format = VIDEO_PALETTE_JPEG;

        /**********************start capture********************///Mmap方式下真正开始视频截取

        //若调用成功,开始一帧的截取,是非阻塞的 是否截取完毕留给VIDIOCSYNC来判断
        if (ioctl(usb_camera_fd,VIDIOCCAPTURE,VIDEO_START) == -1)
        {
                perror("ioctl (VIDIOCCAPTURE)");
                return -1;
        }

        /***********************wait for ready*******************///调用VIDIOCSYNC等待一帧截取结束

        //若成功,表明一帧截取已完成。可以开始做下一次 VIDIOCMCAPTURE
        //frame是当前截取的帧的序号
        /*if (ioctl(usb_camera_fd, VIDIOCSYNC, &vid_mmap.frame) == -1)
        {
                perror("ioctl (VIDIOCSYNC)");
                //return -1;
        }*/
  
        framesize=320*240>>2;//实际采集到的jpeg图像的大小最多也就十几KB

        //获取刚刚采集到的图像数据帧的地址

        framebuffer = mapaddr + video_mbuffer.offsets[vid_mmap.frame];

        //获取图像的大小

        //jpegsize = get_jpegsize(framebuffer, framesize);

        if (jpegsize < 0)
        {
                printf("Can't get size of jpeg picture\n");
                return 1;
        }

        //分配空间,准备将destbuffer 缓冲区中的图像数据写入文件
        destbuffer = (unsigned char *)malloc(video_mbuffer.size);
        if ( destbuffer == NULL)
        {
                printf("malloc memory for destbuffer error\n");
                return -1;
        }
        memcpy(destbuffer,framebuffer,video_mbuffer.size);

        fp = fopen(filename,"wb");//打开文件
        if (!fp)
        {
                printf("Can't open file %s",filename);
                //return -1;
        }

        fwrite(destbuffer,video_mbuffer.size,1,fp);//写入文件
        fclose(fp);//关闭文件

        free(destbuffer);//释放空间
        munmap(mapaddr,video_mbuffer.size);//取消绑定
        close(usb_camera_fd);
        return 1;
}

open: fd = open("/dev/v4l/video0", O_RDONLY);
fd为文件句柄,失败时返回负值。
read: i = read(fd, buf, image_width*image_height*2);
成功时返回读取的字节数,失败时返回负值。
mmap: buf = (__u8 *)mmap(0, vm.size, PROT_READ, MAP_SHARED, fd, 0);
失败时返回-1。vm为video_mbuf结构体,通过调用ioctl的VIDIOCGMBUF获得vm.size
ioctl: ioctl(fd, VIDIOCCAPTURE, VIDEO_START);
                成功时返回0;失败时返回负值。
ioctl函数支持的命令如下:(定义位于/include/linux/videodev.h)
Opcode        Input type        Description
VIDIOCGCAP        struct video_capability        可获得当前摄像头支持的采集图像的最大值以及最小值
VIDIOCGWIN        struct video_window        获得捕获源的大小
VIDIOCSWIN        struct video_window        设置捕获源的大小
一般为640*480
VIDIOCGCAPTURE        struct video_capture        获得目标图像大小
VIDIOCSCAPTURE        struct video_capture        设置目标图像大小
(不得超过源大小)
VIDIOCGPICT        struct video_picture        获得采集图像的颜色模式
VIDIOCSPICT        struct video_picture        设置采集图像的颜色模式,
VIDIOCCAPTURE        STILL_IMAGE
VIDEO_START
VIDEO_STOP        开始/停止捕获。这三个宏需要自己定义,其值分别为:-1,0,1
STILL_IMAGE:捕获一帧后停止
VIDIOCGMBUF        struct video_mbuf        获得缓冲区的大小,用于mmap

注:采集参数的设置要在VIDEO_START之前执行,即执行VIDIOCCAPTURE时参数为VIDEO_START(或者STILL_IMAGE)时,才会检查更新硬件寄存器的设置。



上面是我的源码。下面是驱动开发接口

但是运行后怎么都得不到图片啊。

各位大侠帮小弟看看吧。。

最新回复

cun
你说的这个东西不知道你做好了没有,我有些问题想和你交流,我基本上可以显示图片,而且也实现扫频了。但是现在对于网络发包出现一点问题。我看了你调用的get_picturesize函数了,这个可以直接算出你jpeg包的大小。但是我试过后发现图片还是有问题,而且还有不少的噪声。 对于你上述的问题我有一些意见可以给你。第一,你的摄像头支持jpeg格式的设置吗?第二。如果支持的话,这部分是有硬件压缩还是软件压缩,因为如果你是前者的话,你必须有驱动支持。简单来说,你可以先设置你的摄像头为位图方式去采集,例如bmp=24,rgb=16来设这你的摄像头。  详情 回复 发表于 2010-6-29 19:40
点赞 关注

回复
举报

2

帖子

0

TA的资源

一粒金砂(中级)

沙发
 
没人帮忙么。。5555555
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
没人帮忙么。。5555555
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

4
 
我也正想做这个呢,要是你把问题解决一下告诉我一下,我的msn:zmy12006#hotmail.com,我用的mini2440
驱动的位置好像跟你有点不一样
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

5
 
开什么玩笑,把一堆的源代码贴上来,谁愿意看呀~~~

 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

6
 
不知道驱动的模块是不是正确的。驱动模块代码你也没有出来,就给了接口怎么弄啊 核心东西都没有。你那个程序是只是应用程序调用别人的接口的。如果驱动模块是正确的 你只要细心点应该就可以了
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

7
 
你得先证明驱动程序是正确的,然后再写程序.测试方法也很简单,找一个小程序测试下就可以了.
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

8
 
你的驱动的问题把,用的是什么 系统呢?或者系统与驱动的接口?
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

9
 
先采用 串口打印 等方式 调测试下 你对应图片采集的驱动吧。

看驱动是否正确,。

比如你可以拿一张 全黑 和全白的图片,看看 你的驱动采集的数据是否正确吧。
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

10
 
你说的这个东西不知道你做好了没有,我有些问题想和你交流,我基本上可以显示图片,而且也实现扫频了。但是现在对于网络发包出现一点问题。我看了你调用的get_picturesize函数了,这个可以直接算出你jpeg包的大小。但是我试过后发现图片还是有问题,而且还有不少的噪声。
对于你上述的问题我有一些意见可以给你。第一,你的摄像头支持jpeg格式的设置吗?第二。如果支持的话,这部分是有硬件压缩还是软件压缩,因为如果你是前者的话,你必须有驱动支持。简单来说,你可以先设置你的摄像头为位图方式去采集,例如bmp=24,rgb=16来设这你的摄像头。
 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/6 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表