国嵌实时监控系统代码笔记(一)cam.c

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <linux/types.h>
#include <linux/videodev2.h>

#include <main.h>

struct buf
{
    void *start;
    int len;	
};

struct cam 
{
    struct v4l2_dev *v4_dev;
    struct buf              tran_frm;           /* 帧转移 */
    __u32                   tran_frm_max_size;
	
};


struct v4l2_dev
{
    int fd;
    __u8 name[32];
    __u8 drv[16];
    struct buf *buf;
    struct event_ext *ev;
    
    void*                   arg;//arg即cam
};
																//图像的位置
static void handle_jpeg_img_proc(const void *p, int size, void *arg)//arg即cam
{
    struct cam *v = arg;//arg即cam
//	重新定义写入的图像数据
    v->tran_frm.start = (void*)p;
    v->tran_frm.len   = size;
}

/*事件处理函数*/
void cam_handler(int fd,void *arg)
{
     struct v4l2_buffer buf;
     struct v4l2_dev *v = arg;//arg即cam
     int file_fd;
     
     file_fd = open("test.jpg",O_RDWR|O_CREAT,0777);
	
     /*帧出列*/
     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     buf.memory = V4L2_MEMORY_MMAP;
     ioctl (v->fd, VIDIOC_DQBUF, &buf);//从缓冲区取出一个缓冲帧
 		//																						 buffer中已使用的字节数
     handle_jpeg_img_proc(v->buf[buf.index].start, buf.bytesused, v->arg);
   //通过v->buf映射的的图像缓冲区,通过buf.index取到对应的图像
     /*buf入列*/
     ioctl(v->fd, VIDIOC_QBUF, &buf);	//从缓冲区写入一个缓冲帧
}

struct v4l2_dev * v4l2_init()
{
     struct v4l2_capability cap;
     struct v4l2_dev *v;
     struct v4l2_format fmt;//四字符代码,为了标示视频数据流格式 
     struct v4l2_requestbuffers req;
     int i;
     struct v4l2_buffer buf;  

     
     //1. 初始化摄像头
     v = calloc(1,sizeof(struct v4l2_dev));
     v->fd = open("/dev/video3",O_RDWR|O_NONBLOCK);
     
     //1.1 获取驱动信息
     ioctl (v->fd, VIDIOC_QUERYCAP, &cap);
 	// int ioctl(int handle, int cmd,[int *argdx, int argcx]);返回值:成功为0,出错为-1
   //ioctl主要是调用后完成更改驱动中的参数  		*******************  重要概念   **********************
     if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) //检测摄像头
     {
          printf("this is not a video device\n");
          return -1;	
     }
     strcpy((char *)v->name,(char *)cap.card);
     strcpy((char *)v->drv,(char *)cap.driver);
     
     //1.2 设置图像格式
     fmt.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     fmt.fmt.pix.width       = 1280;
     fmt.fmt.pix.height      = 1024;
     fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;
     fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;//四字符代码,为了标示视频数据流格式 
		//这个结构体在设置格式和获取当然格式时会用到。  
		//struct v4l2_format {  
    //enum v4l2_buf_type type;//类型,已说过  
    //union {   
    //    struct v4l2_pix_format      pix;     /* V4L2_BUF_TYPE_VIDEO_CAPTURE */   
    //    struct v4l2_pix_format_mplane   pix_mp;  /* V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE */   
    //    struct v4l2_window      win;     /* V4L2_BUF_TYPE_VIDEO_OVERLAY */  
    //    struct v4l2_vbi_format      vbi;     /* V4L2_BUF_TYPE_VBI_CAPTURE */  
    //    struct v4l2_sliced_vbi_format   sliced;  /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */  
    //    __u8    raw_data[200];                   /* user-defined */  
    //} fmt;  
     ioctl (v->fd, VIDIOC_S_FMT, &fmt) ;
        
     //1.3 申请图像缓冲区
     req.count               = 4;//4个连续缓冲区
     req.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     req.memory              = V4L2_MEMORY_MMAP;
     ioctl (v->fd, VIDIOC_REQBUFS, &req);
     
     //1.4 把内核空间中的图像缓冲区映射到用户空间
     v->buf = calloc(4,sizeof(struct buf));
     
     for (i = 0; i < req.count; i++)
     { 
           /*获取图像缓冲区的信息*/
           buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
           buf.memory      = V4L2_MEMORY_MMAP;
           buf.index       = i;
 
           ioctl (v->fd, VIDIOC_QUERYBUF, &buf); 
             
           v->buf[i].len = buf.length; 
           
           // 把内核空间中的图像缓冲区映射到用户空间
          v->buf[i].start = mmap (NULL ,    //通过mmap建立映射关系
                                        buf.length,
                                        PROT_READ | PROT_WRITE ,//可读可写标志
                                        MAP_SHARED ,//与其它所有映射这个对象的进程共享映射空间。
                                        v->fd,
                                        buf.m.offset);//被映射对象内容的起点。
     }
     
     //1.5 图像缓冲入队
       for (i = 0; i < 4; ++i)
       {
               buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
               buf.memory      = V4L2_MEMORY_MMAP;
               buf.index       = i; //取到对应的图像缓冲区的图像入队
               ioctl (v->fd, VIDIOC_QBUF, &buf);     
       }
     
     //2. 注册事件到epoll
     v->ev = epoll_event_create(v->fd,EPOLLIN,cam_handler,v);
     //																可读类型						
     epoll_add_event(srv_main->epfd,v->ev);
     
     return v;
	
}

