//多线程成功实例
#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 ***c; /* 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 ***c;
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);
***c = 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.***c = htonl(***c);
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
{
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))
{
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))
{
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))
{
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
{
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
{
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;
}