usb camera demo

/*
 * usb_camera_test.c - usb camera capture program
 *
 * Test opening usb camera, reading and saving data from usb camera by hcd.
 */


#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#include <errno.h>
#include <getopt.h> /* getopt_long() */
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <linux/videodev2.h>
#include <sys/ioctl.h>
#include <malloc.h>
#include <sys/mman.h>
#include <unistd.h>



#define CLEAR(x) memset(&(x), 0, sizeof (x))


struct buffer {
void *      start;
size_t      length;
};


typedef struct {
char *data;
unsigned long length;
} frame_t;


struct buffer *         buffers        = NULL;
static unsigned int     n_buffers       = 0;


static int open_device(int *fd, char *dev_name)
{
*fd =open (dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);
if(*fd < 0){
close(*fd);
return -1;
}


return 0;
}


static int init_device (int fd, int force_format, int print_info)
{
struct v4l2_requestbuffers req;
struct v4l2_capability cap;
struct v4l2_cropcap cropcap;
struct v4l2_crop crop;
struct v4l2_format fmt;
unsigned int min;
int ret;
struct v4l2_fmtdesc fmtdesc;


if (-1 == ioctl (fd, VIDIOC_QUERYCAP, &cap)) {
fprintf (stderr, "VIDIOC_QUERYCAP fail\n");
goto err;
}


if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
fprintf (stderr, "VIDIOC_QUERYCAP fail\n");
goto err;
}


if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
fprintf (stderr, "device does not support streaming i/o\n");
goto err;
}


if (print_info) {
/* Print capability infomations */
printf("Capability Informations:\n");
printf(" driver: %s\n", cap.driver);
printf(" card: %s\n", cap.card);
printf(" bus_info: %s\n", cap.bus_info);
printf(" version: %08X\n", cap.version);
}


/* Select video input, video standard and tune here. */
CLEAR (cropcap);


cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (0 == ioctl (fd, VIDIOC_CROPCAP, &cropcap)) {
crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
crop.c = cropcap.defrect; /* reset to default */


if (-1 == ioctl (fd, VIDIOC_S_CROP, &crop)) {
switch (errno) {
case EINVAL:
/* Cropping not supported. */
break;
default:
/* Errors ignored. */
break;
}
}
}


/* enum video formats. */
CLEAR(fmtdesc);
if (print_info) {
fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
printf("Enum format:\n");
while ((ret = ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc)) == 0) {
fmtdesc.index++;
printf(" <%d> pixelformat = \"%c%c%c%c\", description = %s\n",fmtdesc.index,
fmtdesc.pixelformat & 0xFF,
(fmtdesc.pixelformat >> 8) & 0xFF,
(fmtdesc.pixelformat >> 16) & 0xFF,
(fmtdesc.pixelformat >> 24) & 0xFF,
fmtdesc.description);
}
}


/* set video formats. */
CLEAR (fmt);
char * p = (char *)(&fmt.fmt.pix.pixelformat);
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (force_format) {
if (ioctl (fd, VIDIOC_G_FMT, &fmt) < 0) {
/* Errors ignored. */
printf("get fmt fail\n");
}


//fmt.fmt.pix.width       = width;
//fmt.fmt.pix.height      = height;
//    init_mem_repo();
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;


if (-1 == ioctl (fd, VIDIOC_S_FMT, &fmt)){
printf("set format fail\n");
// return -1;
}
}


if (print_info) {
if (ioctl (fd, VIDIOC_G_FMT, &fmt) < 0) {
/* Errors ignored. */
printf("get fmt fail\n");
}


printf("Used fmt:\n");
printf(" fmt.type = %d\n", fmt.type);
printf(" fmt.width = %d\n", fmt.fmt.pix.width);
printf(" fmt.height = %d\n", fmt.fmt.pix.height);
printf(" fmt.format = %c%c%c%c\n", p[0], p[1], p[2], p[3]);
printf(" fmt.field = %d\n", fmt.fmt.pix.field);
}


/* Buggy driver paranoia. */
min = fmt.fmt.pix.width * 2;
if (fmt.fmt.pix.bytesperline < min)
fmt.fmt.pix.bytesperline = min;


min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
if (fmt.fmt.pix.sizeimage < min)
fmt.fmt.pix.sizeimage = min;


