📄 vidcat.c
字号:
}
fflush (out);
}
/*
* write pgm image to stdout / file
*/
void
put_image_pgm (FILE *out, char *image, int width, int height, int binary)
{
int x, y, ls=0;
unsigned char *p = (unsigned char *)image;
if (!binary) {
fprintf (out, "P2\n%d %d\n%d\n", width, height, 255);
for (x = 0; x < width; x++) {
for (y = 0; y < height; y++) {
fprintf (out, "%03d ", p[0]);
p++;
if (ls++ > 4) {
fprintf (out, "\n");
ls = 0;
}
}
}
fprintf (out, "\n");
} else {
fprintf (out, "P5\n%d %d\n%d\n", width, height, 255);
for (x = 0; x < width * height; x++) {
fwrite (p, 1, 1, out);
p++;
}
}
fflush (out);
}
/*
* write YUV4MPEG stream which is nice for mpeg2enc
*/
int
to_yuv (FILE *out, int fd, int width, int height)
{
struct video_mbuf vid_buf;
struct video_mmap vid_mmap;
int do_read = 0;
int done = 0;
char *map;
int size;
int num = 0;
double ms_time0, ms_time1;
int tpf = 40; /* 40 ms time per frame (= 25 fps) */
if (ioctl (fd, VIDIOCGMBUF, &vid_buf) == -1) {
do_read = 1;
} else {
fprintf (stderr, "buffsize=%d frames=%d\n",vid_buf.size,vid_buf.frames);
}
if (!do_read) {
map = mmap (0, vid_buf.size, PROT_READ|PROT_WRITE,MAP_SHARED, fd, 0);
if ((unsigned char *)-1 == (unsigned char *)map) {
perror ("mmap()");
return -1;
}
vid_mmap.format = VIDEO_PALETTE_YUV420P;
vid_mmap.frame = 0;
vid_mmap.width = width;
vid_mmap.height =height;
size = (width * height) + (width * height / 2);
fprintf (stderr, "%dx%d bufsize=%d size=%d\n",
width, height, vid_buf.size, size);
printf ("YUV4MPEG%d %d %d\n", width, height, 3);
if (ioctl (fd, VIDIOCMCAPTURE, &vid_mmap) == -1) {
perror ("ioctl VIDIOCMCAPTURE");
munmap (map, vid_buf.size);
return -1;
}
vid_mmap.frame = 1;
if (ioctl (fd, VIDIOCMCAPTURE, &vid_mmap) == -1) {
perror ("ioctl VIDIOCMCAPTURE");
munmap (map, vid_buf.size);
return -1;
}
while (!done) {
ms_time0 = ms_time(); /* milli seconds */
vid_mmap.frame = vid_mmap.frame > 0 ? 0 : 1;
if (ioctl (fd, VIDIOCSYNC, &vid_mmap.frame) == -1) {
perror ("ioctl VIDIOCSYNC");
munmap (map, vid_buf.size);
return -1;
}
printf ("FRAME\n");
fwrite (map + vid_buf.offsets[vid_mmap.frame], 1, size, stdout);
if (ioctl (fd, VIDIOCMCAPTURE, &vid_mmap) == -1) {
perror ("ioctl VIDIOCMCAPTURE");
munmap (map, vid_buf.size);
return -1;
}
num++;
ms_time1 = ms_time () - ms_time0;
if (ms_time1 < (double)tpf) {
usleep (tpf - (int)ms_time1);
} else {
fprintf (stderr, "delayed: dt=%f\n",ms_time1 - (double)tpf);
}
}
munmap (map, vid_buf.size);
} else {
fprintf (stderr, "still not implemented\n");
}
return 0;
}
/*
* main()
*/
int
main (int argc, char *argv[])
{
int width = DEF_WIDTH, height = DEF_HEIGHT, size, dev = -1, c;
char *image, *device = VIDEO_DEV, *file = NULL;
int max_try = 5; /* we try 5 seconds/times to open the device */
int quality = QUAL_DEFAULT; /* default jpeg quality setting */
int input = INPUT_DEFAULT; /* this means take over current device settings*/
int norm = NORM_DEFAULT;
int loop =0 ;
int binary = 0;
int palette = VIDEO_PALETTE_RGB24;
//int palette = VIDEO_PALETTE_YUV420;
int num = 0;
FILE *out = stdout;
#ifdef HAVE_LIBJPEG
int format = FMT_JPEG;
#else
# ifdef HAVE_LIBPNG
int format = FMT_PNG;
# else
int format = FMT_PPM;
# endif
#endif
while ((c = getopt (argc, argv, "bd:f:gi:ln:o:p:q:s:vV")) != EOF) {
switch (c) {
case 'b': /* PPM as binary file */
binary = 1;
break;
case 'd': /* change default device */
device = optarg;
break;
case 'f':
if (strcasecmp ("yuv4mpeg", optarg) == 0)
format = FMT_YUV4MPEG;
else if (strcasecmp ("png", optarg) == 0)
format = FMT_PNG;
else if (strcasecmp ("ppm", optarg) == 0)
format = FMT_PPM;
else if (strcasecmp ("pgm", optarg) == 0) {
format = FMT_PGM;
palette = VIDEO_PALETTE_GREY;
} else if (strcasecmp ("jpeg", optarg) == 0)
format = FMT_JPEG;
else
format = FMT_UNKNOWN;
break;
case 'g':
palette = VIDEO_PALETTE_GREY;
break;
case 'i':
if (strcasecmp ("tv", optarg) == 0) {
input = IN_TV;
} else if (strcasecmp ("comp1", optarg) == 0) {
input = IN_COMPOSITE;
} else if (strcasecmp ("comp2", optarg) ==0) {
input = IN_COMPOSITE2;
} else if (strcasecmp ("s-video", optarg) == 0) {
input = IN_SVIDEO;
} else {
usage (argv[0]);
}
break;
case 'l':
loop = 1;
break;
case 'n':
if (strcasecmp ("pal", optarg) == 0)
norm = NORM_PAL;
else if (strcasecmp ("ntsc", optarg) == 0)
norm = NORM_NTSC;
else if (strcasecmp ("secam", optarg) == 0)
norm = NORM_SECAM;
else
usage (argv[0]);
break;
case 'o':
file = optarg;
break;
case 'p':
switch (*optarg) {
case 'R':
case 'c':
palette = VIDEO_PALETTE_RGB24;
break;
case 'y':
palette = VIDEO_PALETTE_YUV420P;
break;
case 'Y':
palette = VIDEO_PALETTE_YUV422P;
break;
case 'g':
palette = VIDEO_PALETTE_GREY;
break;
default:
usage (argv[0]);
break;
}
break;
case 'q':
sscanf (optarg, "%d", &quality);
break;
case 's':
sscanf (optarg, "%dx%d", &width, &height);
break;
case 'v':
verbose++;
break;
case 'V':
printf ("Vidcat, Version %s\n", VERSION);
exit (0);
break;
default:
usage (argv[0]);
break;
}
}
if (verbose) {
fprintf (stderr, "input palette: %s\n",
palette == VIDEO_PALETTE_GREY ? "grey" :
palette == VIDEO_PALETTE_RGB24 ? "rgb" :
palette == VIDEO_PALETTE_YUV420P ? "yuv420" : "yuv422");
fprintf (stderr, "size: %dx%d\n", width, height);
}
if (file) {
out = fopen (file, "wb");
if (!out) {
perror (file);
return 1;
}
}
again:
/* open the video4linux device */
while (max_try) {
dev = open (device, O_RDWR);
if (dev == -1) {
if (!--max_try) {
fprintf (stderr, "Can't open device %s\n", device);
return (1);
}
sleep (1);
} else { break; }
}
if (!num) {
/* if we loop we have to do this only once. so
* check frame number and execute only for the
* frame number "0".
*/
if (v4l_set_input (dev, input, norm) == -1) {
return (1);
}
if (v4l_check_size (dev, &width, &height) == -1) {
return (1);
}
/*if (v4l_check_palette (dev, &palette) == -1) {
return (1);
}*/
}
switch (format) {
case FMT_YUV4MPEG:
if (palette == VIDEO_PALETTE_YUV420P)
return to_yuv (out, dev, width, height);
break;
}
image = get_image (dev, width, height, palette, &size); //从v4l设备获取rgb图像
if (!size)
close (dev);
if (image) {
switch (format) {
case FMT_PPM:
if (palette == VIDEO_PALETTE_GREY)
put_image_pgm (out, image, width, height, binary);
else
put_image_ppm (out, image, width, height, binary);
break;
case FMT_PGM:
put_image_pgm (out, image, width, height, binary);
break;
case FMT_PNG:
put_image_png (out, image, width, height, palette);
break;
case FMT_JPEG:
put_image_jpeg (out, image, width, height, quality, palette);
break;
default:
fprintf (stderr, "Unknown format (%d)\n", format);
break;
}
if (size) {
munmap (image, size);
close (dev);
} else if (image) {
free (image);
}
if (loop) {
num++;
goto again;
}
} else {
fprintf (stderr, "Error: Can't get image\n");
}
return (0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -