I found a test program on the Internet and looked at it. It was modified according to capture. C. The test procedure is as follows:
1. GCC-O capture_image capture_image.c
2. Switch CTRL + ALT + F1 to the Ubuntu console. Switch to the console mode because the test image is not visible in the graphic mode, which may be related to the framebuffer settings.
3. sudo modprobe Vivi
4. sudo./capture_image-D/dev/video0
At this time, we can see that there is a 640xlarge window in the upper left corner of the screen, the content is a color bar, the color bar keeps moving, lasting for 5 seconds
You can also use cheese for testing in Ubuntu.
1. sudo apt-Get install cheese
2. sudo modprobe Vivi
2. After cheese is started, you can see the scroll color bar.
Attached Test Procedure
# Include <stdio. h> <br/> # include <stdlib. h> <br/> # include <string. h> <br/> # include <assert. h> <br/> # include <getopt. h> <br/> # include <fcntl. h> <br/> # include <unistd. h> <br/> # include <errno. h> <br/> # include <sys/STAT. h> <br/> # include <sys/types. h> <br/> # include <sys/time. h> <br/> # include <sys/Mman. h> <br/> # include <sys/IOCTL. h> <br/> # include <ASM/types. h> <br/> # include <Linux/videodev2.h> <br/> # InCl Ude <Linux/FB. h> <br/> # define clear (x) memset (& (x), 0, sizeof (x )) </P> <p> struct buffer {<br/> void * start; <br/> size_t length; <br/> }; </P> <p> static char * dev_name = NULL; <br/> static int FD =-1; <br/> struct buffer * buffers = NULL; <br/> static unsigned int n_buffers = 0; <br/> static int time_in_sec_capture = 5; <br/> static int fbfd =-1; <br/> static struct fb_var_screeninfo vinfo; <br/> static Struct fb_fix_screeninfo finfo; <br/> static char * FBP = NULL; <br/> static long screensize = 0; </P> <p> static void errno_exit (const char * s) <br/> {<br/> fprintf (stderr, "% s error % d, % s/n ", S, errno, strerror (errno); <br/> exit (exit_failure ); <br/>}</P> <p> static int xioctl (int fd, int request, void * Arg) <br/>{< br/> int R; <br/> do r = IOCTL (FD, request, ARG); <br/> while (-1 = R & eintr = ER Rno); <br/> return r; <br/>}</P> <p> inline int clip (INT value, int min, int max) {<br/> return (value> Max? MAX: value <min? Min: value); <br/>}</P> <p> static void process_image (const void * P) {</P> <p> // convertyuvtorgb32 <br/> 1; <br/> unsigned char * In = (char *) P; <br/> int width = 640; <br/> int Height = 480; <br/> int istride = 1280; <br/> int X, Y, J; <br/> int y0, U, Y1, V, R, G, B; <br/> long location = 0; </P> <p> for (y = 100; y <peight + 100; ++ y) {<br/> for (j = 0, x = 100; j <width * 2; j + = 4, x + = 2) {<br/> location = (x + V Info. xoffset) * (vinfo. bits_per_pixel/8) + <br/> (Y + vinfo. yoffset) * finfo. line_length; </P> <p> Y0 = in [J]; <br/> U = in [J + 1]-128; <br/> Y1 = in [J + 2]; <br/> V = in [J + 3]-128; </P> <p> r = (298 * y0 + 409 * V + 128)> 8; <br/> G = (298 * y0-100 * U-208 * V + 128)> 8; <br/> B = (298 * y0 + 516 * u + 128)> 8; </P> <p> FBP [location + 0] = clip (B, 0,255); <br/> FBP [location + 1] = clip (G, 0,255); <br/> FBP [location + 2] = clip (R, 0,255); <br/> FBP [location + 3] = 255; </P> <p> r = (298 * Y1 + 409 * V + 128)> 8; <br/> G = (298 * Y1-100 * U-208 * V + 128)> 8; <br/> B = (298 * Y1 + 516 * u + 128)> 8; </P> <p> FBP [location + 4] = clip (B, 0,255); <br/> FBP [location + 5] = clip (G, 0,255); <br/> FBP [location + 6] = clip (R, 0,255 ); <br/> FBP [location + 7] = 255; <br/>} <Br/> in + = istride; <br/>}</P> <p> static int read_frame (void) <br/>{< br/> struct v4l2_buffer Buf; <br/> unsigned int I; </P> <p> clear (BUF); <br/> Buf. type = v4l2_buf_type_video_capture; <br/> Buf. memory = v4l2_memory_mmap; </P> <p> If (-1 = xioctl (FD, vidioc_dqbuf, & BUF) {<br/> switch (errno) {<br/> case eagain: <br/> return 0; <br/> case EIO: </P> <p> default: <br/> errno_exit ("vid Ioc_dqbuf "); <br/>}</P> <p> assert (BUF. index <n_buffers); <br/> printf ("v4l2_pix_format-> Field (% d)/n", Buf. field); <br/> // assert (BUF. field = v4l2_field_none); <br/> process_image (buffers [Buf. index]. start); <br/> If (-1 = xioctl (FD, vidioc_qbuf, & BUF) <br/> errno_exit ("vidioc_qbuf "); </P> <p> return 1; <br/>}</P> <p> static void run (void) <br/>{< br/> unsigned int count; <br/> int fram Es; <br/> frames = 30 * time_in_sec_capture; </P> <p> while (frames --> 0) {<br/> (;;) {<br/> fd_set FDS; <br/> struct timeval TV; <br/> int R; <br/> fd_zero (& FDs ); <br/> fd_set (FD, & FDs); </P> <p> TV. TV _sec = 2; <br/> TV. TV _usec = 0; </P> <p> r = select (FD + 1, & FDS, null, null, & TV ); </P> <p> If (-1 = r) {<br/> If (eintr = errno) <br/> continue; <br/> errno_exit ("select"); <br/>}</P> <p> If (0 = r) {<br/> fprintf (stderr, "select timeout/N"); <br/> exit (exit_failure ); <br/>}</P> <p> If (read_frame () <br/> break; </P> <p >}< br/>}</P> <p> static void stop_capturing (void) <br/>{< br/> Enum v4l2_buf_type; </P> <p> type = v4l2_buf_type_video_capture; <br/> If (-1 = xioctl (FD, vidioc_streamoff, & type) <br/> errno_exit ("vidioc_streamoff"); <br/>}</P> <p> static void start_c Apturing (void) <br/>{< br/> unsigned int I; <br/> Enum v4l2_buf_type; </P> <p> for (I = 0; I <n_buffers; ++ I) {<br/> struct v4l2_buffer Buf; <br/> clear (BUF); </P> <p> Buf. type = v4l2_buf_type_video_capture; <br/> Buf. memory = v4l2_memory_mmap; <br/> Buf. index = I; </P> <p> If (-1 = xioctl (FD, vidioc_qbuf, & BUF) <br/> errno_exit ("vidioc_qbuf "); <br/>}</P> <p> type = v4l2_buf_type_video_capt Ure; </P> <p> If (-1 = xioctl (FD, vidioc_streamon, & type) <br/> errno_exit ("vidioc_streamon "); </P> <p >}</P> <p> static void uninit_device (void) <br/>{< br/> unsigned int I; </P> <p> for (I = 0; I <n_buffers; ++ I) <br/> If (-1 = munmap (buffers [I]. start, buffers [I]. length) <br/> errno_exit ("munmap"); </P> <p> If (-1 = munmap (FBP, screensize )) {<br/> printf ("error: framebuffer device munmap () Fai LED. /n "); <br/> exit (exit_failure); <br/>}< br/> free (buffers ); <br/>}</P> <p> static void init_mmap (void) <br/>{< br/> struct v4l2_requestbuffers req; </P> <p> // MMAP framebuffer <br/> FBP = (char *) MMAP (null, screensize, prot_read | prot_write, map_shared, fbfd, 0 ); <br/> If (INT) FBP =-1) {<br/> printf ("error: failed to map framebuffer device to memory. /n "); <br/> exit (exit_failure); <br/>} <Br/> memset (FBP, 0, screensize); <br/> clear (req); </P> <p> req. count = 4; <br/> req. type = v4l2_buf_type_video_capture; <br/> req. memory = v4l2_memory_mmap; </P> <p> If (-1 = xioctl (FD, vidioc_reqbufs, & req) {<br/> If (einval = errno) {<br/> fprintf (stderr, "% s does not support memory mapping/N", dev_name); <br/> exit (exit_failure ); <br/>} else {<br/> errno_exit ("vidioc_reqbufs"); <br/>} <Br/>}</P> <p> If (req. count <4) {// If (req. count <2) <br/> fprintf (stderr, "insufficient buffer memory on % s/n", dev_name); <br/> exit (exit_failure ); <br/>}</P> <p> buffers = calloc (req. count, sizeof (* buffers); </P> <p> If (! Buffers) {<br/> fprintf (stderr, "out of memory/N"); <br/> exit (exit_failure ); <br/>}</P> <p> for (n_buffers = 0; n_buffers <req. count; ++ n_buffers) {<br/> struct v4l2_buffer Buf; </P> <p> clear (BUF); </P> <p> Buf. type = v4l2_buf_type_video_capture; <br/> Buf. memory = v4l2_memory_mmap; <br/> Buf. index = n_buffers; </P> <p> If (-1 = xioctl (FD, vidioc_querybuf, & BUF) <br/> errno_exit ("vidioc_query Buf "); </P> <p> buffers [n_buffers]. length = Buf. length; <br/> buffers [n_buffers]. start = MMAP (null, Buf. length, prot_read | prot_write, map_shared, FD, Buf. m. offset); </P> <p> If (map_failed = buffers [n_buffers]. start) <br/> errno_exit ("MMAP"); <br/>}</P> <p> static void init_device (void) <br/>{< br/> struct v4l2_capability cap; <br/> struct v4l2_cropcap cropcap; <br/> struct v4l2_crop crop; <br /> Struct v4l2_format FMT; <br/> unsigned int min; </P> <p> // get fixed screen information <br/> If (-1 = xioctl (fbfd, fbioget_fscreeninfo, & finfo )) {<br/> printf ("error reading fixed information. /n "); <br/> exit (exit_failure ); <br/>}</P> <p> // get variable screen information <br/> If (-1 = xioctl (fbfd, fbioget_vscreeninfo, & vinfo )) {<br/> printf ("error reading variable information. /n "); <br/> E Xit (exit_failure); <br/>}< br/> screensize = vinfo. xres * vinfo. yres * vinfo. bits_per_pixel/8; </P> <p> If (-1 = xioctl (FD, vidioc_querycap, callback) {<br/> If (einval = errno) {<br/> fprintf (stderr, "% s is no v4l2 device/N", dev_name); <br/> exit (exit_failure ); <br/>} else {<br/> errno_exit ("vidioc_querycap"); <br/>}</P> <p> If (! (Cap. capabilities & v4l2_cap_video_capture) {<br/> fprintf (stderr, "% s is no video capture device/N", dev_name); <br/> exit (exit_failure ); <br/>}</P> <p> If (! (Cap. capabilities & v4l2_cap_streaming) {<br/> fprintf (stderr, "% s does not support streaming I/O/N", dev_name); <br/> exit (exit_failure ); <br/>}</P> <p> clear (cropcap); </P> <p> cropcap. type = v4l2_buf_type_video_capture; </P> <p> If (0 = xioctl (FD, vidioc_cropcap, & cropcap) {<br/> crop. type = v4l2_buf_type_video_capture; <br/> crop. C = cropcap. defrect; </P> <p> If (-1 = xioctl (FD, vidioc_s_cr Op, & crop) {<br/> switch (errno) {<br/> case einval: <br/> break; <br/> default: <br/> break; <br/>}< br/>}else {}</P> <p> clear (FMT ); </P> <p> FMT. type = v4l2_buf_type_video_capture; <br/> FMT. FMT. PIX. width = 640; <br/> FMT. FMT. PIX. height = 480; <br/> FMT. FMT. PIX. pixelformat = v4l2_pix_fmt_yuyv; <br/> FMT. FMT. PIX. field = v4l2_field_interlaced; </P> <p> If (-1 = xioctl (FD, vidioc_s_fmt, & FMT) <br/> errno_exit ("vidioc_s_fmt"); </P> <p> init_mmap (); </P> <p >}</P> <p> static void close_device (void) <br/>{< br/> If (-1 = close (FD) <br/> errno_exit ("close"); <br/> FD =-1; <br/> close (fbfd); <br/>}</P> <p> static void open_device (void) <br/>{< br/> struct stat st; </P> <p> If (-1 = Stat (dev_name, & St) {<br/> fprintf (stderr, "cannot identify '% s ': % d, % s/n ", dev_name, errno, stre Rror (errno); <br/> exit (exit_failure); <br/>}</P> <p> If (! S_ischr (St. st_mode) {<br/> fprintf (stderr, "% s is no device/N", dev_name); <br/> exit (exit_failure ); <br/>}</P> <p> // open framebuffer <br/> fbfd = open ("/dev/fb0", o_rdwr ); <br/> If (fbfd =-1) {<br/> printf ("error: cannot open framebuffer device. /n "); <br/> exit (exit_failure); <br/>}</P> <p> // open camera <br/> FD = open (dev_name, o_rdwr | o_nonblock, 0); </P> <p> If (-1 = FD) {<br/> fprintf (stderr, "cannot open '% s ': % d, % s/n ", dev_name, errno, strerror (errno); <br/> exit (exit_failure ); <br/>}</P> <p> static void usage (File * FP, int argc, char ** argv) <br/> {<br/> fprintf (FP, <br/> "Usage: % s [Options]/n" <br/> "Options: /n "<br/>"-d | -- device name video device name [/dev/Video]/n "<br/>"-H | -- help print this message/ N "<br/>"-T | -- How long will display in seconds/N "<br/> "", <br/> argv [0]); <br/>}</P> <p> static const char short_options [] = "D: Ht :"; <br/> static const struct option long_options [] = {<br/> {"device", required_argument, null, 'D'}, <br/> {"help ", no_argument, null, 'H'}, <br/> {"time", no_argument, null, 't'}, <br/> {0, 0, 0, 0 }< br/>}; </P> <p> int main (INT argc, char ** argv) <br/>{< br/> dev_name = "/dev/video0"; </P> <p> (;;) <br/>{< br/> int index; <br/> int C; </P> <p> C = getopt_long (argc, argv, short_options, long_options, & Index); <br/> If (-1 = C) <br/> break; </P> <p> switch (c) {<br/> case 0: <br/> break; </P> <p> case 'D': <br/> dev_name = optarg; <br/> break; </P> <p> case 'H': <br/> usage (stdout, argc, argv); <br/> exit (exit_success ); <br/> case 'T': <br/> time_in_sec_capture = atoi (optarg); <br/> break; </P> <p> default: <br/> usage (stderr, argc, argv); <br/> exit (exit_failure ); <br/>}</P> <p> open_device (); </P> <p> init_device (); </P> <p> start_capturing (); </P> <p> Run (); </P> <p> stop_capturing (); </P> <p> uninit_device (); </P> <p> close_device (); </P> <p> exit (exit_success ); </P> <p> return 0; <br/>}
This test program is based on the hard code of the VIVI driver and is not necessarily suitable for other camera drivers.
For example, Logitech stv06xx USB camera on hand does not support the 640x480 mode. For more information, see the 60 lines in code 59,
Line 2 of the Code, if (-1 = xioctl (FD, vidioc_s_fmt, & FMT), should be a negotiation process,
343 FMT. FMT. pix. width = 640;
344 FMT. FMT. pix. Height = 480;
345 FMT. FMT. pix. pixelformat = v4l2_pix_fmt_yuyv;
346 FMT. FMT. pix. Field = v4l2_field_interlaced;
These rows are only the expected format of the application. The driver selects a similar format to return the result. The final display processing of the application must be performed based on the returned format, that is, process_image must be modified accordingly.