void v4l2_start_capture(struct v4l2_dev *v)
{
    enum v4l2_buf_type type;
    
    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    ioctl (v->fd, VIDIOC_STREAMON, &type);
}

struct cam * cam_sys_init()
{
     struct cam *cam = calloc(1,sizeof(struct cam));
     
     //1. 初始化
     cam->v4_dev = v4l2_init();
     cam->v4_dev->arg = cam; //							arg在这里得到了cam
     
     //2. 开始采集
     v4l2_start_capture(cam->v4_dev);   
     
     //3. 第2课加入
     return cam;	
}

void cam_get_fmt(struct cam *v, __u8 *rsp) 
{
    __u32 fmt = V4L2_PIX_FMT_JPEG;
    memcpy(rsp, &fmt, 4);
}


__u32 cam_get_trans_frame(struct cam *v, __u8 *rsp)
{
    memcpy(rsp, v->tran_frm.start, v->tran_frm.len); 
    return v->tran_frm.len;
}

int process_incoming(struct tcp_cli * c) 
{
    struct cam      *v      = srv_main->cam;
    __u8            *req    = c->req;
    __u8            *rsp    = c->rsp;
    __u8            id      = req[CMD1_POS];
    __u8            status  = ERR_SUCCESS;
    __u8            data[FRAME_DAT_MAX];//保存格式
    __u32           pos, len, size;

    switch (id) {

    case REQUEST_ID(VID_GET_FMT)://发送图像格式
        cam_get_fmt(v, data);        
        build_ack(rsp, (TYPE_SRSP << TYPE_BIT_POS) | SUBS_VID, id, 4, data);
   //		VID_GET_FMT	    =	REQUEST(0x0, TYPE_SREQ, SUBS_VID, 0x11)
  //		#define REQUEST(len, type, subs, id)	(((len) << (8*LEN_POS)) | \
 //			(((type) << TYPE_BIT_POS | (subs)) << (8*CMD0_POS)) | ((id) << (8*CMD1_POS)))
        
        net_send(c, rsp, 4 + FRAME_HDR_SZ);
		break;


    case REQUEST_ID(VID_REQ_FRAME)://发送一帧图像

        pos = FRAME_HDR_SZ + 4;
	
        size = cam_get_trans_frame(v, &rsp[pos]);//这样一来图像就被保存到协议要求的位置来了
            
        build_ack(rsp, (TYPE_SRSP << TYPE_BIT_POS) | SUBS_VID, id, 4, (__u8*)&size);//
        //这里就是要保存len,之前没有保存,没有这一步会出错
        net_send(c, rsp, pos + size);
        break;

    default:
        status = ERR_CMD_ID;
        break;
    }
	
    return status;
}

