main.h文件
#ifndef MAIN_H
#define MAIN_H
#define bool int
#define true 1
#define false 0
typedef struct remote_client
{
bool state ;
int qulity ;
int hntcpsockfd ;
struct sockaddr_in add_client ;
char *recvbuf ;
}client ;
#endif
main.c文件
#include "server_udpsocket.h"
#include "capture.h"
#include "server_tcpsocket.h"
pthread_mutex_t capture_lock = PTHREAD_MUTEX_INITIALIZER ;
//pthread_cond_t cnt_nonzero ;
int cnt ;
//main
int main()
{
//start capture
if(!tcpsocket_Run(&capture_lock))
{
printf("MAIN:start tcpsocket thread failed!/n") ;
return -1 ;
}
if(!capture_Run(&capture_lock))
{
printf("MAIN:start capture thread failed !/n") ;
return -1 ;
}
//start transportation thread
if(!udpsocket_Run(&capture_lock))
{
printf("MAIN:start udpsocket thread failed!/n") ;
return -1 ;
}
//
pthread_join(hthread_tcpsocket,NULL) ;
pthread_join(hthread_udpsocket,NULL) ;//
pthread_join(hthread_capture,NULL) ;//
return 0;
}
capture.h文件
#ifndef _CAPTURE_H_
#define _CAPTURE_H_
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/videodev.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <linux/types.h>
#include <jpeglib.h>
#include <setjmp.h>
#define bool int
#define true 1
#define false 0
//#include <sys/times.h>
int errno;
extern pthread_t hthread_capture ;//capture thread!
extern int quality ;
//extern pthread_cond_t cnt_nonzero ;
extern int cnt ;
bool open_video() ;//open video
char *NextFrame() ;//capture one frame data
void close_video() ;//close video and free resource
bool capture_Run(pthread_mutex_t *capture_lock) ;//create capture thread
void *thread_capture(pthread_mutex_t *capture_lock) ;//capture thread function
void init_encode() ;//initialise the parametre of encoder
void close_encode() ;//Destroy encoder
bool encode_jpeg(char *lpbuf,pthread_mutex_t *capture_lock) ;//jpeg encode
#endif
capture.c文件
#include "capture.h"
//定义视频扑捉相应的结构体
struct video_mbuf v_bufferproperty ;//此结构体利用mmap进行映射帧信息
//实际上是输入到摄像头存储器缓冲区的帧信息
struct video_mmap *v_memorymap ;//用于内存映射
struct video_picture v_imageproperty ;//采集图像的各种属性
struct video_capability v_capability ;//摄像头的基本信息
char *memorymap ;
int bufferIndex=0 ;
//struct v4l vd ;//vidoe4linux
//define the variable
char* deviceName = "/dev/v4l/video0";
char *fname="temp.jpg" ;
int deviceHandle = 0;
int width = 320;
int height = 240;
int depth=16;
int palette=VIDEO_PALETTE_RGB24;
int quality = 40 ;
//conrresponding to thread
pthread_t hthread_capture ;//capture thread!
//variable corresponding to jpeg encoder
struct jpeg_compress_struct cinfo ;//
struct jpeg_error_mgr jerr ;//
JSAMPROW row_pointer[1] ;
int row_stride ;
char *buffer=NULL ;
FILE *fptr_jpg=NULL ;
bool open_video()
{
int ret =-1 ;
//open device
deviceHandle=open(deviceName,O_RDWR) ;//read and write mode
if(deviceHandle==-1)
{
printf("Capture:Open failed!/n") ;
printf("Mesg:%s/n",sys_errlist[errno]) ;
return false ;
}
//get the property of capture
ret=ioctl(deviceHandle,VIDIOCGCAP,&v_capability) ;
if(ret == -1)
{
printf("Capture:obtain capability failed!/n") ;
printf("Mesg:%s/n",sys_errlist[errno]) ;
close(deviceHandle) ;//关闭设备文件
return false ;
}
if((v_capability.type&VID_TYPE_CAPTURE)==0)
{
printf("Capture:this device can't capture video to memory!/n") ;
close(deviceHandle) ;//关闭设备文件
return false ;
}
//print the information of capture
printf(v_capability.name);
printf(", Type:%d/n",v_capability.type);
printf("Maxwidth:%d,Maxheight:%d/n",v_capability.maxwidth ,v_capability.maxheight);
printf("Minwidth:%d,Minheight:%d/n",v_capability.minwidth,v_capability.minheight);
printf("Channels:%d,Audios:%d/n",v_capability.channels,v_capability.audios) ;
//get property of the picture that captured
ret=ioctl(deviceHandle,VIDIOCGPICT,&v_imageproperty) ;
if(ret==-1)
{
printf("Capture:obtain picture property failed!/n") ;
printf("Mesg:%s/n",sys_errlist[errno]) ;
close(deviceHandle) ;//关闭设备文件
return false ;
}
v_imageproperty.palette=palette ;
v_imageproperty.depth=depth ;
//set property of the picture that capured
ret = ioctl(deviceHandle,VIDIOCSPICT,&v_imageproperty) ;
if(ret==-1)
{
printf("Capture:Set the property of image failed!/n") ;
printf("Mesg:%s/n",sys_errlist[errno]) ;
close(deviceHandle) ;//关闭设备文件
return false ;
}
//printf("test!/n") ;
//get the property of map buffer
ret=ioctl(deviceHandle,VIDIOCGMBUF,&v_bufferproperty) ;
if(ret==-1)
{
printf("Capture:Get the property of map buffer failed!/n") ;
printf("Mesg:%s/n",sys_errlist[errno]) ;
close(deviceHandle) ;//关闭设备文件
return false ;
}
//map
memorymap=(char *)mmap(0,v_bufferproperty.size,PROT_READ | PROT_WRITE, MAP_SHARED, deviceHandle, 0);
if((int)memorymap==-1)
{
printf("Capture:Mmap failed!/n") ;
printf("Mesg:%s/n",sys_errlist[errno]) ;
close(deviceHandle) ;//关闭设备文件
return false ;
}
//allocate video_map structures
v_memorymap=(struct video_mmap*)(malloc(v_bufferproperty.frames*sizeof(struct video_mmap))) ;
if(v_memorymap==NULL)
{
printf("Capture:malloc failed!/n") ;
printf("Mesg:%s/n",sys_errlist[errno]) ;
close(deviceHandle) ;//关闭设备文件
return false ;
}
ret=0 ;
// printf("test!/n") ;
while(ret<v_bufferproperty.frames)
{
v_memorymap[ret].frame=ret ;
v_memorymap[ret].width=width ;
v_memorymap[ret].height=height ;
v_memorymap[ret].format=palette ;
++ret ;
}
ret=0 ;
while(ret<(v_bufferproperty.frames-1))
{
if (ioctl (deviceHandle, VIDIOCMCAPTURE, &v_memorymap[bufferIndex]) == -1)
{ // capture request failed
printf("Capture:capture failed!/n") ;
printf("Mesg:%s/n",sys_errlist[errno]) ;
close(deviceHandle) ;//关闭设备文件
return false ;
}
++ret ;
}
bufferIndex=v_bufferproperty.frames-1 ;
return true ;
}
//注意bufferIndex标明当前是第几帧
char* NextFrame()
{
// send a request to begin capturing to the currently indexed buffer
if (ioctl (deviceHandle, VIDIOCMCAPTURE, &v_memorymap[bufferIndex]) == -1)
{ // capture request failed
printf("Capture:capture failed!/n") ;
printf("Mesg:%s/n",sys_errlist[errno]) ;
close(deviceHandle) ;//关闭设备文件
exit(0) ;
}
// move bufferIndex to the next frame
++ bufferIndex;
if (bufferIndex == v_bufferproperty.frames)
{ // bufferIndex is indexing beyond the last buffer
// set it to index the first buffer
bufferIndex = 0;
}
// wait for the currently indexed frame to complete capture
if (ioctl (deviceHandle, VIDIOCSYNC, &v_memorymap[bufferIndex]) == -1)
{ // sync request failed
printf("Capture:video sync failed!/n") ;
printf("Mesg:%s/n",sys_errlist[errno]) ;
close(deviceHandle) ;//关闭设备文件
exit(0) ;
}
// return the address of the frame data for the current buffer index
return (memorymap + v_bufferproperty.offsets[bufferIndex]);
}
//free resource
void close_video()
{
//free the video_mmap structure
free(v_memorymap) ;
//unmap the capture memory
munmap(memorymap,v_bufferproperty.size) ;
//Close device file
close(deviceHandle) ;
}
//create thread
bool capture_Run(pthread_mutex_t *capture_lock)
{
int ret=-1 ;
//注意在linux下使用线程,在编译链接时要加lpthread
ret=pthread_create(&hthread_capture,PTHREAD_CREATE_JOINABLE,(void *)thread_capture,capture_lock) ;
if(ret==-1)
{
printf("Capture:create capture thread failed!/n") ;
return false ;
}
return true ;
}
//thread function
void *thread_capture(pthread_mutex_t *capture_lock)
{
char *temp=NULL ;
if(!open_video())
{
goto exit ;
}
init_encode() ;//
while(1)
{
temp=NextFrame() ;
if(!encode_jpeg(temp,capture_lock))
{
goto exit ;
}
}
exit:
close_encode() ;
close_video() ;
printf("Capture:capture thread exited !/n") ;
}
void init_encode()
{
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
jpeg_set_defaults(&cinfo);
row_stride = width * 3;
buffer=malloc(row_stride) ; //allocate memory for encoder ,note free after
}
void close_encode()
{
//destrory encoder ;
jpeg_destroy_compress(&cinfo);
free(buffer) ;//release jpeg encode buffer
}
bool encode_jpeg(char *lpbuf,pthread_mutex_t *capture_lock)
{
int x ;
pthread_mutex_lock(capture_lock) ;//open lock
fptr_jpg = fopen (fname,"wb");//注意这里为什么用fopen而不用open
if(fptr_jpg==NULL)
{
printf("Encoder:open file failed!/n") ;
printf("Mesg:%s/n",sys_errlist[errno]) ;
return false ;
}
jpeg_stdio_dest(&cinfo, fptr_jpg);
jpeg_set_quality(&cinfo, quality,true);
//begin compress
jpeg_start_compress(&cinfo, TRUE);
row_pointer[0] = buffer;
while (cinfo.next_scanline < height)
{
for (x = 0; x < row_stride; x+=3)
{
buffer[x] = lpbuf[x+2];
buffer[x+1] = lpbuf[x+1];
buffer[x+2] = lpbuf[x];
}
jpeg_write_scanlines (&cinfo, row_pointer, 1);//critical
lpbuf += row_stride;
}
//finish compress
jpeg_finish_compress(&cinfo);
fclose(fptr_jpg);
//unlock
cnt=1 ;
//cond_signal(&cnt_nonzero) ;
pthread_mutex_unlock(capture_lock) ;//release lock
return true ;
}
server_udpsocket.h
#ifndef _SERVER_UDPSOCKET_H_
#define _SERVER_UDPSOCKET_H_
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "main.h"
#define bool int
#define true 1
#define false 0
//#include "main.h"
bool init_udpsocket() ;
bool udpsocket_Run(pthread_mutex_t *capture_lock) ;
void *thread_udpsocket(pthread_mutex_t *capture_lock) ;
extern pthread_t hthread_udpsocket ;
//extern pthread_cond_t cnt_nonzero ;
extern int cnt ;
#endif
server_udpsocket.c文件
#include "server_udpsocket.h"
int hudpsockfd; // Socket file descriptor
int localport=6767 ; //Local socket port
struct sockaddr_in addr_udplocal; //local socket address
struct sockaddr_in addr_udpremote; //remote socket address
int sin_size ;
int errno ;
//file operation
char tempbuf[65535] ;
char revbuf[15] ;
//thread
pthread_t hthread_udpsocket ;
sin_size=sizeof(struct sockaddr_in) ;
extern client* client_queque[10] ;
bool udpsocket_Run(pthread_mutex_t *capture_lock)
{
int ret =-1 ;
ret=pthread_create(&hthread_udpsocket,PTHREAD_CREATE_JOINABLE,(void *)thread_udpsocket,capture_lock) ;
return true ;
}
void *thread_udpsocket(pthread_mutex_t *capture_lock)
{
unsigned int ret ;
FILE *file=NULL ;
char i=0 ;
printf("UDPSocket:udpsocket thread start!/n") ;
hudpsockfd=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP) ;
while(1)
{
if(cnt==0)
{
continue ;
}
//lock
pthread_mutex_lock(capture_lock) ;
cnt=0 ;
//open file
file=fopen("temp.jpg","r") ;
if(file==NULL)
{
printf("UDPSocket:open file failed!/n") ;
printf("Mesg:%s/n",sys_errlist[errno]) ;
goto exit ;
}
ret=fread(tempbuf,1,65535,file) ;
if(ret==-1)
{
printf("UDPSocket:read file failed!/n") ;
printf("Mesg:%s/n",sys_errlist[errno]) ;
}
else
{
//ret=sendto(hudpsockfd,tempbuf,ret,0,(struct sockaddr *)&addr_udpremote, sin_size) ;
for(i=0;i<10;i++)
{
if(client_queque[i]==NULL)
continue ;
if(client_queque[i]->state==false)
continue ;
ret=sendto(hudpsockfd,tempbuf,ret,0,(struct sockaddr *)&(client_queque[i]->add_client), sin_size) ;
if(ret==-1)
{
printf("UDPSocket:send filed!/n") ;
printf("Mesg:%s/n",sys_errlist[errno]) ;
}
}
}
//close file
fclose(file) ;
//unlock
pthread_mutex_unlock(capture_lock) ;
}
exit:
close(hudpsockfd) ;
printf("udpsocket thread exited!/n") ;
}
server_tcpsocket.h文件
#ifndef _SERVER_TCPSOCKET_H_
#define _SERVER_TCPSOCKET_H_
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "main.h"
#define bool int
#define true 1
#define false 0
#define LOGIN 0x05
#define SET 0x06
#define LOGIN_SUCCESS 0x01
#define LOGIN_FAILED 0x02
#define SET_SUCCESS 0x03
#define SET_FAILED 0x04
#define START 0x07
#define STOP 0x08
#define LENGTH 20
#define BACKLOG 10
extern int quality ;
extern client * client_queque[10] ;
extern pthread_t hthread_tcpsocket ;
bool init_tcpsocket() ;
bool tcpsocket_Run(pthread_mutex_t *capture_lock) ;
void *thread_tcpsocket(pthread_mutex_t *capture_lock) ;
extern pthread_t hthread_tcpsocket ;
#endif
server_tcpsocket.c文件
#ifndef _SERVER_TCPSOCKET_H_
#define _SERVER_TCPSOCKET_H_
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "main.h"
#define bool int
#define true 1
#define false 0
#define LOGIN 0x05
#define SET 0x06
#define LOGIN_SUCCESS 0x01
#define LOGIN_FAILED 0x02
#define SET_SUCCESS 0x03
#define SET_FAILED 0x04
#define START 0x07
#define STOP 0x08
#define LENGTH 20
#define BACKLOG 10
extern int quality ;
extern client * client_queque[10] ;
extern pthread_t hthread_tcpsocket ;
bool init_tcpsocket() ;
bool tcpsocket_Run(pthread_mutex_t *capture_lock) ;
void *thread_tcpsocket(pthread_mutex_t *capture_lock) ;
extern pthread_t hthread_tcpsocket ;
#endif
server_tcpsocket.c文件
#include "server_tcpsocket.h"
int htcpsockfd ;//local socket ;
int hntcpsockfd ;//remote socket ;
int localtcpport=6768 ; //Local socket port
struct sockaddr_in addr_tcplocal; //local socket address
struct sockaddr_in addr_tcpremote; //remote socket address
client * client_queque[10] ;
//char recvbuf[LENGTH] ;
int errno ;
unsigned char add_len ;
char *user ="wk521521" ;
//thread
pthread_t hthread_tcpsocket ;
extern client* client_queque[10] ;
bool init_tcpsocket()
{
int ret ;
//obtain socket description
htcpsockfd=socket(AF_INET, SOCK_STREAM, 0) ;
if(htcpsockfd==-1)
{
printf("TCPSocket:failed to obtain socket descripter/n") ;
printf("Mesg:%s/n",sys_errlist[errno]) ;
return false ;
}
// Fill the local socket address struct
addr_tcplocal.sin_family = AF_INET; // Protocol Family
addr_tcplocal.sin_port = htons(localtcpport); // Port number
addr_tcplocal.sin_addr.s_addr = INADDR_ANY; // AutoFill local address
bzero(&(addr_tcplocal.sin_zero), 8); // Flush the rest of struct
//bind local port
ret=bind(htcpsockfd, (struct sockaddr*)&addr_tcplocal, sizeof(struct sockaddr)) ;
if(ret==-1)
{
printf("TCPSocket:failed to obtain socket descripter/n") ;
printf("Mesg:%s/n",sys_errlist[errno]) ;
close(htcpsockfd) ;
return false ;
}
//listen remote calling
ret=listen(htcpsockfd,BACKLOG) ;
if(ret==-1)
{
printf("TCPSocket:failed to obtain socket descripter/n") ;
printf("Mesg:%s/n",sys_errlist[errno]) ;
close(htcpsockfd) ;
return false ;
}
return true ;
}
bool tcpsocket_Run(pthread_mutex_t *capture_lock)
{
int ret =-1 ;
ret=pthread_create(&hthread_tcpsocket,PTHREAD_CREATE_JOINABLE,(void *)thread_tcpsocket,capture_lock) ;
return true ;
}
void *thread_childsocket(client *lpclient)
{
int num =sizeof(struct sockaddr) ;
char temp ;
u_short add ;
if(pthread_detach(pthread_self())!=0)
{
close(lpclient->hntcpsockfd) ;
printf("Child:can't detach child thread!/n") ;
pthread_exit((void *)1) ;
}
getpeername(lpclient->hntcpsockfd,(struct sockaddr*)&(lpclient->add_client),&num) ;
// add=htons(ntohs(lpclient->add_client.sin_port)+1) ;
lpclient->add_client.sin_port=htons(6767) ;
lpclient->state=false ;
lpclient->recvbuf=malloc(LENGTH) ;
while(1)
{
//clear buffer
memset(lpclient->recvbuf,'/0',LENGTH) ;
num=recv(lpclient->hntcpsockfd,lpclient->recvbuf,LENGTH,0) ;
if(num==-1)
{
printf("TCPSocket:failed to recieve!/n") ;
printf("Mesg:%s/n",sys_errlist[errno]) ;
//continue ;
goto exit ;
}
temp=(lpclient->recvbuf)[0] ;
switch(temp)
{
case LOGIN :
if(strcmp((lpclient->recvbuf)+1,user)==0)
{
(lpclient->recvbuf)[0]=LOGIN_SUCCESS ;
(lpclient->recvbuf)[1]='/0' ;
}
else
{
(lpclient->recvbuf)[0]=LOGIN_FAILED ;
(lpclient->recvbuf)[1]='/0' ;
}
send(lpclient->hntcpsockfd,(lpclient->recvbuf),2,0) ;
break ;
case SET :
quality=atoi((lpclient->recvbuf)+1) ;
(lpclient->recvbuf)[0]=SET_SUCCESS ;
(lpclient->recvbuf)[1]='/0' ;
send(lpclient->hntcpsockfd,(lpclient->recvbuf),2,0) ;
break ;
case START :
lpclient->state=true ;
break ;
case STOP :
lpclient->state=false ;
break ;
default:
printf("Child:default!/n") ;
break ;
}
}
exit:
lpclient=NULL ;
free(lpclient->recvbuf) ;
close(lpclient->hntcpsockfd) ;
free(lpclient) ;
lpclient=NULL ;
}
void *thread_tcpsocket(pthread_mutex_t *capture_lock)
{
int index,sin_size ;
int fd[10] ;
unsigned char temp ;
pthread_t hthread_child[5] ;
sin_size = sizeof(struct sockaddr_in);
//init listen socket
if(!init_tcpsocket())
{
goto exit ;
}
printf("TCP thread start!/n") ;
for(index=0;index<10;index++)
{
client_queque[index]=NULL ;
}
index=0 ;
// while(1)
{
//accept remote link
for(index=0;index<10;)
{
if(client_queque[index]==NULL)
{
hntcpsockfd=accept(htcpsockfd, (struct sockaddr *)&addr_tcpremote, &sin_size) ;
if(hntcpsockfd==-1)
{
printf("TCPSocket:failed to accept remote link!/n") ;
printf("Mesg:%s/n",sys_errlist[errno]) ;
continue ;
}
// fd[index]=hntcpsockfd ;
client_queque[index]= (client*)malloc(sizeof(client)) ;
client_queque[index]->hntcpsockfd=hntcpsockfd ;
++index ;
pthread_create(hthread_child,NULL,(void *)thread_childsocket,client_queque[index-1]) ;
if(index==10)
{
index=0 ;
}
}
}
}
exit:
close(htcpsockfd) ;
printf("TCP thread exite!/n") ;
}