CLEAR (req);
req.count   = 8;
req.type    = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory  = V4L2_MEMORY_MMAP;


if (-1 == ioctl (fd, VIDIOC_REQBUFS, &req)) {
fprintf (stderr, "VIDIOC_QUERYCAP fail\n");
goto err;
}


if (req.count < 2) {
fprintf (stderr, "Insufficient buffer memory\n");
return -1;
}


buffers = calloc (req.count, sizeof (*buffers));
if (!buffers) {
fprintf (stderr, "Out of memory\n");
return -1;
}


for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
struct v4l2_buffer buf;


CLEAR (buf);
buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory      = V4L2_MEMORY_MMAP;
buf.index       = n_buffers;


if (-1 == ioctl (fd, VIDIOC_QUERYBUF, &buf)){
fprintf (stderr, "VIDIOC_QUERYCAP fail\n");
goto err;
}


buffers[n_buffers].length = buf.length;
buffers[n_buffers].start = mmap (NULL /* start anywhere */,
       buf.length,
       PROT_READ | PROT_WRITE /* required */,
       MAP_SHARED /* recommended */,
       fd, buf.m.offset);
if (MAP_FAILED == buffers[n_buffers].start){
fprintf (stderr, "mmap fail\n");
goto err;
}
}


return 0;
err:
return -1;
}


static void errno_exit (const char *s)
{
fprintf (stderr, "%s error %d, %s\n",s, errno, strerror (errno));
exit (EXIT_FAILURE);
}


static void start_capturing (int fd)
{
unsigned int i;
int ret;
enum v4l2_buf_type type;


//printf("n_buffers:%d\n",n_buffers);
for (i = 0; i < n_buffers; ++i) {
struct v4l2_buffer buf;


CLEAR (buf);


buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory      = V4L2_MEMORY_MMAP;
buf.index       = i;
ret = ioctl (fd, VIDIOC_QBUF, &buf);
if (-1 == ret)
errno_exit ("VIDIOC_QBUF");
}


type = V4L2_BUF_TYPE_VIDEO_CAPTURE;


ret = ioctl(fd, VIDIOC_STREAMON, &type);
if (-1 == ret)
errno_exit ("VIDIOC_STREAMON");
}


static void stop_capturing(int fd)
{
int ret;
enum v4l2_buf_type type;


type = V4L2_BUF_TYPE_VIDEO_CAPTURE;


ret = ioctl(fd, VIDIOC_STREAMOFF, &type);
if (-1 == ret)
errno_exit("VIDIOC_STREAMOFF");
}


static void uninit_device(void)
{
unsigned int i;


for (i = 0; i < n_buffers; ++i)
if (-1 == munmap(buffers[i].start, buffers[i].length))
errno_exit("munmap");
free(buffers);
}


static void close_device(int fd)
{
if (-1 == close(fd))
errno_exit("close");


fd = -1;
}


/*
 * read a frame of image from video device
 */
static int get_buffer(int fd, struct v4l2_buffer *v4l_buf)
{
if (-1 == ioctl(fd, VIDIOC_DQBUF, v4l_buf))
return 0;


return 1;
}


/*
 * enqueue the frame again
 */
static int put_buffer(int fd, struct v4l2_buffer *v4l_buf)
{
return ioctl(fd, VIDIOC_QBUF, v4l_buf);
}


static void get_fps(int fd)
{
struct v4l2_streamparm* getfps;


getfps=(struct v4l2_streamparm *) calloc(1, sizeof(struct v4l2_streamparm));
memset(getfps, 0, sizeof(struct v4l2_streamparm));
getfps->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;


if(ioctl(fd, VIDIOC_G_PARM, getfps) < 0){
/* Errors ignored. */
printf("get fps fail\n");
}
printf(" getfps.numerator = %d, getfps.denominator = %d\n",
getfps->parm.capture.timeperframe.numerator,
getfps->parm.capture.timeperframe.denominator);
}


static void usage(FILE *fp, char **argv, char *dev_name, int frame_count, char *pict_path)
{
fprintf(fp,
"Usage: %s [options]\n\n"
"Version 1.0\n"
"Options:\n"
"-d | --device name   Video device name [%s]\n"
"-h | --help          Print this message\n"
"-o | --output        Outputs stream to jpeg pict\n"
"-f | --format        Force format to MJPEG\n"
"-c | --count         Number of frames to grab [%i]\n"
"-p | --path          pict output path [%s]\n"
"-i | --info          print debug info\n"
"",
argv[0], dev_name, frame_count, pict_path);
}


