V4L fb.c
int deviceHandle = 0;
int i; // temporary counter
struct video_capability capability;
struct video_channel queryChannel;
struct video_channel selectedChannel;
struct video_window captureWindow;
struct video_picture imageProperties;
struct video_mbuf memoryBuffer;
struct video_mmap* mmaps;
char* memoryMap;
int channelNumber = 0;
int width = 320;
int height = 240;
int depth;
int palette;
int bufferIndex;
int fbfd = 0;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
struct fb_cmap chen_fb_cmap;
long int screensize = 0;
char *fbp = 0;
int x = 0, y = 0;
long int location = 0;
typedef unsigned char BYTE;
BYTE m_pData[240][320];
int gwidth;
int gheight;
int gcount;
int GetSeg(int *x, int len);
void ErosionLin(int s[][20],int sm,int sn,int x[][320],int xm,int xn,int y[][320]);
void DilationLin(int s[][20],int sm,int sn,int x[][320],int xm,int xn,int y[][320]);
void CloseLin(int s[][20],int sm,int sn,int x[][320],int xm,int xn,int y[][320],int z[][320]);
int CountBySeg(int x[][320], long row, long col);
void OnResult();
void gray(char *data,int width,int height);
static int write_file(char *data, int width, int height);
int GetSeg(int *x, int len)
{
int i,temp,sum;
for(i=0;i<len-1;i++)
{
temp = x[i] * x[i+1];
if(temp==1)
x[i] = 0;
}
sum = 0;
for(i=0;i<len;i++)
sum = sum + x[i];
return sum;
}
void ErosionLin(int s[][20],int sm,int sn,int x[][320],int xm,int xn,int y[][320]){
int i0,j0,i,j;
int sum0,sum;
for(i0=0;i0<xm;i0++)
for(j0=0;j0<xn;j0++){
y[i0][j0]=0;
}
sum0=0;
for(i=0;i<sm;i++)
for(j=0;j<sn;j++){
sum0=sum0+s[i][j];
}
for(i0=0;i0=xm-sm;i0++)
for(j0=0;j0=xn-sn;j0++){
sum=0;
for(i=0;i<sm;i++)
for(j=0;j<sn;j++){
sum=sum+s[i][j]*x[i0+i][j0+j];
}
if(sum==sum0)
y[i0+sm/2][j0+sn/2]=1;
}
}
void DilationLin(int s[][20],int sm,int sn,int x[][320],int xm,int xn,int y[][320]){
int i0,j0,i,j;
int sum;
for(i0=0;i0<xm;i0++)
for(j0=0;j0<xn;j0++){
y[i0][j0]=0;
}
for(i0=0;i0=xm-sm;i0++)
for(j0=0;j0=xn-sn;j0++){
sum=0;
for(i=0;i<sm;i++)
for(j=0;j<sn;j++){
sum=sum+s[i][j]*x[i0+i][j0+j];
}
if(sum>0)
y[i0+sm/2][j0+sn/2]=1;
}
}
void CloseLin(int s[][20],int sm,int sn,int x[][320],int xm,int xn,int y[][320],int z[][320]){
DilationLin(s,sm,sn,x,xm,xn,y);
ErosionLin(s,sm,sn,y,xm,xn,z);
}
int CountBySeg(int x[][320],long row, long col)
{
int y[240][320];
int * z;
int i,j,j1,k;
int sum,count,seg;
for(i=0;i<row;i++)
for(j=0;j<col;j++)
y[i][j] = x[i][j];
for(i=0;i<row;i++)
y[i][0]=y[i][col-1] = 0;
for(j=0;j<col;j++)
y[0][j]=y[row-1][j] = 0;
z =(int*)malloc(sizeof(int)*col);
count = 0;
for(i=1;i<row-1;i++)
{
j = 1;
while(j<col-1)
{//while 1
if(y[i][j]==1)
{
sum = 1;
j1 = j + 1;
while(y[i][j1])
{
sum++;
j1++;
}
for(k=0;k<sum+2;k++)
z[k] = y[i-1][j+k-1];
seg = GetSeg(z,sum+2);
count = count + 1 - seg;
j = j + sum;
}
j++;
}
}
free(z);
gcount=count;
return count;
}
void OnResult()
{
int count,i,j;
int temp1[240][320],temp2[240][320];
int xx[240][320];
int s1[20][20];
int s2[20][20];
for(i=0; i<5; i++)
for(j=0; j<5; j++)
s1[i][j]=1;
for(i=0; i<20; i++)
for(j=0; j<20; j++)
s2[i][j]=1;
for(i=0; i<240; i++)
for(j=0; j<320; j++)
{
xx[i][j] = m_pData[i][j];
}
CloseLin(s1,5,5,xx,240,320,temp1,temp2);
ErosionLin(s2,10,10,temp2,240,320,temp1);
count=CountBySeg(temp1,gheight,gwidth);
return;
}
void gray(char *data,int width,int height)
{
int k=0;
long i,j;
gheight=height;
gwidth=width;
for ( i=0; i<height; i++)
{
for ( j=0; j<width; j++)
{
m_pData[i][j]= data[k] *0.114
+data[k+1] * 0.587
+data[k+2] * 0.299;
if(m_pData[i][j]>50)
m_pData[i][j]=1;
else
m_pData[i][j]=0;
k+=3;
}
}
}
static int write_file(char *data, int width, int height)
{
gray(data,width,height);
OnResult();
return 0;
}
char* NextFrame()
{
// send a request to begin capturing to the currently indexed buffer
if (ioctl (deviceHandle, VIDIOCMCAPTURE, &mmaps[bufferIndex]) == -1)
{ // capture request failed
}
// move bufferIndex to the next frame
++ bufferIndex;
if (bufferIndex == memoryBuffer.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, &mmaps[bufferIndex]) == -1)
{ // sync request failed
}
// return the address of the frame data for the current buffer index
return (memoryMap + memoryBuffer.offsets[bufferIndex]);
}
int main()
{
// open the device
char * videodeviceName = "/dev/v4l/video0";
deviceHandle = open (videodeviceName, O_RDWR);
if (deviceHandle == -1)
{ // could not open device
printf("Could not open device %s\n",videodeviceName);
// printf ("Could not open device %s - %s\n", videodeviceName, strerror[errno]);
return -1;
}
// get device capabilities
if (ioctl (deviceHandle, VIDIOCGCAP, &capability) == -1)
{ // query failed
printf ("could not obtain device capabilities\n");
return -1;
}
if ((capability.type & VID_TYPE_CAPTURE) == 0)
{ // this device cannot capture video to memory, exit
printf ("this device cannot capture video to memory\n");
return -1;
}
// enumerate and print out the channels
printf ("Select a channel:\n");
i = 0;
while (i capability.channels)
{
queryChannel.channel = i;
if (ioctl (deviceHandle, VIDIOCGCHAN, &queryChannel) != -1)
{ // ioctl success, queryChannel contains information about this channel
printf ("%d. %s\n", queryChannel.channel, queryChannel.name);
}
++ i;
}
// have the user select a channel
printf (": ");
fflush (stdout);
scanf ("%d", &channelNumber);
// set the selected channel
selectedChannel.channel = channelNumber;
selectedChannel.norm = VIDEO_MODE_NTSC;
if (ioctl (deviceHandle, VIDIOCSCHAN, &selectedChannel) == -1)
{ // could not set the selected channel
printf ("Could not set channel #%d\nNot a fatal error.", channelNumber);
}
// set the desired width and height
//if ((capability.type & VID_TYPE_SCALES) != 0)
//{ // supports the ability to scale captured images
// have the user enter a desired width
printf ("Enter the desired width (e.g. 320): ");
fflush (stdout);
scanf ("%d", &width);
printf ("Enter the desired height (e.g. 240): ");
fflush (stdout);
scanf ("%d", &height);
captureWindow.x = 0;
captureWindow.y = 0;
captureWindow.width = width;
captureWindow.height = height;
captureWindow.chromakey = 0;
captureWindow.flags = 0;
captureWindow.clips = 0;
captureWindow.clipcount = 0;
if (ioctl (deviceHandle, VIDIOCSWIN, &captureWindow) == -1)
{ // could not set window values for capture
printf ("Could not set desired dimensions\nNot a fatal error.\n");
}
//}
// retrieve the actual width and height of the capturing images
if (ioctl (deviceHandle, VIDIOCGWIN, &captureWindow) == -1)
{ // could not obtain specifics of capture window
printf ("Could not obtain capture window dimensions.\n");
}
width = captureWindow.width;
height = captureWindow.height;
printf ("Capturing dimensions are : %d, %d\n", width, height);
// request that we capture to 24bit RGB
// get image properties
if (ioctl (deviceHandle, VIDIOCGPICT, &imageProperties) != -1)
{ // successfully retrieved the default image properties
// the following values are for requesting 24bit RGB
imageProperties.depth = 24;
imageProperties.palette = VIDEO_PALETTE_RGB24;
if (ioctl (deviceHandle, VIDIOCSPICT, &imageProperties) == -1)
{ // failed to set the image properties
printf ("Could not set the video depth and palette.\nPerhaps not a fatal error.\n");
}
}
// verify that the requested capture pixel depth and palette succeeded
if (ioctl (deviceHandle, VIDIOCGPICT, &imageProperties) == -1)
{ // failed to retrieve default image properties
printf ("Failed to retrieve the video depth and palette.\n");
return -1;
}
depth = imageProperties.depth;
palette = imageProperties.palette;
if ((depth != 24) || (palette != VIDEO_PALETTE_RGB24))
{ // not a format our program supports
printf ("Format is not 24bit RGB.\n");
return -1;
}
printf ("Capture depth is %dbit RGB\n",depth);
// obtain memory about capture space
if (ioctl (deviceHandle, VIDIOCGMBUF, &memoryBuffer) == -1)
{ // failed to retrieve information about capture memory space
printf ("Failed to retrieve information about MMIO space.\n");
return -1;
}
// obtain memory mapped area
memoryMap = (char*)mmap (0, memoryBuffer.size, PROT_READ | PROT_WRITE, MAP_SHARED, deviceHandle, 0);
if ((int)memoryMap == -1)
{ // failed to retrieve pointer to memory mapped area
printf ("Failed to obtain MMIO space.\n");
return -1;
}
// allocate structures
mmaps = (struct video_mmap*)(malloc (memoryBuffer.frames * sizeof (struct video_mmap)));
//****************
//add by chenfu 2005.01.26
//****************
//open framebuffer
/*int fbfd = 0;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
struct fb_cmap chen_fb_cmap;
long int screensize = 0;
char *fbp = 0;
int x = 0, y = 0;
long int location = 0;*/
// Open the file for reading and writing
fbfd = open("/dev/fb/0", O_RDWR);
if (!fbfd) {
printf("Error: cannot open framebuffer device.\n");
exit(1);
}
printf("The framebuffer device was opened successfully.\n");
// Get fixed screen information
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) {
printf("Error reading fixed information.\n");
exit(2);
}
// Get variable screen information
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
printf("Error reading variable information.\n");
exit(3);
}
vinfo.bits_per_pixel=12;
if(ioctl(fbfd, FBIOPUT_VSCREENINFO, &vinfo)){
printf("The dfdfdfdfdfdfdfdfdfdfu\n");
}
// printf("The framebuffer set not .chenfu\n");
// Get variable screen information
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
printf("Error reading variable information.\n");
exit(3);
}
printf(" the chenfu framebuffe is %dx%d, %dbpp \n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel );
/*if (ioctl(fbfd, FBIOGETCMAP, &chen_fb_cmap)) {
printf("Error CHENFU variable information.\n");
exit(4);
}*/
// printf("the CHENFU CMAP %d\n",*chen_fb_cmap.red);
// Figure out the size of the screen in bytes
//screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
screensize = vinfo.xres * vinfo.yres*1.5;
// Map the device to memory
fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED,fbfd, 0);
if ((int)fbp == -1) {
printf("Error: failed to map framebuffer device to memory.\n");
exit(4);
}
printf("The framebuffer device was mapped to memory successfully.\n");
//the next is to capture
//start capture
// fill out the fields
i = 0;
while (i memoryBuffer.frames)
{
mmaps[i].frame = i;
mmaps[i].width = width;
mmaps[i].height = height;
mmaps[i].format = palette;
++ i;
}
// request capture to each buffer except the last one
i = 0;
while (i (memoryBuffer.frames-1))
{
if (ioctl (deviceHandle, VIDIOCMCAPTURE, &mmaps[i]) == -1)
{
// capture request failed}
++ i;
}
// set our index to the last buffer
bufferIndex = memoryBuffer.frames-1;
// capture and write out ten frames
printf ("Capture is ready;now start to captur images.\n");
while (1)
{ char* frame = NextFrame();
write_file(frame, 320, 240);
int index=0;
for ( y = 0; y 240; y++ )
for ( x = 0; x <160; x++ ) {
index = index +2;
location =(x+ vinfo.xoffset) * 3 + (y+vinfo.yoffset) * finfo.line_length;
*(fbp + location) = (frame[index*3+2]&0xF0)|((frame[index*3+1]&0xF0)>>4);
*(fbp + location+1) = (frame[index*3]&0xF0)|((frame[(index+1)*3+2]&0xF0)>>4);
*(fbp + location+2) = (frame[(index+1)*3+1]&0xF0)|((frame[(index+1)*3]&0xF0)>>4);
}
if((gcount>=0)&&(gcount=9))
drawNum(gcount);
else
drawNum(0);
}
// free the video_mmap structures
free (mmaps);
// unmap the capture memory
munmap (memoryMap, memoryBuffer.size);
// close the device
close (deviceHandle);
return 0;
}