作業日記@HatenaBlog

各種の作業メモ

ビデオキャプチャカードで静止画撮影

BT848チップを搭載したビデオキャプチャカードで静止画をコマ撮りするプログラム。
ファイル名を「vdcap.c」とし、C言語のソースプログラムとする。
以下のサイトに掲載されたソースを参考に切り貼りした。
http://home.jp.freebsd.org/cgi-bin/showmail/FreeBSD-users-jp/19999
http://www.mickey.ai.kyutech.ac.jp/~ohashi/FreeBSD/capture_j.html
すでに消滅したサイト↓
http://web.archive.org/web/20031204181630/http://junkun.vbl.tsukuba.ac.jp/~junkun/capture.html

実際のソース

/* -------------------------------- */
/* Video capturing program on BT848 */
/* 2003/05/08 */
/* -------------------------------- */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
/*#include <getopt.h>*/
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/fcntl.h>
#include <machine/ioctl_meteor.h>
#include <machine/ioctl_bt848.h>

void usage(void)
{
fprintf(stderr, "%s\n",
"usage: vdcap [-r row] [-c col] [-b brightness] [-n contrast] [-s saturation] [-h hue] [-p [0|1|2]] [-v]");
}

extern int errno;

/* for getopt() function */
extern char *optarg;
extern int optind, opterr, optopt;

/* defalut frame size */
#define ROWS 480
#define COLS 640

/* defalut parameters */
int size,
brightness = -1, /* = BT848_BRIGHTCENTER */
contrast = -1, /* = BT848_CONTRASTCENTER */
saturation = -1, /* = BT848_SATUCENTER */
hue = -1, /* = BT848_HUECENTER */
port = METEOR_INPUT_DEV0, /* -p 0:DEV0, 1:DEV1, 2:SVIDEO */
verb = 0; /* -v for debug mode */


/* --------------- */
/* Start of main() */
/* --------------- */

int main(int argc, char *argv[]) {
struct meteor_geomet geo;
char *mmbuf, b[4];
char *p;
int i, c;

/* Allowed device */
char *dev = "/dev/bktr0";
/*
char *dev = "/dev/meteor0";
*/

/* Set default frame */
geo.rows = ROWS;
geo.columns = COLS;
geo.frames = 1;
geo.oformat = METEOR_GEO_RGB24;

/* Get option parameters */
while( getopt(argc, argv, "r:c:b:n:s:h:p:v")!= -1)
{
switch( optopt ) {
case 'r':
geo.rows = atoi(optarg);
break;

case 'c':
geo.columns = atoi(optarg);
break;

case 'b':
brightness = atoi(optarg);
break;

case 'n':
contrast = atoi(optarg);
break;

case 's':
saturation = atoi(optarg);
break;

case 'h':
hue = atoi(optarg);
break;

case 'p':
switch( atoi(optarg) )
{
case 0:
port = METEOR_INPUT_DEV0;
break;
case 1:
port = METEOR_INPUT_DEV1;
break;
case 2:
port = METEOR_INPUT_DEV_SVIDEO;
break;
case '?':
default:
fprintf(stderr,"-p: illegal option!\n");
usage();
exit(1);
}
break;

case 'v':
verb = 1;
break;

case '?':
default:
usage();
exit(1);
}
optarg = NULL;
}

/* Not option strings */
if (optind < argc)
{
while (optind < argc)
{
printf("Not option string: %s\n", argv[optind++]);
}
usage();
exit(1);
}


/* Open device */
if ( (i = open(dev, O_RDONLY) ) < 0)
{
fprintf(stderr, "open failed: %s: %d\n", dev, errno);
exit(1);
}

/* Frame size */
if (ioctl(i, METEORSETGEO, &geo) < 0)
{
fprintf(stderr,"ioctl failed: %d\n", errno);
exit(1);
}

/* Frame format */
c = METEOR_FMT_NTSC;
if (ioctl(i, METEORSFMT, &c) < 0)
{
fprintf(stderr,"ioctl failed: %d\n", errno);
exit(1);
}

/* Input port */
if (ioctl(i, METEORSINPUT, &port) < 0)
{
fprintf(stderr,"ioctl failed: %d\n", errno);
exit(1);
}

/* Contrast */
if (contrast != -1)
{
if (ioctl(i, METEORSCONT, &contrast) < 0)
{
fprintf(stderr,"ioctl failed: %d\n", errno);
exit(1);
}
}

/* Brightness */
if (brightness != -1)
{
if (ioctl(i, METEORSBRIG, &brightness) < 0)
{
fprintf(stderr,"ioctl failed: %d\n", errno);
exit(1);
}
}

/* Saturation */
if (saturation != -1)
{
if (ioctl(i, METEORSCSAT, &saturation) < 0)
{
fprintf(stderr,"ioctl failed: %d\n", errno);
exit(1);
}
}

/* Hue */
if (hue != -1)
{
if (ioctl(i, METEORSHUE, &hue) < 0)
{
fprintf(stderr,"ioctl failed: %d\n", errno);
exit(1);
}
}

/* Define buffering image */
size = geo.rows * geo.columns * 4;
mmbuf = (char *)mmap((caddr_t)0,
size,
PROT_READ,
MAP_SHARED,
i,
(off_t)0);

/* Debug mode */
if (verb)
{
fprintf(stderr, "columns: %d\n", geo.columns);
fprintf(stderr, "rows: %d\n", geo.rows);
fprintf(stderr, "size: %d\n", size);

ioctl(i, METEORGBRIG, &c);
fprintf(stderr, "brightness: %d\n", c & 0xff);

ioctl(i, METEORGCONT, &c);
fprintf(stderr, "contrast: %d\n", c & 0xff);

ioctl(i, METEORGCSAT, &c);
fprintf(stderr, "saturation: %d\n", c & 0xff);

ioctl(i, METEORGHUE, &c);
fprintf(stderr, "hue: %d\n", c & 0xff);

switch( port )
{
case 4096:
fprintf(stderr, "port: 0\n");
break;
case 8192:
fprintf(stderr, "port: 1\n");
break;
case 24576:
fprintf(stderr, "port: S-Video\n");
break;
}

}

/* Continuously capturing frame */
c = METEOR_CAP_CONTINOUS;
ioctl(i, METEORCAPTUR, &c);

sleep(1); /* wait for the frame */

/* make PPM header and print it to stdout */
printf("P6\n%d %d\n255\n", geo.columns, geo.rows);
/* print body */
for (p = &mmbuf[0]; p < &mmbuf[size]; )
{
b[2] = *p++; /* blue */
b[1] = *p++; /* green */
b[0] = *p++; /* red */
*p++;
fputc(b[0], stdout);
fputc(b[1], stdout);
fputc(b[2], stdout);
}

/* Stop continuously frame capture */
c = METEOR_CAP_STOP_CONT;
ioctl(i, METEORCAPTUR, &c);

/* Close device */
close(i);
exit(0);

}

/* ------------- */
/* End of main() */
/* ------------- */