基于 ARM 的远程视频监控系统 乐橙远程视频监控系统
系统组成:USB 视频采集模块、数据处理模块、视频播放模块。其中 USB 视频采集模块要解决两个问题,一个是摄像头驱动问题,另一个就是怎么样用 v4l 采集数据的问题。数据处理模块最主要就是把采集到的每一帧图像数据进行压缩,以节省网络带宽。视频播放模块主要就是客户段软件的实现,它通过网络接收数据,解压后进行播放。系统框架图如下:
系统工作流程:实现好摄像头驱动后,用 v4l 接口从摄像头中读取视频数据;调用 H.264 编码库对数据进行编码,然后通过 socket 发给客户端;客户端接收数据,进行解码,最后显示出来。
系统软硬件环境:
宿主机:Lenovo PC, Ubuntu 10.10
FL2440开发板:S3C2440, Linux-2.6.12
摄像头:中星微 ZC0301PH, 驱动为 gspca
编解码库:t264
实现步骤:
1. 编译摄像头驱动:进入摄像头驱动源码目录,修改 Makefile 文件,主要是改动 CC=arm-linux-gcc,KERNELDIR=YourKernelDir,然后 make,就会产生 gspca.ko 这个模块。
2. 交叉编译 H.264 源码:进入源码目录,修改 Makefile 文件:CC=arm-linux-gcc 即可。
3. 编译服务端软件,源码下附,Makefile 中要指明 H.264 的头文件路径还有上一步产生的库文件路径。
4. 测试,insmod gspca.ko,运行 ./camera_server。效果如下:
附 camera_server.c 源码:
view plaincopy to clipboardprint?
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>
#include<sys/ioctl.h>
#include<sys/mman.h>
#include<stdlib.h>
#include<linux/types.h>
#include<linux/videodev.h>
#include<setjmp.h>
#include<string.h>
#include<signal.h>
#include<errno.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include"convert.h"
#include"/paul/Tools/Lib/avc/common/T264.h"
#defineSERVER_PORT8888
T264_t*m_t264;
T264_param_tm_param;
char*m_pSrc;
char*m_pDst;
int*m_lDstSize;
char*m_pPoolData;
#defineUSB_VIDEO"/dev/video0"
intcam_fd;
structvideo_mmapcam_mm;
structvideo_capabilitycam_cap;
structvideo_picturecam_pic;
structvideo_mbufcam_mbuf;
structvideo_windowwin;
char*cam_data=NULL;
intnframe;
staticunsignedcharcam_yuv[2457616];
voidread_video(char*pixels,intw,inth)
{
intret;
intframe=0;
cam_mm.width=w;
cam_mm.height=h;
cam_mm.frame=0;
cam_mm.format=VIDEO_PALETTE_RGB24;//OurcamerasupportRGB24
/*Readdata*/
ret=ioctl(cam_fd,VIDIOCMCAPTURE,&cam_mm);
if(ret<0){
printf("ERROR:VIDIOCMCAPTUREn");
}
/*Waituntilalldataisread.*/
ret=ioctl(cam_fd,VIDIOCSYNC,&frame);
if(ret<0){
printf("ERROR:VIDIOCSYNCn");
}
}
/*Configurepicture*/
voidconfig_vid_pic()
{
charcfpath[100];
FILE*cf;
intret;
if(ioctl(cam_fd,VIDIOCGPICT,&cam_pic)<0){
printf("ERROR:VIDIOCGPICTn");
}
cam_pic.palette=VIDEO_PALETTE_RGB24;
cam_pic.brightness=30464;
cam_pic.hue=111;
cam_pic.colour=555;
cam_pic.contrast=43312;
cam_pic.whiteness=111;
cam_pic.depth=24;
ret=ioctl(cam_fd,VIDIOCSPICT,&cam_pic);
if(ret<0){
close(cam_fd);
printf("ERROR:VIDIOCSPICT,Can'tsetvideo_pictureformatn");
}
return;
}
voidinit_video(intw,inth)
{
intret;
/*Openthedevice*/
cam_fd=open(USB_VIDEO,O_RDWR);
if(cam_fd<0)
printf("Can'topenvideodevicen");
/*Getinfo*/
ret=ioctl(cam_fd,VIDIOCGCAP,&cam_cap);
if(ret<0){
printf("Can'tgetdeviceinformation:VIDIOCGCAPn");
}
printf("Devicename:%snWidth:%d~%dnHeight:%d~%dn",
cam_cap.name,
cam_cap.maxwidth,
cam_cap.minwidth,
cam_cap.maxheight,
cam_cap.minheight);
if(ioctl(cam_fd,VIDIOCGWIN,&win)<0){
printf("ERROR:VIDIOCGWINn");
}
win.x=0;
win.y=0;
win.width=w;
win.height=h;
/*SetWindow*/
if(ioctl(cam_fd,VIDIOCSWIN,&win)<0){
printf("ERROR:VIDIOCSWINn");
}
config_vid_pic();
/*Getdevicebuffer*/
ret=ioctl(cam_fd,VIDIOCGMBUF,&cam_mbuf);
if(ret<0){
printf("ERROR:VIDIOCGMBUF,Can'tgetvideo_mbufn");
}
printf("Frames:%dn",cam_mbuf.frames);
nframe=cam_mbuf.frames;
/*Memorymap*/
cam_data=(char*)mmap(0,cam_mbuf.size,PROT_READ|PROT_WRITE,MAP_SHARED,cam_fd,0);
if(cam_data==MAP_FAILED){
printf("ERROR:mmapn");
}
printf("Buffersize:%dnOffset:%dn",cam_mbuf.size,cam_mbuf.offsets[0]);
InitLookupTable();
}
/*ThisfunctionisfromtheexampleT264.c.
*Itinitializetheencodewithparametersfromtheconfigurefile.
*Youdon'tneedtoknowthegreatdetail.
*/
voidinit_param(T264_param_t*param,constchar*file)
{
inttotal_no;
FILE*fd;
charline[255];
int32_tb;
if(!(fd=fopen(file,"r")))
{
printf("Couldn'topenparameterfile%s.n",file);
exit(-1);
}
memset(param,0,sizeof(*param));
fgets(line,254,fd);sscanf(line,"%d",&b);
if(b!=4)
{
printf("wrongparamfileversion,expectv4.0n");
exit(-1);
}
fgets(line,254,fd);sscanf(line,"%d",¶m->width);
fgets(line,254,fd);sscanf(line,"%d",¶m->height);
fgets(line,254,fd);sscanf(line,"%d",¶m->search_x);
fgets(line,254,fd);sscanf(line,"%d",¶m->search_y);
fgets(line,254,fd);sscanf(line,"%d",&total_no);
fgets(line,254,fd);sscanf(line,"%d",¶m->iframe);
fgets(line,254,fd);sscanf(line,"%d",¶m->idrframe);
fgets(line,254,fd);sscanf(line,"%d",¶m->b_num);
fgets(line,254,fd);sscanf(line,"%d",¶m->ref_num);
fgets(line,254,fd);sscanf(line,"%d",¶m->enable_rc);
fgets(line,254,fd);sscanf(line,"%d",¶m->bitrate);
fgets(line,254,fd);sscanf(line,"%f",¶m->framerate);
fgets(line,254,fd);sscanf(line,"%d",¶m->qp);
fgets(line,254,fd);sscanf(line,"%d",¶m->min_qp);
fgets(line,254,fd);sscanf(line,"%d",¶m->max_qp);
fgets(line,254,fd);sscanf(line,"%d",¶m->enable_stat);
fgets(line,254,fd);sscanf(line,"%d",¶m->disable_filter);
fgets(line,254,fd);sscanf(line,"%d",¶m->aspect_ratio);
fgets(line,254,fd);sscanf(line,"%d",¶m->video_format);
fgets(line,254,fd);sscanf(line,"%d",¶m->luma_coeff_cost);
fgets(line,254,fd);sscanf(line,"%d",&b);
param->flags|=(USE_INTRA16x16)*(!!b);
fgets(line,254,fd);sscanf(line,"%d",&b);
param->flags|=(USE_INTRA4x4)*(!!b);
fgets(line,254,fd);sscanf(line,"%d",&b);
param->flags|=(USE_INTRAININTER)*(!!b);
fgets(line,254,fd);sscanf(line,"%d",&b);
param->flags|=(USE_HALFPEL)*(!!b);
fgets(line,254,fd);sscanf(line,"%d",&b);
param->flags|=(USE_QUARTPEL)*(!!b);
fgets(line,254,fd);sscanf(line,"%d",&b);
param->flags|=(USE_SUBBLOCK)*(!!b);
fgets(line,254,fd);sscanf(line,"%d",&b);
param->flags|=(USE_FULLSEARCH)*(!!b);
fgets(line,254,fd);sscanf(line,"%d",&b);
param->flags|=(USE_DIAMONDSEACH)*(!!b);
fgets(line,254,fd);sscanf(line,"%d",&b);
param->flags|=(USE_FORCEBLOCKSIZE)*(!!b);
fgets(line,254,fd);sscanf(line,"%d",&b);
param->flags|=(USE_FASTINTERPOLATE)*(!!b);
fgets(line,254,fd);sscanf(line,"%d",&b);
param->flags|=(USE_SAD)*b;
fgets(line,254,fd);sscanf(line,"%d",&b);
param->flags|=(USE_EXTRASUBPELSEARCH)*(!!b);
fgets(line,254,fd);sscanf(line,"%d",&b);
param->flags|=(USE_SCENEDETECT)*(!!b);
fgets(line,254,fd);sscanf(line,"%d",&b);
param->block_size|=(SEARCH_16x16P)*(!!b);
fgets(line,254,fd);sscanf(line,"%d",&b);
param->block_size|=(SEARCH_16x8P)*(!!b);
fgets(line,254,fd);sscanf(line,"%d",&b);
param->block_size|=(SEARCH_8x16P)*(!!b);
fgets(line,254,fd);sscanf(line,"%d",&b);
param->block_size|=(SEARCH_8x8P)*(!!b);
fgets(line,254,fd);sscanf(line,"%d",&b);
param->block_size|=(SEARCH_8x4P)*(!!b);
fgets(line,254,fd);sscanf(line,"%d",&b);
param->block_size|=(SEARCH_4x8P)*(!!b);
fgets(line,254,fd);sscanf(line,"%d",&b);
param->block_size|=(SEARCH_4x4P)*(!!b);
fgets(line,254,fd);sscanf(line,"%d",&b);
param->block_size|=(SEARCH_16x16B)*(!!b);
fgets(line,254,fd);sscanf(line,"%d",&b);
param->block_size|=(SEARCH_16x8B)*(!!b);
fgets(line,254,fd);sscanf(line,"%d",&b);
param->block_size|=(SEARCH_8x16B)*(!!b);
fgets(line,254,fd);sscanf(line,"%d",&b);
param->block_size|=(SEARCH_8x8B)*(!!b);
fgets(line,254,fd);sscanf(line,"%d",¶m->cpu);
fgets(line,254,fd);sscanf(line,"%d",¶m->cabac);
//fgets(line,254,fd);sscanf(line,"%s",src_path);
//fgets(line,254,fd);sscanf(line,"%s",out_path);
//fgets(line,254,fd);sscanf(line,"%s",rec_path);
//param->rec_name=rec_path;
fclose(fd);
}
/*CreateandInitializeanencoder*/
voidinit_encoder()
{
/*Configurefile*/
constchar*paramfile="fastspeed.txt";
/*Readthefileandfilltheparameterstruct*/
init_param(&m_param,paramfile);
m_param.direct_flag=1;
/*Createanencoderwiththeparametersreadfromconfigurefile.*/
m_t264=T264_open(&m_param);
/*allocmemoryfortheencodeddata.*/
m_lDstSize=m_param.height*m_param.width+(m_param.height*m_param.width>>1);
m_pDst=(uint8_t*)T264_malloc(m_lDstSize,CACHE_SIZE);
/*allocmemoryfromdatapackage*/
m_pPoolData=malloc(m_param.width*m_param.height*3/2);
}
/*Thisfunctionisthemainworkingfunction.
*@sockfd:Thesocketweusetosenddata.
*@w:Thewidthofpicture.
*@h:Theheightofpicture.
*/
voidmain_loop(intsockfd,intw,inth)
{
/*Theaddressoftheclient*/
structsockaddr_inaddrdst;
intaddrlen,n;
/*Datasize*/
int32_tiActualLen;
introw_stride=w*3*h/2;
/*Fillclientaddress*/
bzero(&addrdst,sizeof(structsockaddr_in));
addrdst.sin_family=AF_INET;
addrdst.sin_addr.s_addr=inet_addr("125.216.244.49");
addrdst.sin_port=htons(SERVER_PORT);
/*Allisready,comesthisloop,doingtheactuallywork.*/
while(1)
{
/*Readdatafromthecamera*/
read_video(NULL,w,h);
/*WeconvertRGBtoYUV420,sincetheencodeacceptYUV420only*/
ConvertRGB2YUV(w,h,cam_data,cam_yuv);
iActualLen=T264_encode(m_t264,cam_yuv,m_pDst,row_stride);
printf("encoded:%d,%dbytes.n",row_stride,iActualLen);
/*Filladatapackage.
*Hereweputtheframenumberfirst,
*andthetheactualencodeddata.
*Notethatitisnotsafetodoso:
*sendingbinarydatadirectlymaycauseEndianproblem.
*However,ARMandx86areallSmallEndian,soitlooksfine.
*/
memcpy(m_pPoolData,&m_t264->frame_num,1);
memcpy(m_pPoolData+1,m_pDst,iActualLen);
iActualLen++;
/*Weusesockettosendaframe.*/
sendto(sockfd,m_pPoolData,iActualLen,0,
(structsockaddr*)&addrdst,sizeof(structsockaddr_in));
}
}
/*Callbackfunction*/
voidfree_dev()
{
printf("Freedevicen");
close(cam_fd);
}
intmain(void)
{
printf("Startembeddedvideoserver...n");
fflush(stdout);
intsockfd;
/*Actually,theprogramisaclienttechniquely
*thus,wedonthavetobinditaaddress.*/
sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(sockfd<0)
{
printf("0-");
printf("SocketErrorn");
exit(1);
}
/*Initializetheencoder*/
init_encoder();
/*Iguessthisistoregisteracallbackfunction,
*whentheencoderexitunexpectly,thisfunction
*willbecallled.
*/
atexit(&free_dev);
/*InitializeV4l
*Wegetdatafromcamerabythev4lAPI
*/
init_video(m_param.width,m_param.height);
/*Whenworking,wewillbeinaloop.
*Everytimewereaddatafromthecamera,encodeit,
*andsendittotheclient.
*/
main_loop(sockfd,m_param.width,m_param.height);
close(sockfd);
}
更多阅读
32位和64位的区别 如何查看系统是32还是64位 xp系统是32位还是64位
【32位和64位的区别】如何查看系统是32还是64位——简介 最近有个朋友问我。32位和64位系统到底有什么区别的区别?WIN7系统32位和64位有什么区别?怎么查看我的系统是不是64位的?不能安装64位系统是怎么回事?怎么看系统多少位的。带着这
怎样制作自己的游戏视频 游戏视频后期制作软件
看到网上很多人做出自己的视频,其实视频很容易制作怎样制作自己的游戏视频——工具/原料fraps格式工厂怎样制作自己的游戏视频——步骤/方法怎样制作自己的游戏视频 1、首先进入FRAPS设置好快捷键怎样制作自己的游戏视频 2、进入游
教你如何在土豆网下载你想要格式的播放视频 精 87版红楼梦土豆网播放
想知道要怎么样才能在土豆网上下载你想要格式的播放视频吗?方法很简单,现在就来教大家如何在土豆网下载你想要格式的播放视频吧!教你如何在土豆网下载你想要格式的播放视频 精——步骤/方法教你如何在土豆网下载你想要格式的播放视
如何免费看优酷土豆上的付费视频 优酷付费视频下载
如何免费看优酷土豆上的付费视频——简介我们平时看视频的时候,各大视频网站上有些新电影是收费的,只能看5----10分钟,能不能有一种方法让我们免费看这些视频呢。现在我无意中发现了这么一个方法,经我的验证是对有些视频可以正常使用的,
怎样免费下载高清的mv视频 mv下载网站 免费 高清
怎样免费下载高清的mv视频——简介网络上有很多好看的视频mv,但是只是会员才可以下载观看,普通人只能在线看一下,看完后也就没有了。那么,怎样才能让普通人也能下载下来呢。下面就用“酷我音乐”介绍下怎样免费下载高清的mv视频——工