2012年10月15日星期一亲测可以下载 公开视频光盘目录结构 国嵌视频1.iso -学习方法与课程体系介绍(学前必看) -学习方法介绍.avi -国嵌嵌入式课程体系.pdf -嵌入式Linux学习方法.pdf -国嵌课程1-嵌入式入门体验班(上) -第1天(嵌入式系统概述) -国嵌体验入门班-1-1(嵌入式系统概述).avi -国嵌体验入门班-1-2(ARM概述).avi -国嵌体验入门班-1-3(嵌入式Linux概述).avi -国嵌体验入门班-1-4(2440开发板介绍).avi -国嵌体验入门班-1-5(软硬件环境搭建).avi -第2天(开发板快乐体验) -国嵌体验入门班-2-1(开发板系统安装).avi -国嵌体验入门班-2-1(开发板系统安装-Jlink方式).avi -国嵌体验入门班-2-1(开发板系统安装-并口方式).avi -国嵌体验入门班-2-2(裸机程序体验).avi -国嵌体验入门班-2-3(QT系统体验).avi -国嵌体验入门班-2-4(Android系统体验).avi 国嵌视频2.iso -国嵌课程1-嵌入式入门体验班(下) -第3天(Linux系统体验) -国嵌体验入门班-3-1(Linux定制安装).avi -国嵌体验入门班-3-2(Linux命令).avi -国嵌体验入门班-3-3(VI使用).avi -国嵌体验入门班-3-4(Linux系统管理).avi -国嵌体验入门班-3-5(Shell编程).avi -国嵌体验入门班-3-6(Qcd功能演示).avi -国嵌体验入门班-3-7(必修实验).avi -国嵌课程2-嵌入式Linux应用开发班 -第1天(编程基础) -国嵌应用班-1-1(GCC程序编译).avi -国嵌应用班-1-2(GDB程序调试).avi -国嵌应用班-1-3(makefile工程管理).avi -国嵌应用班-1-4(必修实验).avi -第2天(文件时间编程) -国嵌应用班-2-1(系统调用方式访问文件).avi -国嵌应用班-2-2(库函数访问文件).avi -国嵌应用班-2-3(时间编程).avi -国嵌应用班-2-4(必修实验).avi -第3天(多进程程序设计) -国嵌应用班-3-1(进程控制原理).avi -国嵌应用班-3-2(进程控制程序设计).avi -国嵌应用班-3-3(必修实验).avi -第4天(进程间通讯) -国嵌应用班-4-1(进程间通讯概述).avi -国嵌应用班-4-2(管道通讯).avi -国嵌应用班-4-3(信号通讯).avi -国嵌应用班-4-4(共享内存通讯).avi -国嵌应用班-4-5(必修实验).avi -第5天(进程间通讯) -国嵌应用班-5-1(消息队列).avi -国嵌应用班-5-2(信号量).avi -国嵌应用班-5-3(必修实验).avi -第6天(进程间通讯) -国嵌应用班-6-1(线程基础).avi -国嵌应用班-6-2(多线程程序设计).avi -国嵌应用班-6-3(必修实验).avi -第7天(网络编程) -国嵌应用班-7-1(Linux网络概述).avi -国嵌应用班-7-2(Linux网络编程基础).avi -国嵌应用班-7-3(TCP程序设计).avi -国嵌应用班-7-4(UDP网络程序设计).avi -国嵌应用班-7-5(并发服务器).avi -国嵌应用班-7-6(必修实验).avi 国嵌视频3.iso -国嵌课程3-ARM系统进阶班 -第1天(ARM系统开发基础) -ARM系统精讲班-1-1(ADS集成开发环境).avi -ARM系统精讲班-1-2(ARM工作模式).avi -ARM系统精讲班-1-3(ARM寄存器).avi -ARM系统精讲班-1-4(ARM寻址方式).avi -ARM系统精讲班-1-5(ARM汇编指令详解).avi -第2天(ARM系统开发基础) -ARM系统精讲班-2-1(ARM汇编指令详解).avi -ARM系统精讲班-2-2(ARM伪指令).avi -ARM系统精讲班-2-3((混合编程).avi -ARM系统精讲班-1-8(必修实验).avi -第3天(LED驱动程序设计) -ARM系统精讲班-2-1(GPIO).avi -ARM系统精讲班-2-2(LED控制程序设计).avi -ARM系统精讲班-2-3((LED闪烁).avi -第4天(LED与按键驱动程序设计) -ARM系统精讲班-4-1(ARM中断控制系统).avi -ARM系统精讲班-4-2(按键控制程序设计).avi -ARM系统精讲班-2-6(必修实验).avi -第5天(定时器与时钟驱动程序设计) -ARM系统精讲班-5-1(ARM时钟体系).avi -ARM系统精讲班-5-2(定时器驱动程序设计).avi -国嵌课程4(嵌入式LINUX内核驱动进阶班-上) -第1天(内核开发基础) -国嵌内核驱动进阶班-1-1(Linux内核简介).avi -国嵌内核驱动进阶班-1-2(Linux内核源代码).avi -国嵌内核驱动进阶班-1-3(Linux内核配置与编译).avi -国嵌内核驱动进阶班-1-4(Linux内核模块开发).avi -国嵌内核驱动进阶班-1-5(必修实验).avi -第2天(U-Boot移植) -国嵌内核驱动进阶班-2-1(嵌入式linux系统架构).avi -国嵌内核驱动进阶班-2-2(交叉工具链).avi -国嵌内核驱动进阶班-2-3(Bootloader介绍).avi -国嵌内核驱动进阶班-2-4(U-Boot介绍).avi -国嵌内核驱动进阶班-2-5(U-Boot命令).avi -国嵌内核驱动进阶班-2-6(U-Boot启动流程).avi -国嵌内核驱动进阶班-2-7(Uboot移植).avi -国嵌内核驱动进阶班-2-8(必修实验).avi 国嵌视频4.iso -国嵌课程4(嵌入式LINUX内核驱动进阶班-下) -第3天(内核开发基础) -国嵌内核驱动进阶班-3-1(嵌入式linux内核制作).avi -国嵌内核驱动进阶班-3-2(根文件系统制作).avi -国嵌内核驱动进阶班-3-3(内核启动流程).avi -国嵌内核驱动进阶班-3-4(嵌入式文件系统).avi -国嵌内核驱动进阶班-3-5(必修实验).avi -第4天(内存管理子系统) -国嵌内核驱动进阶班-4-1(Linux内存管理).avi -国嵌内核驱动进阶班-4-2(进程地址空间).avi -国嵌内核驱动进阶班-4-3(内核地址空间).avi -国嵌内核驱动进阶班-4-4(Linux内核链表).avi -国嵌内核驱动进阶班-4-5(Linux内核定时器).avi -国嵌内核驱动进阶班-2-7(Uboot移植).avi -国嵌内核驱动进阶班-2-8(必修实验).avi -第5天(进程管理子系统) -国嵌内核驱动进阶班-5-1(LINUX进程控制).avi -国嵌内核驱动进阶班-5-2(LINUX进程调度).avi -国嵌内核驱动进阶班-5-3(Linux系统调用).avi -国嵌内核驱动进阶班-5-4(Proc文件系统).avi -国嵌内核驱动进阶班-5-5(内核异常分析).avi -国嵌内核驱动进阶班-5-6(必修实验).avi -第6天(简单字符设备驱动程序设计) -国嵌内核驱动进阶班-6-1(LINUX驱动程序介绍).avi -国嵌内核驱动进阶班-6-2(字符设备驱动程序设计).avi -国嵌内核驱动进阶班-6-3(字符设备驱动程序实例分析).avi -国嵌内核驱动进阶班-6-4(竞争与互斥).avi -国嵌内核驱动进阶班-6-5(必修实验).avi -第7天(高级字符设备驱动程序设计) -国嵌内核驱动进阶班-7-1(Ioctl设备控制).avi -国嵌内核驱动进阶班-7-2(内核等待队列).avi -国嵌内核驱动进阶班-7-3(阻塞型字符设备驱动).avi -国嵌内核驱动进阶班-7-4(Poll设备方法).avi -国嵌内核驱动进阶班-7-5(自动创建设备文件).avi -国嵌内核驱动进阶班-7-6(必修实验).avi
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值