基于v4l2(linux 2.6)的视频采集(ARM9+TVP5150)YUV420数据,下面是我的程序:<br /><br />#ifdef __cplusplus<br />extern "C"{<br />#endif<br /><br />/*=======================================================================<br /> INCLUDE FILES<br />=======================================================================*/<br />/* Standard Include Files */<br />#include <errno.h><br /> <br />/* Verification Test Environment Include Files */<br />#include <sys/types.h> <br />#include <sys/stat.h> <br />#include <fcntl.h><br />#include <sys/ioctl.h><br />#include <unistd.h> <br />#include <stdint.h><br />#include <stdio.h><br />#include <stdlib.h><br />#include <asm/types.h><br />#include <linux/compiler.h><br />#include <linux/videodev.h><br />#include <sys/mman.h><br />#include <string.h><br />#include <malloc.h><br />//#include <asm/arch/mxc_v4l2.h><br /><br />struct v4l2_mxc_offset {<br /> uint32_t u_offset;<br /> uint32_t v_offset;<br />};<br /><br />#define TEST_BUFFER_NUM 3<br /><br />struct testbuffer<br />{<br /> unsigned char *start;<br /> size_t offset;<br /> unsigned int length;<br />};<br /><br />struct testbuffer buffers[TEST_BUFFER_NUM];<br />int g_width = 352;<br />int g_height = 288;<br />int g_capture_count = 3;<br />int g_rotate = 0;<br />int g_cap_fmt = V4L2_PIX_FMT_YUV420;<br />int g_camera_framerate = 30;<br />int g_extra_pixel = 0;<br /><br />int start_capturing(int fd_v4l)<br />{<br /> unsigned int i;<br /> struct v4l2_buffer buf;<br /> enum v4l2_buf_type type;<br /><br /> for (i = 0; i < TEST_BUFFER_NUM; i++)<br /> {<br /> memset(&buf, 0, sizeof (buf));<br /> buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;<br /> buf.index = i;<br /> if (ioctl(fd_v4l, VIDIOC_QUERYBUF, &buf) < 0)<br /> {<br /> printf("VIDIOC_QUERYBUF error
");<br /> return -1;<br /> }<br /><br /> buffers.length = buf.length;<br /> buffers.offset = (size_t) buf.m.offset;<br /> buffers.start = mmap (NULL, buffers.length,<br /> PROT_READ | PROT_WRITE, MAP_SHARED,<br /> fd_v4l, buffers.offset);<br /> memset(buffers.start, 0xFF, buffers.length);<br /> }<br /><br /> for (i = 0; i < TEST_BUFFER_NUM; i++)<br /> {<br /> memset(&buf, 0, sizeof (buf));<br /> buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;<br /> buf.memory = V4L2_MEMORY_MMAP;<br /> buf.index = i;<br /> buf.m.offset = buffers.offset;<br /> if (g_extra_pixel){<br /> buf.m.offset += g_extra_pixel *<br /> (g_width + 2 * g_extra_pixel) + g_extra_pixel;<br /> }<br /><br /> if (ioctl (fd_v4l, VIDIOC_QBUF, &buf) < 0) {<br /> printf("VIDIOC_QBUF error
");<br /> return -1;<br /> }<br /> }<br /><br /> type = V4L2_BUF_TYPE_VIDEO_CAPTURE;<br /> if (ioctl (fd_v4l, VIDIOC_STREAMON, &type) < 0) {<br /> printf("VIDIOC_STREAMON error
");<br /> return -1;<br /> }<br /> return 0;<br />}<br /><br />int stop_capturing(int fd_v4l)<br />{<br /> enum v4l2_buf_type type;<br /><br /> type = V4L2_BUF_TYPE_VIDEO_CAPTURE;<br /> return ioctl (fd_v4l, VIDIOC_STREAMOFF, &type);<br />}<br /><br />int v4l_capture_setup(void)<br />{<br /> char v4l_device[100] = "/dev/v4l/video0";<br /> struct v4l2_format fmt;<br /> struct v4l2_control ctrl;<br /> struct v4l2_streamparm parm;<br /> int fd_v4l = 0;<br /> struct v4l2_mxc_offset off;<br /> <br /> if ((fd_v4l = open(v4l_device, O_RDWR, 0)) < 0)<br /> {<br /> printf("Unable to open %s
", v4l_device);<br /> return 0;<br /> }<br /> <br /> struct v4l2_crop crop;<br /> memset(&crop, 0, sizeof (crop));<br /> crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;<br /> crop.c.left = 0;<br /> crop.c.top = 0;<br /> crop.c.width = 640;<br /> crop.c.height = 288; <br /> if (ioctl(fd_v4l, VIDIOC_S_CROP, &crop) < 0)<br /> {<br /> printf("set cropping failed
");<br /> }<br /> <br /> fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;<br /> fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;<br /> fmt.fmt.pix.width = g_width;<br /> fmt.fmt.pix.height = g_height;<br /> if (g_extra_pixel){<br /> off.u_offset = (2 * g_extra_pixel + g_width) * (g_height + g_extra_pixel)<br /> - g_extra_pixel + (g_extra_pixel / 2) * ((g_width / 2)<br /> + g_extra_pixel) + g_extra_pixel / 2; <br /> off.v_offset = off.u_offset + (g_extra_pixel + g_width / 2) *<br /> ((g_height / 2) + g_extra_pixel); <br /> fmt.fmt.pix.bytesperline = g_width + g_extra_pixel * 2;<br /> fmt.fmt.pix.priv = (uint32_t) &off;<br /> fmt.fmt.pix.sizeimage = (g_width + g_extra_pixel * 2 )<br /> * (g_height + g_extra_pixel * 2) * 3 / 2;<br /> } else {<br /> fmt.fmt.pix.bytesperline = g_width;<br /> printf("bytesperline: %d
", fmt.fmt.pix.bytesperline);<br /> fmt.fmt.pix.priv = 0;<br /> fmt.fmt.pix.sizeimage = 0;<br /> }<br /><br /> if (ioctl(fd_v4l, VIDIOC_S_FMT, &fmt) < 0)<br /> {<br /> printf("set format failed
");<br /> return 0;<br /> }<br /><br /> parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;<br /> parm.parm.capture.timeperframe.numerator = 1;<br /> parm.parm.capture.timeperframe.denominator = g_camera_framerate;<br /> parm.parm.capture.capturemode = 0;<br /> <br /> if (ioctl(fd_v4l, VIDIOC_S_PARM, &parm) < 0)<br /> {<br /> printf("VIDIOC_S_PARM failed
");<br /> return -1;<br /> }<br /><br /> // Set rotation<br /> ctrl.id = V4L2_CID_PRIVATE_BASE + 0;<br /> ctrl.value = g_rotate;<br /> if (ioctl(fd_v4l, VIDIOC_S_CTRL, &ctrl) < 0)<br /> {<br /> printf("set ctrl failed
");<br /> return 0;<br /> }<br /><br /> struct v4l2_requestbuffers req;<br /> memset(&req, 0, sizeof (req));<br /> req.count = TEST_BUFFER_NUM;<br /> req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;<br /> req.memory = V4L2_MEMORY_MMAP;<br /><br /> if (ioctl(fd_v4l, VIDIOC_REQBUFS, &req) < 0)<br /> {<br /> printf("v4l_capture_setup: VIDIOC_REQBUFS failed
");<br /> return 0;<br /> }<br /><br /> return fd_v4l;<br />}<br /><br />int v4l_capture_test(int fd_v4l, const char * file)<br />{<br /> struct v4l2_buffer buf;<br />#if TEST_OUTSYNC_ENQUE<br /> struct v4l2_buffer temp_buf;<br />#endif<br /> struct v4l2_format fmt;<br /> FILE * fd_y_file = 0;<br /> int count = g_capture_count;<br /> <br /> if ((fd_y_file = fopen(file, "wb")) < 0)<br /> {<br /> printf("Unable to create y frame recording file
");<br /> return -1;<br /> }<br /><br /> fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;<br /> if (ioctl(fd_v4l, VIDIOC_G_FMT, &fmt) < 0)<br /> {<br /> printf("get format failed
");<br /> return -1;<br /> }<br /> else<br /> {<br /> printf(" Width = %d", fmt.fmt.pix.width);<br /> printf(" Height = %d", fmt.fmt.pix.height);<br /> printf(" Image size = %d
", fmt.fmt.pix.sizeimage);<br /> printf(" pixelformat = %d
", fmt.fmt.pix.pixelformat);<br /> }<br /><br /> if (start_capturing(fd_v4l) < 0)<br /> {<br /> printf("start_capturing failed
");<br /> return -1;<br /> }<br /><br /> while (count-- > 0) {<br /> memset(&buf, 0, sizeof (buf));<br /> buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;<br /> buf.memory = V4L2_MEMORY_MMAP;<br /> if (ioctl (fd_v4l, VIDIOC_DQBUF, &buf) < 0) {<br /> printf("VIDIOC_DQBUF failed.
");<br /> }<br /><br /> fwrite(buffers[buf.index].start, fmt.fmt.pix.sizeimage, 1, fd_y_file);<br /><br />#if TEST_OUTSYNC_ENQUE<br /> /* Testing out of order enque */<br /> if (count == 25) {<br /> temp_buf = buf;<br /> printf("buf.index %d
", buf.index);<br /> continue;<br /> }<br /><br /> if (count == 15) {<br /> if (ioctl (fd_v4l, VIDIOC_QBUF, &temp_buf) < 0) {<br /> printf("VIDIOC_QBUF failed
");<br /> break;<br /> }<br /> }<br />#endif<br /> if (count >= TEST_BUFFER_NUM) {<br /> if (ioctl (fd_v4l, VIDIOC_QBUF, &buf) < 0) {<br /> printf("VIDIOC_QBUF failed
");<br /> break;<br /> }<br /> }<br /> else<br /> printf("buf.index %d
", buf.index);<br /> }<br /><br /> if (stop_capturing(fd_v4l) < 0)<br /> {<br /> printf("stop_capturing failed
");<br /> return -1;<br /> }<br /><br /> fclose(fd_y_file);<br /><br /> close(fd_v4l);<br /> return 0;<br />}<br /><br /><br />int process_cmdline(int argc, char **argv)<br />{<br /> int i;<br /> <br /> for (i = 1; i < argc; i++) {<br /> if (strcmp(argv, "-w") == 0) {<br /> g_width = atoi(argv[++i]);<br /> }<br /> else if (strcmp(argv, "-h") == 0) {<br /> g_height = atoi(argv[++i]);<br /> }<br /> else if (strcmp(argv, "-r") == 0) {<br /> g_rotate = atoi(argv[++i]);<br /> }<br /> else if (strcmp(argv, "-c") == 0) {<br /> g_capture_count = atoi(argv[++i]);<br /> }<br /> else if (strcmp(argv, "-fr") == 0) {<br /> g_camera_framerate = atoi(argv[++i]);<br /> }<br /> else if (strcmp(argv, "-e") == 0) {<br /> g_extra_pixel = atoi(argv[++i]);<br /> }<br /> else if (strcmp(argv, "-f") == 0) {<br /> i++;<br /> g_cap_fmt = v4l2_fourcc(argv[0], argv[1],argv[2],argv[3]);<br /><br /> if ( (g_cap_fmt != V4L2_PIX_FMT_BGR24) &&<br /> (g_cap_fmt != V4L2_PIX_FMT_BGR32) &&<br /> (g_cap_fmt != V4L2_PIX_FMT_RGB565) &&<br /> (g_cap_fmt != V4L2_PIX_FMT_YUV420) )<br /> {<br /> return -1;<br /> }<br /> }<br /> else if (strcmp(argv, "-help") == 0) {<br /> printf("MXC Video4Linux capture Device Test
" <br /> "Syntax: mxc_v4l2_capture.out -w <capture width>
" <br /> " -h <capture height>
" <br /> " -r <rotation> -c <capture counter>
"<br /> " -e <destination cropping: extra pixels>
" <br /> " -f <format> -fr <frame rate, 0-auto>
");<br /> return -1;<br /> }<br /> }<br /><br /> printf("g_width = %d, g_height = %d
", g_width, g_height);<br /> <br /> if ((g_width == 0) || (g_height == 0)) {<br /> return -1;<br /> }<br /> return 0;<br />}<br /><br />int main(int argc, char **argv)<br />{<br /> int fd_v4l;<br /><br /> if (process_cmdline(argc, argv) < 0) {<br /> return -1;<br /> }<br /> fd_v4l = v4l_capture_setup();<br /> return v4l_capture_test(fd_v4l, argv[argc-1]);<br />}<br /><br />现在采集出来的图像在垂直面上有两幅相同的。<br />不知道还有哪个参数不对。 |
|