www.pudn.com > dxc.rar > dxc.c, change:2007-09-01,size:9806b
//多线程成功实例
#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)
{
fprintf(stderr, "can not open video0");//\u6253\u5f00\u6444\u50cf\u5934
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\nThe 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;
}