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
#include
#include
#include
#include
#include
#include
//#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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
}
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;
}