#include "my.h"
int main()
{
char buff[1024];
client_fd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(client_fd < 0){
perror("socket");
exit(EXIT_FAILURE);
}
struct sockaddr_in server_addr;
memset(&server_addr,0,sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(7777);
server_addr.sin_addr.s_addr = inet_addr("10.5.19.10");
int ret = connect(client_fd,(struct sockaddr *)&server_addr,sizeof(struct sockaddr));
if(ret < 0){
perror("connect");
exit(EXIT_FAILURE);
}
pthread_mutex_init(&mut,NULL);
pthread_cond_init(&image_cond,NULL);
pthread_cond_init(&info_cond,NULL);
memset(&recv_thread,0,sizeof(image_thread));
if((ret = pthread_create(&recv_thread,NULL,recv_thread_function,(void *)&client_fd)) != 0)
printf("revb_thread create error\n");
else
printf("recv_thread create success\n");
memset(&image_thread,0,sizeof(image_thread));
if((ret = pthread_create(&image_thread,NULL,image_thread_function,(void *)&client_fd)) != 0)
printf("image_thread create error\n");
else
printf("image_thread create success\n");
memset(&info_thread,0,sizeof(image_thread));
if((ret = pthread_create(&info_thread,NULL,info_thread_function,(void *)&client_fd)) != 0)
printf("info_thread create error\n");
else
printf("info_thread create success\n");
pthread_join(recv_thread,NULL);
pthread_join(image_thread,NULL);
pthread_join(info_thread,NULL);
close(client_fd);
}
void *recv_thread_function(void *arg)
{
int fd = *(int *)arg;
char buff[1024];
struct sockaddr_in server_addr;
memset(&server_addr,0,sizeof(server_addr));
int len = sizeof(struct sockaddr);
while(1){
FD_ZERO(&read_fds);
FD_SET(client_fd,&read_fds);
max_fds = client_fd + 1;
if((select(max_fds,&read_fds,NULL,NULL,NULL))<0){
perror("select");
exit(EXIT_FAILURE);
}
if(FD_ISSET(client_fd,&read_fds)){
memset(buff,0,sizeof(buff));
recv(client_fd,buff,sizeof(buff),0);
if(strcmp(buff,"image_start") == 0){
pthread_mutex_lock(&mut);
image_flag = 1;
pthread_cond_signal(&image_cond);
pthread_mutex_unlock(&mut);
}
else if(strcmp(buff,"image_end") == 0){
image_flag = 0;
v4l2_video_off();
v4l2_munmap();
}
else if(strcmp(buff,"cpu_info") == 0){
pthread_mutex_lock(&mut);
info_flag = 1;
pthread_cond_signal(&info_cond);
pthread_mutex_unlock(&mut);
}
}
}
}
void *image_thread_function(void *arg)
{
int fd = *(int *)arg;
v4l2_open();
v4l2_get_capability();
v4l2_support_format();
set_v4l2_format();
set_v4l2_streamparm();
v4l2_init_mmap();
v4l2_video_on();
while(1){
pthread_mutex_lock(&mut);
if(image_flag != 1)
pthread_cond_wait(&image_cond,&mut);
else{
//采集视频并传输
grap_video_loop();
image_flag = 0;
}
pthread_mutex_unlock(&mut);
}
}
void *info_thread_function(void *arg)
{
int fd = *(int *)arg;
struct dev_info dev;
while(1){
memset(&dev,0,sizeof(dev));
pthread_mutex_lock(&mut);
if(info_flag != 1)
pthread_cond_wait(&info_cond,&mut);
else{
//采集设备信息
get_devinfo(&dev);
//send 设备信息
send(client_fd,(char *)&dev,sizeof(dev),0);
info_flag = 0;
}
pthread_mutex_unlock(&mut);
}
}
void v4l2_open()
{
if((fd = open("/dev/video0",O_RDWR)) < 0){
perror("v4l2 open error\n");
exit(EXIT_FAILURE);
}
}
void v4l2_get_capability()
{
struct v4l2_capability cap;
if(ioctl(fd,VIDIOC_QUERYCAP,&cap)<0){
perror("v4l2 get capability error\n");
exit(EXIT_FAILURE);
}
// printf("drive name %s\n",cap.driver);
// printf("dev name %s\n",cap.card);
}
void v4l2_support_format()
{
struct v4l2_fmtdesc fmtdesc;
memset(&fmtdesc,0,sizeof(fmtdesc));
fmtdesc.index = 0;
fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
while((ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc)) == 0)
fmtdesc.index++;
// printf("pixelformat = %c%c%c%c\n",fmtdesc.pixelformat & 0xff,(fmtdesc.pixelformat >> 8)&0xff,(fmtdesc.pixelformat >> 16)&0xff,(fmtdesc.pixelformat >> 24)&0xff);
// printf("description %s\n",fmtdesc.description);
}
int set_v4l2_streamparm()
{
struct v4l2_streamparm parm;
memset(&parm,0,sizeof(parm));
parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if(ioctl(fd,VIDIOC_G_PARM,&parm)<0){
perror("v4l2 get parm error\n");
exit(EXIT_FAILURE);
}
printf("denominator %d\n",parm.parm.capture.timeperframe.denominator);
parm.parm.capture.timeperframe.numerator = 1;
parm.parm.capture.timeperframe.denominator = 30;
parm.parm.capture.capturemode = 0; //设置为高清
if(ioctl(fd,VIDIOC_S_PARM,&parm)<0){
perror("v4l2 set parm error\n");
exit(EXIT_FAILURE);
}
return 0;
}
int set_v4l2_format()
{
struct v4l2_format fmt;
memset(&fmt,0,sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if(ioctl(fd,VIDIOC_G_FMT,&fmt)<0){
perror("v4l2 get format error\n");
exit(EXIT_FAILURE);
}
fmt.fmt.pix.width = 320;
fmt.fmt.pix.height = 240;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
if(ioctl(fd,VIDIOC_S_FMT,&fmt)<0){
perror("v4l2 set format error\n");
exit(EXIT_FAILURE);
}
if(ioctl(fd,VIDIOC_G_FMT,&fmt)<0){
perror("v4l2 get format error\n");
exit(EXIT_FAILURE);
}
return 0;
}
int v4l2_init_mmap()
{
struct v4l2_requestbuffers req;
struct v4l2_buffer buf;
memset(&req,0,sizeof(req));
req.count = 4;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if(ioctl(fd,VIDIOC_REQBUFS,&req) < 0){
perror("v4l2 local memory error\n");
exit(EXIT_FAILURE);
}
buffers = calloc(req.count,sizeof(VideoBuffer));
for(numBufs=0;numBufs<req.count;numBufs++)
{
memset(&buf,0,sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = numBufs;
//读取缓存
if(ioctl(fd,VIDIOC_QUERYBUF,&buf) < 0){
perror("v4l2 VIDIOC_QUERYBUF error\n");
exit(EXIT_FAILURE);
}
buffers[numBufs].length = buf.length;
//转换成相对地址
buffers[numBufs].start = mmap(NULL,buf.length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,buf.m.offset);
}
return 0;
}
int v4l2_grab_frame()
{
struct v4l2_buffer buf;
memset(&buf,0,sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
//读取缓存
if(ioctl(fd,VIDIOC_DQBUF,&buf) < 0){
perror("v4l2 VIDIOC_DQBUF error\n");
exit(EXIT_FAILURE);
}
assert(buf.index < numBufs);
process_video_image(buffers[buf.index].start,buffers[buf.index].length);
//重新加入缓存队列
if(ioctl(fd,VIDIOC_QBUF,&buf) < 0){
perror("v4l2 VIDIOC_QBUF error\n");
exit(EXIT_FAILURE);
}
return 1;
}
int v4l2_video_on()
{
unsigned int i;
enum v4l2_buf_type type;
for(i=0;i<4;i++){
struct v4l2_buffer buf;
memset(&buf,0,sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if(ioctl(fd,VIDIOC_QBUF,&buf) < 0){
perror("v4l2 VIDIOC_QBUF error\n");
exit(EXIT_FAILURE);
}
}
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if(ioctl(fd,VIDIOC_STREAMON,&type) < 0){
perror("v4l2 VIDIOC_STREAMON error\n");
exit(EXIT_FAILURE);
}
printf("video on\n");
return 0;
}
void process_video_image(void *p,unsigned int size)
{
//发送给服务器
int nsendbytes = send(client_fd,p,size,0);
printf("send ok\n");
}
void grap_video_loop()
{
while(1){
fd_set fds;
struct timeval tv;
int ret;
FD_ZERO(&fds);
FD_SET(fd,&fds);
if((ret=select(fd+1,&fds,NULL,NULL,NULL))<0){
perror("select\n");
exit(EXIT_FAILURE);
}
if(v4l2_grab_frame())
break;
}
}
int v4l2_video_off()
{
enum v4l2_buf_type type;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if(ioctl(fd,VIDIOC_STREAMOFF,&type) < 0){
perror("v4l2 VIDIOC_STREAMON error\n");
exit(EXIT_FAILURE);
}
}
void v4l2_munmap()
{
for(numBufs=0;numBufs<4;numBufs++)
{
munmap(buffers[numBufs].start,buffers[numBufs].length);
}
close(fd);
}
void get_devinfo(struct dev_info *dev)
{
float