#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <assert.h>
#include <linux/videodev2.h>
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define portnumber 3333
int socket_fd;
#define USB_VIDEO "/dev/video0"
int cam_fd;
int buf_count;
typedef struct
{
void *start;
int length;
}BUFTYPE;
BUFTYPE *user_buf;
#define PIC_WIDTH 640
#define PIC_HEIGHT 320
//#define PIC_WIDTH 320
//#define PIC_HEIGHT 240
/***************************************************
structv4l2_capability
{
__u8 driver[16]; //驱动名字
__u8 card[32]; //设备名字
__u8 bus_info[32]; //设备在系统中的位置
__u32 version; //驱动版本号
__u32 capabilities; //设备支持的操作
__u32 reserved[4]; //保留字段
};
struct v4l2_fmtdesc
{
__u32 index; //要查询的格式序号,应用程序设置
enum v4l2_buf_type type; //帧类型,应用程序设置
__u32 flags; //是否为压缩格式
__u8 description[32]; //格式名称
__u32 pixelformat; //格式
__u32 reserved[4]; //保留
};
***************************************************/
int init_mmap(void)
{
int i = 0;
int ret;
struct v4l2_requestbuffers reqbuf;
struct v4l2_buffer buf;
bzero(&reqbuf,sizeof(reqbuf));
reqbuf.count = 4; //缓存数量,也就是说在缓存队列里保持多少张照片
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //数据流类型,必须永远是V4L2_BUF_TYPE_VIDEO_CAPTURE
reqbuf.memory = V4L2_MEMORY_MMAP; //或V4L2_MEMORY_USERPTR
ret = ioctl(cam_fd, VIDIOC_REQBUFS, &reqbuf); //请求Kernel分配Video Buffer
if( ret == -1 ) {
perror("VIDIOC_REQBUFS the device memory fail\n");
close(cam_fd);
exit(EXIT_FAILURE);
}
buf_count = reqbuf.count; //实际申请到的缓存数量
printf("Request the memory count:%d\n", reqbuf.count);
user_buf = (BUFTYPE *)calloc(reqbuf.count,sizeof(*user_buf));
if( user_buf == NULL ) {
fprintf(stderr,"Request the usr memory fail\n");
close(cam_fd);
exit(EXIT_FAILURE);
}
for(i=0; i<reqbuf.count; i++) {
bzero(&buf, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
ret = ioctl(cam_fd, VIDIOC_QUERYBUF, &buf); //查询申请到内核缓冲区的信息
if( ret == -1 ) {
perror("VIDIOC_QUERYBUF the device memory fail\n");
free(user_buf);
close(cam_fd);
exit(EXIT_FAILURE);
}
/*V4L2_buffer结构体的作用就相当于申请的缓冲帧的代理,
找缓冲帧的都要先问问它,通过它来联系缓冲帧,起了中间桥梁的作用。*/
user_buf[i].length = buf.length;
user_buf[i].start = mmap(NULL, buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, cam_fd, buf.m.offset); //NULL:start anywhere
if( MAP_FAILED == user_buf[i].start ) {
perror("Fail to mmap\n");
free(user_buf);
close(cam_fd);
exit(EXIT_FAILURE);
}
}
return 0;
}
void init_camer(void)
{
struct v4l2_fmtdesc fmt;
struct v4l2_capability cap;
struct v4l2_format stream_fmt;
int ret;
/*检查和设置设备属性*/
ret = ioctl(cam_fd, VIDIOC_QUERYCAP, &cap); //查询设备驱动的功能
if( ret < 0 ) {
perror("Unknown the video device\n");
close(cam_fd);
exit(EXIT_FAILURE);
}
//判断是否是一个视频捕捉设备
if( !(cap.capabilities & V4L2_BUF_TYPE_VIDEO_CAPTURE) ) {
printf("The Current device is not a video capture device\n");
close(cam_fd);
exit(EXIT_FAILURE);
}
//判断是否支持视频流形式
if( !(cap.capabilities & V4L2_CAP_STREAMING) ) {
printf("The Current device does not support streaming i/o\n");
close(cam_fd);
exit(EXIT_FAILURE);
}
//打印设备属性
printf("DriverName:%s\nDeviceName:%s\nBusInfo%s\nDeviceVersion:%u.%u.%u\n",
cap.driver, cap.card, cap.bus_info, (cap.version>>16)&0xff,
(cap.version>>8)&0xff, cap.version&0xff);
/*当前视频设备支持的视频格式*/
memset(&fmt, 0, sizeof(fmt));
fmt.index = 0; //先设置要查询的格式序号为0
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //
while( (ret = ioctl(cam_fd, VIDIOC_ENUM_FMT, &fmt)) == 0 ) { // 执行成功时,函数返回值为 0;
printf("index:%d\npixelformat = %c%c%c%c\ndescription = '%s'\n",
fmt.index, fmt.pixelformat&0xff, (fmt.pixelformat>>8)&0xff,
(fmt.pixelformat>>16)&0xff, (fmt.pixelformat>>24)&0xff,
fmt.description);
fmt.index++;
}
//设置帧格式
//设置摄像头采集数据格式,如设置采集数据的
//长,宽,图像格式(JPEG,YUYV,MJPEG等格式)
stream_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //数据流类型,必须永远是V4L2_BUF_TYPE_VIDEO_CAPTURE
stream_fmt.fmt.pix.width = PIC_WIDTH;
stream_fmt.fmt.pix.height = PIC_HEIGHT;
stream_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; //V4L2_PIX_FMT_MJPEG;V4L2_PIX_FMT_RGB32
stream_fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
if( ioctl(cam_fd,VIDIOC_S_FMT,&stream_fmt) == -1 ) {
perror("Fail to format config for YUYV\n");
close(cam_fd);
exit(EXIT_FAILURE);
}
/*注意:如果该视频设备驱动不支持你所设定的图像格式,视频驱动会重新修改
struct v4l2_format结构体变量的值为该视频设备所支持的图像格式,所以在程序设计中,
设定完所有的视频格式后,要获取实际的视频格式,要重新读取 struct v4l2_format
结构体变量。使用VIDIOC_G_FMT设置视频设备的视频数据格式,VIDIOC_TRY_FMT验证视频
设备的视频数据格式。 */
//检查是否支持某种帧格式
/*
stream_fmt.fmt.pix.pixelformat=V4L2_PIX_FMT_RGB32;
if( ioctl(cam_fd,VIDIOC_S_FMT,&stream_fmt) == -1 ) {
perror("Fail to format config for RGB32\n");
//close(cam_fd);
//exit(EXIT_FAILURE);
}
stream_fmt.fmt.pix.pixelformat=V4L2_PIX_FMT_MJPEG;
if( ioctl(cam_fd,VIDIOC_S_FMT,&stream_fmt) == -1 ) {
perror("Fail to format config for MJPEG\n");
//close(cam_fd);
//exit(EXIT_FAILURE);
}
*/
}
int start_capturing(void)
{
int i;
struct v4l2_buffer buf;
enum v4l2_buf_type type;
for(i=0; i<buf_count; i++) {
bzero(&buf, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
/*投放一个空的视频缓冲区到视频缓冲区输入队列中*/
if( ioctl(cam_fd, VIDIOC_QBUF, &buf) == -1 ) {
printf("index:%d\n", i);
perror("VIDIOC_QBUF for fail\n");
free(user_buf);
close(cam_fd);
exit(EXIT_FAILURE);
}
}
/*开始采集数据*/
type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //将缓冲帧放入队列
if( ioctl(cam_fd, VIDIOC_STREAMON, &type) == -1 ) {
printf("index:%d\n", i);
perror("VIDIOC_STREAMON for fail\n");
free(user_buf);
close(cam_fd);
exit(EXIT_FAILURE);
}
return 0;
}
//将采集好的数据放到文件中
int process_image(void *addr,int length)
{
int i;
int temp=0;
//将采集好的数据放到文件中
//sprintf(picture_name,"picture%d.jpg",num++);
/*if( (fp = fopen(picture_name,"w")) == NULL ) {
perror("Fail to fopen");
exit(EXIT_FAILURE);
} */
for(i=0; i<(PIC_WIDTH*PIC_HEIGHT/2048); i++) {
write(socket_fd, addr+i*2048, 2048);
}
printf("picture length:%d\n", length);
printf("picture size:%dKB\n", length/1024);
usleep(10000); //10ms
write(socket_fd, addr, 10); //结束信号
return 0;
}
void read_frame(void)
{
struct v4l2_buffer buf;
int i;
bzero(&buf,sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
//从队列中取缓冲区
if( ioctl(cam_fd, VIDIOC_DQBUF, &buf) == -1 )
{
perror("VIDIOC_DQBUF to fail");
free(user_buf);
close(cam_fd);
exit(EXIT_FAILURE);
}
assert(buf.index < buf_count); //ssert的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行。
//读取�
mini2440基于MPEG摄像头及SDL实现的远程监控代码
3星 · 超过75%的资源 需积分: 10 53 浏览量
2014-11-03
20:54:07
上传
评论 1
收藏 6KB ZIP 举报
冷冻的彩虹
- 粉丝: 66
- 资源: 20
最新资源
- python 链接ms sqlserver的通用文件
- FOC,即Field-Oriented Control.zip
- 3339-VB一款N-Channel沟道SOT23的MOSFET晶体管参数介绍与应用说明
- QT6实现音频输出功能
- DSC_0019_BURST20240210145321463.JPG
- 涉及c语言面试题及答案
- DSC_0001_BURST20240224182755811.JPG
- 3338-VB一款N-Channel沟道SOT23的MOSFET晶体管参数介绍与应用说明
- 欢乐斗地主python项目游戏源码下载
- 3324-VB一款N-Channel沟道SOT23的MOSFET晶体管参数介绍与应用说明
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