这个程序耗费我一天的时间,才得以解决一个问题!原来在arm linux上的程序最好不要放在/usr目录下,我这个程序就是,开始我就把程序放在这个目录下,摄像头采集一会就不采集数据了,一直找不到原因所在,开始还以为内存耗尽了, 但是始终找不到耗尽的原因!郁闷了我好久!今天得以解决,解决了我毕业设计的一大隐患!就担心这个地方出问题,造成毕业设计失败!
明天开始写网络传输模块的程序!
以后有时间会把这个程序进一步封装,更加模块化!
头文件:capture.h
#ifndef _CAPTURE_H_
#define _CAPTURE_H_
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define bool int
#define true 1
#define false 0
//#include
int errno;
bool open_video() ;//open video
char *NextFrame() ;//capture one frame data
void close_video() ;//close video and free resource
bool capture_run() ;//create capture thread
void *thread_capture() ;//capture thread function
bool encode_jpeg(char *lpbuf,int width ,int height) ;//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 ;
//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_RGB565;
//conrresponding to thread
pthread_t hthread_capture ;//capture thread!
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 ;
}
printf("memorymap=%d/n",(int)memorymap) ;
//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_memorymap[ret].frame=ret ;
v_memorymap[ret].width=width ;
v_memorymap[ret].height=height ;
v_memorymap[ret].format=palette ;
++ret ;
}
ret=0 ;
printf("frame size:%d,frames :%d/n",v_bufferproperty.size,v_bufferproperty.frames) ;
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) ;//关闭设备文件
exit(0) ;
}
++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()
{
int ret=-1 ;
//注意在linux下使用线程,在编译链接时要加lpthread
ret=pthread_create(&hthread_capture,NULL,thread_capture,NULL) ;
if(ret==-1)
{
printf("Capture:create capture thread failed!/n") ;
return false ;
}
// printf("test!/n") ;
return true ;
}
//thread function
void *thread_capture()
{
char *temp=NULL ;
int a=0 ;
if(!open_video())
{
goto exit ;
}
// bufferIndex=0 ;
// printf("test11!/n") ;
while(1)
{
temp=NextFrame() ;
printf("Frames:%d/n",a) ;
if(!encode_jpeg(temp,width,height))
{
goto exit ;
}
++a ;
}
close_video() ;
exit:
printf("Capture:capture thread exited !/n") ;
}
bool encode_jpeg(char *lpbuf,int width ,int height)
{
struct jpeg_compress_struct cinfo ;//
struct jpeg_error_mgr jerr ;//
JSAMPROW row_pointer[1] ;
int row_stride ;
char *buffer=NULL ;
int x ;
FILE *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 ;
}
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
jpeg_stdio_dest(&cinfo, fptr_jpg);
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, 80,true);
jpeg_start_compress(&cinfo, TRUE);
row_stride = width * 3;
// row_pointer[0] = &buffer[cinfo.next_scanline * row_stride];
buffer=malloc(row_stride) ;
row_pointer[0] = buffer;
while (cinfo.next_scanline < height)
{
// (void)jpeg_write_scanlines(&cinfo, row_pointer, 1);
//printf("row_stride=%d/n",row_stride) ;
for (x = 0; x < row_stride; x+=3)
{
buffer[x] = lpbuf[x];
buffer[x+1] = lpbuf[x+1];
buffer[x+2] = lpbuf[x+2];
}
jpeg_write_scanlines (&cinfo, row_pointer, 1);//critical
lpbuf += row_stride;
}
jpeg_finish_compress(&cinfo);
fclose(fptr_jpg);
jpeg_destroy_compress(&cinfo);
free(buffer) ;
return true ;
}
int main()
{
capture_Run() ;
while(1) ;
return 0;
}