static const char short_options[] = "d:hofc:p:i";


static const struct option
long_options[] = {
{ "device", required_argument, NULL, 'd' },
{ "help",   no_argument,       NULL, 'h' },
{ "output", no_argument,       NULL, 'o' },
{ "format", no_argument,       NULL, 'f' },
{ "count",  required_argument, NULL, 'c' },
{ "path",   required_argument, NULL, 'p' },
{ "info",   no_argument,       NULL, 'i' },
{ 0, 0, 0, 0 }
};




int main(int argc, char **argv)
{
char *dev_name = "/dev/video0";
char *pict_path = "/";
int fd_cam =  -1;
int fd_pict = -1;
// int out_buf;
int out_buf = 1; 
int force_format;
int frame_count = 2;
// int print_info = 0;
int print_info = 1;
int r, i, ret;
struct timeval tv;
fd_set fds;
char file[20];
frame_t *fm = malloc(sizeof(frame_t));
struct v4l2_buffer buf;


buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;


for (;;) {
int idx;
int c;


c = getopt_long(argc, argv,
short_options, long_options, &idx);


if (-1 == c)
break;


switch (c) {
case 0: /* getopt_long() flag */
break;
case 'd':
dev_name = optarg;
break;
case 'h':
usage(stdout, argv, dev_name, frame_count, pict_path);
exit(EXIT_SUCCESS);
case 'o':
out_buf++;
break;
case 'f':
force_format++;
break;
case 'c':
errno = 0;
frame_count = strtol(optarg, NULL, 0);
if (errno)
errno_exit(optarg);
break;
case 'p':
pict_path = optarg;
break;
case 'i':
print_info++;
break;
default:
usage(stderr, argv, dev_name, frame_count, pict_path);
exit(EXIT_FAILURE);
}
}


fprintf(stdout, "===usb camera test start===\n");
if (print_info)
printf("open and init camera\n");
ret = open_device(&fd_cam, dev_name);
if (ret == -1) {
printf("open camera failed\n");
return -1;
}


ret = init_device (fd_cam, force_format, print_info);
if (ret == -1) {
      printf("init camera failed\n");
return -1;
}


if (print_info)
printf("start capturing\n");
start_capturing (fd_cam);


for(i = 0; i < frame_count; i++)
{
FD_ZERO (&fds);
FD_SET (fd_cam, &fds);
tv.tv_sec = 2;
tv.tv_usec = 0;


r = select (fd_cam + 1, &fds, NULL, NULL, &tv);


r = get_buffer(fd_cam, &buf);


fm->data = buffers[buf.index].start;
fm->length = buf.bytesused;


if(r != 0) {
int flag = 0;


if (out_buf) {
sprintf(file,"%s/pic%d.jpg", pict_path, i);
fd_pict = open(file, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if(fd_pict != -1) {
if (print_info) {
flag = 1;
printf(" open pic%d and write\n", i);
}
write(fd_pict, fm->data, fm->length);
close(fd_pict);
}
}
if (flag == 0 && print_info == 0) {
fflush(stdout);
fprintf(stdout, ".");
}
}


put_buffer(fd_cam, &buf);
if (print_info)
get_fps(fd_cam);
}


if (print_info)
printf("stop capturing, close camera\n");
stop_capturing(fd_cam);
uninit_device();
close_device(fd_cam);
fprintf(stdout, "\n===usb camera test done===\n");


return 0;

}


#if   0
usb_camera_test.c is used to test opening usb camera,
reading and saving data from usb camera by hcd.

You can use it as bolow, for example:

(1) ./usb_camera_test -o -f -c 2
Func Desc: open "/dev/video0", save stream as jpeg picture
to "/" catalog, set format as MJPEG, save 2 frames data.

(2) ./usb_camera_test -o -p "/mnt/" -f -c 2 -i
Func Desc: open "/dev/video0", save stream as jpeg picture
to "/mnt/" catalog, set format as MJPEG, save 2 frames data,
print debug info.

(3) ./usb_camera_test -d "/dev/video1" -i
Func Desc: open "/dev/video1", print debug info, not save
stream data.

#endif

make file:



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值