linux下视频采集服务器(UDP传输、多线程模式)
来源:互联网 发布:淘宝倒计时怎么搞 编辑:程序博客网 时间:2024/05/17 02:24
linux下多线程网络编程,实现arm9视频采集和网络发送jpeg数据,使用udp协议,自己写的,搞了好几天!linux下的多线程比较复杂易出错。
linux network under the multi-threaded programming, video capture and realize ARM9 send jpeg data network, using udp protocol, wrote it myself, engaged in for several days! linux under the more complicated multi-threaded, error-prone.
- //多线程成功实例
- #include <strings.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <stdarg.h>
- #include <linux/types.h>
- #include <linux/videodev.h>
- #include <pthread.h>
- #include <semaphore.h>
- #include <sys/types.h>
- #include <sys/mman.h>
- #include <sys/ioctl.h>
- #include <sys/stat.h>
- #include <sys/time.h>
- #include <sys/file.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <time.h>
- #include <string.h>
- #include <netdb.h>
- #include <arpa/inet.h>
- #include <sys/times.h>
- #include <netinet/in.h>
- #include <sys/socket.h>
- #include <sys/param.h>
- #include <ctype.h>
- #include <sys/utsname.h>
- #define BUFSIZE 6
- #define DATA 32*1024
- #define PORT 5000
- #define RTP_HDR_SZ 12
- #define VIDEO_PALETTE_JPEG 21
- unsigned char buf[BUFSIZE+2][DATA];
- int head,tail;
- sem_t writen;
- sem_t readn;
- struct ARG{int sockfd;
- int sin_size;
- struct sockaddr_in client;
- };
- struct FDG{
- int video_fd;
- };
- typedef unsigned char u_int8;
- typedef unsigned short u_int16;
- int get_jpegsize (unsigned char *buf, int insize);
- double tdbl(struct timeval *a);
- pthread_mutex_t buffer_mutex=PTHREAD_MUTEX_INITIALIZER;
- static void *producer(void *fdg)
- {
- struct FDG *vd;
- int video_fd;
- if(sizeof(fdg)!=sizeof(struct FDG))
- {
- perror("producer arg error");
- exit(1);
- }
- else
- {
- vd=(struct FDG *)fdg;
- video_fd=vd->video_fd;
- free(fdg);
- fdg=NULL;
- }
- for( ; ; )
- {
- sem_wait(&writen);//减少可读的资源数
- pthread_mutex_lock(&buffer_mutex);//进入互斥区
- // memset(buf[head], 's', 20);
- read(video_fd, buf[head], DATA);
- head=(head+1) % BUFSIZE;
- pthread_mutex_unlock(&buffer_mutex);//离开互斥区
- sem_post(&readn);//增加可读资源数
- // sleep(0.0001);
- }
- }
- static void *consumer(void *arg)
- {
- int sockfd;
- int sin_size;
- int jpegsize;
- struct sockaddr_in client;
- struct ARG *info;
- typedef struct {
- unsigned int version:2;/* protocol version */
- unsigned int p:1; /* padding flag */
- unsigned int x:1; /* header extension flag */
- unsigned int cc:4; /* CSRC count */
- unsigned int m:1; /* marker bit */
- unsigned int pt:7; /* payload type */
- unsigned int seq:16; /* sequence number */
- unsigned int ts; /* timestamp */
- unsigned int ssrc; /* synchronization source */
- } rtp_hdr_t;
- struct timeval start;
- rtp_hdr_t rtphdr;
- u_int8 *jpeg_data;
- u_int8 *packet_buf;
- unsigned int ts;
- unsigned int ssrc;
- u_int8 *ptr;
- u_int8 frame,bframe;
- int bytes_left ;//jpeg数据总长度
- int data_len,packetsize;//packetsize变量
- info=( struct ARG *)arg;
- if(info->sockfd<0)
- {
- perror("error error");
- exit(1);
- }
- if(info->sin_size!=16)
- {
- perror("err error");
- exit(1);
- }
- sockfd=info->sockfd;
- sin_size=info->sin_size;
- memcpy(&client,&info->client,sizeof(info->client));
- free(arg);
- arg=NULL;
- packetsize=RTP_HDR_SZ+2050;
- packet_buf = (u_int8 *)calloc(packetsize, sizeof(u_int8));
- jpeg_data= (u_int8 *) malloc(DATA);
- for(;;)
- {
- frame=0;
- gettimeofday(&start, 0);
- ts = (unsigned int)(tdbl(&start)*1000);
- ssrc = 125;
- /* Initialize RTP header*/
- rtphdr.version = 2;
- rtphdr.p = 0;
- rtphdr.x = 0;
- rtphdr.cc = 0;
- rtphdr.m = 0;
- rtphdr.pt = 40;
- rtphdr.seq = 1;
- rtphdr.ts = htonl(ts);
- rtphdr.ssrc = htonl(ssrc);
- sem_wait(&readn);//减少可读的资源数
- pthread_mutex_lock(&buffer_mutex);//进入互斥区
- jpegsize=get_jpegsize(buf[tail],DATA);
- if(jpegsize!=-1)
- {
- memcpy(jpeg_data,buf[tail],jpegsize);
- }
- tail=(tail+1) % BUFSIZE;
- pthread_mutex_unlock(&buffer_mutex);//离开互斥区
- sem_post(&writen);//增加可读资源数
- bytes_left = jpegsize;
- while (bytes_left > 0)
- {
- ptr = packet_buf + RTP_HDR_SZ;
- bframe=frame;
- data_len = packetsize - (ptr - packet_buf)-2;//每一分片大小
- if (data_len >= bytes_left) //当为最后一个分片时
- {
- data_len = bytes_left;
- rtphdr.m = 1;
- bframe=255;
- data_len=jpegsize%2048;
- }
- *ptr=bframe; ptr++;
- *ptr=frame; ptr++;
- rtphdr.seq = htons(rtphdr.seq);
- memcpy(packet_buf, &rtphdr, RTP_HDR_SZ);
- memcpy(ptr, jpeg_data + frame*2048, data_len);
- if(sendto(sockfd,packet_buf,(ptr - packet_buf) + data_len,
- 0,(struct sockaddr *)&client,sin_size)<0)
- {
- perror(" sendto error");
- }
- frame++;
- bytes_left -= 2048;
- rtphdr.seq = ntohs(rtphdr.seq);
- rtphdr.seq++;
- }
- sleep(0.0001);
- }
- free(packet_buf);
- free(jpeg_data);
- pthread_exit(NULL);
- }
- int main()
- {
- clock_t oldtick,newtick;
- float time1 ;
- static int vf=0;
- int i;
- clock_t totalold,totalnew;
- int video_fd;
- struct video_capability grab_cap;
- int width = 320;
- int height = 240;
- struct video_picture grab_pic;
- struct video_mmap grab_map;
- struct video_mbuf grab_buf;
- int sockfd;
- int sin_size;
- struct sockaddr_in client;
- struct sockaddr_in server;
- char msg[100];
- struct ARG *arg;
- struct FDG *fdg;
- pthread_t p_tid;
- pthread_t c_tid;
- head=0;
- tail=0;
- for(i=0; i<BUFSIZE+2; i++)
- {
- bzero(buf[i],DATA);
- }
- sem_init(&writen,0,BUFSIZE);
- sem_init(&readn,0,0);
- //数据采集………………………………………………
- loop:
- totalold = clock();
- video_fd = open("/dev/video0", O_RDWR);
- if (video_fd == -1)
- {
- ///u6253/u5f00/u6444/u50cf/u5934
- fprintf(stderr, "can not open video0");
- exit(1);
- }
- oldtick = clock();
- if ((ioctl(video_fd, VIDIOCGCAP, &grab_cap)) < 0)
- {
- fprintf(stderr, "ioctl VIDEOCGCAP failed.");
- exit(1);
- }
- newtick = clock();
- time1 = (double)(newtick - oldtick)/ CLOCKS_PER_SEC;
- printf("/n%f second is take to ioctl VIDEOCGCAP /n",time1);
- printf("The VideoCap Name: %s/n", grab_cap.name);
- printf("The hannels: %d/n", grab_cap.channels);
- printf("The Audios: %d/n", grab_cap.audios);
- printf("The maxwidth: %d, maxheight: %d, minwidth %d, minheight: %d/n",
- grab_cap.maxwidth, grab_cap.maxheight,
- grab_cap.minwidth, grab_cap.minheight);
- oldtick = clock();
- if ((ioctl(video_fd, VIDIOCGPICT, &grab_pic)) < 0)
- {
- fprintf(stderr, "ioctl VIDIOCGPICT failed.");
- exit(1);
- }
- newtick = clock();
- time1 = (double)(newtick - oldtick)/ CLOCKS_PER_SEC;
- printf("/n%f second is take to ioctl VIDIOCGPICT /n",time1);
- printf("The brightness: %d/nThe hue: %d/nThe colour: %d/n
- The contrast:%d/nThe whiteness: %d/nThe depth: %d/nThe palette: %d/n",
- grab_pic.brightness, grab_pic.hue, grab_pic.colour, grab_pic.contrast,
- grab_pic.whiteness, grab_pic.depth, grab_pic.palette);
- oldtick = clock();
- if ((ioctl(video_fd, VIDIOCGMBUF, &grab_buf)) < 0)
- {
- fprintf(stderr, "ioctl VIDIOCGMBUF, failed.");
- exit(1);
- }
- newtick = clock();
- time1 = (double)(newtick - oldtick)/ CLOCKS_PER_SEC;
- printf("/n%f second is take to ioctl VIDIOCGMBUF /n",time1);
- printf("The mapping size:%d/nThe mapping frames:%d/nThe mapping offset %d/n",
- grab_buf.size, grab_buf.frames, grab_buf.offsets);
- printf("The mapping size: %d nihao/n",grab_buf.size);
- grab_map.width = width;
- grab_map.height = height;
- grab_map.format = VIDEO_PALETTE_JPEG;
- grab_map.frame = 0;
- if(vf==0)
- {
- vf=vf+1;
- close(video_fd);
- goto loop;
- }
- fdg=(struct FDG *)malloc(sizeof(struct FDG));
- if(fdg==NULL)
- {
- perror("fdg malloc error");
- exit(1);
- }
- else {fdg->video_fd=video_fd;}
- if(pthread_create(&p_tid, NULL, producer, (void *)fdg))
- {
- perror("pthrea p_tid1 error!");
- exit(1);
- }
- // free(fdg);
- // fdg=NULL;
- //网络部分
- if((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1)
- {
- perror("creat socket error");
- exit(1);
- }
- bzero(&server,sizeof(server));
- server.sin_family=AF_INET;
- server.sin_port=htons(PORT);
- server.sin_addr.s_addr=htonl(INADDR_ANY);
- if(bind(sockfd,(struct sockaddr *)&server,sizeof(struct sockaddr))==-1){
- perror("bind error");
- exit(1);}
- sin_size=sizeof(struct sockaddr_in);
- while(1)
- {
- if((recvfrom(sockfd,msg,100,0,(struct sockaddr *)&client,&sin_size))<0)
- {
- perror("recv error");
- exit(1);
- }
- arg=(struct ARG *)malloc(sizeof(struct ARG));
- if(arg==NULL)
- {
- perror("ARG malloc error");
- exit(1);
- }
- else {
- arg->sockfd=sockfd;
- arg->sin_size=sin_size;
- memcpy((void *)&arg->client,&client,sizeof(client));
- }
- if(pthread_create(&c_tid,NULL,consumer,(void *)arg))
- {
- perror("pthread c_tid error!");
- exit(1);
- }
- // free(arg);
- // arg=NULL;
- }
- pthread_join(p_tid,NULL);
- //pthread_join(p_tid2,NULL);
- pthread_join(c_tid,NULL);
- close(video_fd);
- close(sockfd);
- return 0;
- }
- //获得JPEG图片大小
- int get_jpegsize (unsigned char *buf, int insize)
- {
- int i,flg=0,fc=0,fd=0,nd=0,k;
- if((buf[0]==0xFF) && (buf[1]==0xD8)&& (buf[2]==0xFF) && (buf[3]==0xDB))
- {
- for ( k= 0 ; k< 590; k++)
- {
- if(buf[k]== 0x0D)nd++;
- if ((buf[k]== 0xFF) && (buf[k+1] == 0xC4))
- {
- flg++;
- fc=k+1;
- }
- if ((buf[k]== 0xFF) && (buf[k+1] == 0xDA))
- {
- fd=k+1;
- flg++;
- break;
- }
- }
- if((flg==2)&&(fc==137)&&(fd==576)&&(nd<=5))
- {
- for ( i= 1024*2 ; i< insize; i++)
- {
- if ((buf[i] == 0xFF) && (buf[i+1] == 0xD9)) return i+2;
- }
- }
- }
- return -1;
- }
- double tdbl(struct timeval *a)
- {
- return a->tv_sec + a->tv_usec/1e6;
- }
- linux下视频采集服务器(UDP传输、多线程模式)
- linux下视频采集服务器(UDP传输、多线程模式)
- linux下视频采集服务器(UDP传输、多线程模式)
- QT linux v4l2下多线程视频采集播放
- Linux下的基于udp传输的语音采集和播放
- linux下视频采集代码
- 基于qt的多线程视频采集与传输
- linux下视频传输测试
- linux下视频传输测试
- 基于嵌入式Linux的视频图像采集与传输
- 基于嵌入式Linux的视频图像采集与传输
- 基于嵌入式Linux的视频图像采集与传输
- Linux下UDP传输文件示例
- LINUX下实现UDP传输文件
- DM6467 之视频采集(linux)下mmap
- 嵌入式linux环境下的视频采集(V4L2)
- TCP/UDP传输摄像头采集的数据(opencv)
- 多线程UDP传输协议
- Linux后台运行MATLAB命令
- PeopleTools Security
- Matlab中的并交子集运算
- ORACLE函数大全(整理转帖)
- android多点触摸(multi touch)---待续
- linux下视频采集服务器(UDP传输、多线程模式)
- matlab随机抽样
- ORA-01536: 超出表空间 'XX' 的空间限额 (转载)
- 在tomcat上运行php
- SQL Server 函数大全(整理转帖)
- 关注2010中国移动开发者大会android技术的生命周期
- VsFlex7.Ocx控件的注册说明
- javascript模拟时钟 ——我的第一篇博客
- Perl入门(数组)