📄 videodog44.c
字号:
/* videodog4.c - v4l capture using the double buffer capability */
/* experimental code */
/* tested only w/ cpia driver over paralel port */
#include <stdio.h>
#include <time.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <linux/videodev.h>
#include <unistd.h> /* read */
#include <errno.h> /* errno */
#include <stdlib.h>
#include <termios.h>
#include <math.h>
#include <sys/fcntl.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <sys/shm.h>
#include <sys/resource.h>
#include <string.h>
void DOT (void) { static int indice=0; fprintf(stderr,"%d", indice++); }
#define VIDEO_BUFFERS 2 // numero de buffers usados na captura
// padrao de imagens
#define WIDTH 320
#define HEIGHT 240
#define DEPTH 3
#define IMGSIZE (WIDTH * HEIGHT * DEPTH)
// structs globais
struct video_mbuf mbuf;
struct video_picture pic;
struct video_channel chn;
struct video_mmap buf[VIDEO_BUFFERS];
struct video_capability cap;
unsigned char *buffer;
int video_fd;
static int frame_flag=0;
int _grab_frame (int frame) { // captura
if (ioctl(video_fd, VIDIOCMCAPTURE, buf + frame) == -1) ; // captura para o frame determinado
return 0;
}
int _grab_sync ( int frame ) { // sincroniza
if (ioctl (video_fd, VIDIOCSYNC, buf+frame) == -1); // sincroniza o frame determinado
return 0;
return frame; // apenas para controle, retorna o frame
}
int _grab_open (char *device, int width, int height, int depth) {
unsigned int size=0;
if ((video_fd=open(device, O_RDWR)) < 0 ) return -1;
if (ioctl (video_fd, VIDIOCGCAP, &cap) < 0) return -1;
if (width > cap.maxwidth || height > cap.maxheight ||
width < cap.minwidth || height < cap.minheight)
return -1;
if (ioctl (video_fd, VIDIOCGPICT, &pic) < 0) return -1;
chn.type = VIDEO_TYPE_CAMERA;
chn.norm = VIDEO_MODE_PAL;
chn.channel = 1;
if (ioctl (video_fd, VIDIOCSCHAN, &chn) < 0) return -1;
// mmap
buf[0].frame = 0;
buf[1].frame = 1;
buf[0].width = buf[1].width = width;
buf[0].height = buf[1].height = height;
switch (depth) {
case 1:
buf[0].format = buf[1].format = VIDEO_PALETTE_GREY;
break;
case 2:
buf[0].format = buf[1].format = VIDEO_PALETTE_RGB565;
break;
case 3:
default:
buf[0].format = buf[1].format = VIDEO_PALETTE_RGB24;
break;
}
size = width * height * depth;
mbuf.size = size * VIDEO_BUFFERS;
mbuf.frames = 0;
mbuf.offsets[0] = 0;
mbuf.offsets[1] = size;
if (ioctl (video_fd, VIDIOCGMBUF, &mbuf) < 0) return -1;
buffer = mmap (0, mbuf.size, PROT_READ | PROT_WRITE, MAP_SHARED, video_fd, 0);
if (buffer == (unsigned char *) -1) return -1;
if (_grab_frame(frame_flag) < 0) return 0;
if (frame_flag) frame_flag=0;
else frame_flag=1;
return 0;
}
void _grab_close (void) {
munmap (buffer, mbuf.size);
close (video_fd);
}
unsigned char *_grab_pix (void) { // retorna um frame, alternando
// static int frame=frame_flag; // registro static , inicia no frame_flag e a cada chamada alterna
if (_grab_frame(frame_flag) < 0) return 0;
frame_flag=!frame_flag;
if(_grab_sync(!frame_flag) < 0) return 0;
return buffer + mbuf.offsets[frame_flag]; // inverte
}
void _save_test_pnm (unsigned char *buffer, int wido, int heio, unsigned long si) {
static int indo=0;
FILE *fp;
char bewf[128];
sprintf (bewf, "image-%d.pnm", indo);
indo++;
if ((fp = fopen (bewf, "w")) == NULL) return;
fprintf (fp, "P6\n%d %d\n255\n", wido, heio);
fwrite (buffer, si, 1, fp);
fclose (fp);
}
void _save_test_ppm (unsigned char *image, int width, int height)
// this is a shameless copy from vidcat merged together with
// Gleicon's _save_test_pnm Franz <fre@wenglor.de>
{
unsigned char *p = (unsigned char *)image;
unsigned char rgb[3];
static int indo=0;
int fp,j,k;
unsigned char header[16];
//unsigned char *p;
//unsigned char rgb[3];
char bewf[128];
sprintf (bewf, "image-%d.ppm", indo);
indo++;
if ((fp = open (bewf, O_WRONLY | O_CREAT, 0644)) < 0) {
printf ("ppm open failed: %d\n", errno);
exit (1);
//fp = fopen(filename,"w");
//if(fp == NULL)
//return -1;
}
sprintf(header,"P6\n%d %d\n255\n",width, height);
//fprintf(fp,"P6\n%d %d\n255\n",screen_width, screen_height);
write (fp, header, strlen(header));
//fwrite(img, screen_height, 3*screen_width, fp);
for (j=0; j<height; j++) {
for (k=0; k<width; k++) {
rgb[2] = *p++;
rgb[1] = *p++;
rgb[0] = *p++;
//p++;
write(fp, rgb, 3);
}
}
close(fp);
//return 0;
}
/*
ls=sizeof(unsigned char);
if ((fp = fopen (bewf, "w")) == NULL) return;
fprintf (fp,"P6\n%d %d\n%d\n", width, height, 255);
for (x = 0; x < width * height; x++) {
buff[0] = p[2];
buff[1] = p[1];
buff[2] = p[0];
fwrite (buff, ls, 3, fp);
p += 3;
}
fflush (fp);
fclose (fp);*/
int main (void) {
time_t t, t2;
//struct tm *mytm;
int a;
//unsigned char *bufo;
int interlock=0;
if (_grab_open("/dev/video0", WIDTH, HEIGHT, DEPTH) < 0) {
fprintf (stderr,"cant open\n");
exit(0);
}
while (1) {
time(&t);
for (a=0; a< 30; a++) {
ioctl (video_fd, VIDIOCMCAPTURE, &buf[interlock]);
interlock = !interlock;
ioctl (video_fd, VIDIOCSYNC, &buf[interlock] );
_save_test_ppm (_grab_pix(), WIDTH, HEIGHT);
}
time (&t2);
fprintf (stderr,"Time: initial: %ld \nfinal: %ld\nelapsed: %ld \n", (time_t)t, (time_t)t2, (time_t)t2-t);
}
_grab_close();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -