linux下视频采集服务器(UDP传输、多线程模式)

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 <libv4l1-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 video0i\n");
exit(1);
}
oldtick = clock();
if ((ioctl(video_fd, VIDIOCGCAP, &grab_cap)) < 0){
fprintf(stderr, "ioctl VIDEOCGCAP failed.\n");
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.\n");  
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.\n");  
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\n");  
exit(1);  
}  
else  {
fdg->video_fd=video_fd;
}   


if(pthread_create(&p_tid, NULL, producer, (void *)fdg))  {  
perror("pthrea p_tid1 error!\n");  
exit(1);  
}  


// free(fdg);  
// fdg=NULL;  


//网络部分  
if((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1)  {  
perror("creat socket error\n");  
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\n");  
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\n");  
exit(1);  
}  


arg=(struct ARG *)malloc(sizeof(struct ARG));  
if(arg==NULL)  {  
perror("ARG malloc error\n");  
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!\n");  
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;  

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux中,UDP多线程通信指的是使用UDP协议进行多线程之间的通信。 UDP(User Datagram Protocol)是一种无连接的传输协议,它不保证数据包的可靠性和顺序。与TCP(Transmission Control Protocol)不同,UDP不需要在通信前建立连接,因此在实现多线程通信时,UDP是一种更为轻量级的选择。 在Linux中,可以使用多线程来实现UDP通信。多线程通信可以通过创建多个线程来同时处理来自不同客户端的请求和响应。每个线程都可以独立处理接收和发送UDP数据包,利用多线程的并行性提高通信的效率。 在使用多线程进行UDP通信时,可以采用下面的步骤: 1. 创建一个UDP套接字(socket)用于通信。 2. 创建多个线程,并为每个线程分配一个独立的线程ID。 3. 在每个线程中,利用UDP套接字接收和发送数据包。 4. 线程同步:使用互斥锁(mutex)或信号量(semaphore)进行线程间的同步,以确保数据的完整性和一致性。 5. 释放资源:在通信结束后,关闭UDP套接字,销毁线程多线程通信可以实现高并发的UDP通信,适用于一些需要同时处理多个UDP请求和响应的场景,比如服务器端应用、实时传输等。 但是需要注意的是,UDP是一种不可靠的协议,不提供数据包的重传和顺序保证。因此,在进行UDP多线程通信时,需要在应用层面考虑数据的完整性和可靠性,比如使用校验和、重传机制等。同时,还需要注意线程间的同步问题,以避免数据的竞争和冲突。 总之,通过使用多线程进行UDP通信,可以提高通信的效率和并发处理能力,但需要注意协议本身的特点以及线程间的同步和数据一致性问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值