-
-
Save dponchalee/8f5d6c132135e83cee08dff28ff2e2c1 to your computer and use it in GitHub Desktop.
Capture single image V4L2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Driver Caps: | |
| Driver: "omap3" | |
| Card: "omap3/mt9v032//" | |
| Bus: "" | |
| Version: 0.0 | |
| Capabilities: 04000001 | |
| Camera Cropping: | |
| Bounds: 752x480+0+0 | |
| Default: 752x480+0+0 | |
| Aspect: 1/1 | |
| FMT : CE Desc | |
| -------------------- | |
| UYVY: UYVY, packed | |
| YUYV: YUYV (YUV 4:2:2), packed | |
| BA10: Bayer10 (GrR/BGb) | |
| Selected Camera Mode: | |
| Width: 752 | |
| Height: 480 | |
| PixFmt: BA10 | |
| Field: 1 | |
| Length: 724992 | |
| Address: 0x40156000 | |
| Image Length: 0 | |
| omap-iommu omap-iommu.0: omap2_iommu_fault_isr: da:000c0000 translation fault | |
| omap-iommu omap-iommu.0: iommu_fault_handler: da:000c0000 pgd:dfd10000 *pgd:9f4d1c01 pte:df4d1f00 *pte:00000000 | |
| omap-iommu omap-iommu.0: omap2_iommu_fault_isr: da:000c0000 translation fault | |
| omap-iommu omap-iommu.0: iommu_fault_handler: da:000c0000 pgd:dfd10000 *pgd:9f4d1c01 pte:df4d1f00 *pte:00000000 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <errno.h> | |
| #include <fcntl.h> | |
| #include <linux/videodev2.h> | |
| #include <stdint.h> | |
| #include <stdio.h> | |
| #include <string.h> | |
| #include <sys/ioctl.h> | |
| #include <sys/mman.h> | |
| #include <unistd.h> | |
| void *buffer; | |
| static int xioctl(int fd, int request, void *arg) | |
| { | |
| int r; | |
| do r = ioctl (fd, request, arg); | |
| while (-1 == r && EINTR == errno); | |
| return r; | |
| } | |
| int print_caps(int fd) | |
| { | |
| struct v4l2_capability caps = {}; | |
| if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &caps)){ | |
| perror("Querying Capabilities"); | |
| return 1; | |
| } | |
| printf( "Driver Caps:\n" | |
| " Driver: \"%s\"\n" | |
| " Card: \"%s\"\n" | |
| " Bus: \"%s\"\n" | |
| " Version: %d.%d\n" | |
| " Capabilities: %08x\n", | |
| caps.driver, | |
| caps.card, | |
| caps.bus_info, | |
| (caps.version>>16)&&0xff, | |
| (caps.version>>24)&&0xff, | |
| caps.capabilities); | |
| if (!(caps.capabilities & V4L2_CAP_VIDEO_CAPTURE)){ | |
| fprintf(stderr, "The device does not handle single-planar video capture.\n"); | |
| } | |
| if (!(caps.capabilities & V4L2_CAP_STREAMING)){ | |
| fprintf(stderr, "The device does not handle frame streaming.\n"); | |
| } | |
| struct v4l2_fmtdesc fmtdesc = {0}; | |
| fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
| char fourcc[5] = {0}; | |
| char c, e; | |
| printf(" FMT : CE Desc\n--------------------\n"); | |
| while (0 == xioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc)){ | |
| strncpy(fourcc, (char *)&fmtdesc.pixelformat, 4); | |
| c = fmtdesc.flags & 1? 'C' : ' '; | |
| e = fmtdesc.flags & 2? 'E' : ' '; | |
| printf(" %s: %c%c %s\n", fourcc, c, e, fmtdesc.description); | |
| fmtdesc.index++; | |
| } | |
| struct v4l2_format fmt = {0}; | |
| fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
| fmt.fmt.pix.width = 640; | |
| fmt.fmt.pix.height = 480; | |
| fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG; | |
| // fmt.fmt.pix.field = V4L2_FIELD_ANY; | |
| if (-1 == xioctl(fd, VIDIOC_S_FMT, &fmt)){ | |
| perror("Setting Pixel Format"); | |
| return 1; | |
| } | |
| strncpy(fourcc, (char *)&fmt.fmt.pix.pixelformat, 4); | |
| printf( "Selected Camera Mode:\n" | |
| " Width: %d\n" | |
| " Height: %d\n" | |
| " PixFmt: %s\n" | |
| " Field: %d\n", | |
| fmt.fmt.pix.width, | |
| fmt.fmt.pix.height, | |
| fourcc, | |
| fmt.fmt.pix.field); | |
| return 0; | |
| } | |
| int init_mmap(int fd) | |
| { | |
| struct v4l2_requestbuffers req = {0}; | |
| req.count = 1; | |
| req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
| req.memory = V4L2_MEMORY_MMAP; | |
| if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req)){ | |
| perror("Requesting Buffer"); | |
| return 1; | |
| } | |
| struct v4l2_buffer buf = {0}; | |
| buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
| buf.memory = V4L2_MEMORY_MMAP; | |
| buf.index = 0; | |
| if(-1 == xioctl(fd, VIDIOC_QUERYBUF, &buf)){ | |
| perror("Querying Buffer"); | |
| return 1; | |
| } | |
| buffer = mmap (NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset); | |
| if(buffer == MAP_FAILED){ | |
| perror("mmap"); | |
| return 1; | |
| } | |
| memset(buffer, 0, buf.length); | |
| printf("Length: %d\nAddress: %p\n", buf.length, buffer); | |
| printf("Image Length: %d\n", buf.bytesused); | |
| return 0; | |
| } | |
| int capture_image(int fd) | |
| { | |
| struct v4l2_buffer buf = {0}; | |
| buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
| buf.memory = V4L2_MEMORY_MMAP; | |
| buf.index = 0; | |
| // Put the buffer in the incoming queue. | |
| if(-1 == xioctl(fd, VIDIOC_QBUF, &buf)){ | |
| perror("Query Buffer"); | |
| return 1; | |
| } | |
| // Activate streaming | |
| if(-1 == xioctl(fd, VIDIOC_STREAMON, &buf.type)){ | |
| perror("Start Capture"); | |
| return 1; | |
| } | |
| //wait for complete | |
| fd_set fds; | |
| FD_ZERO(&fds); | |
| FD_SET(fd, &fds); | |
| struct timeval tv = {0}; | |
| tv.tv_sec = 5; | |
| int r = select(fd+1, &fds, NULL, NULL, &tv); | |
| if(-1 == r){ | |
| perror("Waiting for Frame"); | |
| return 1; | |
| } | |
| // The buffer's waiting in the outgoing queue. | |
| if(-1 == xioctl(fd, VIDIOC_DQBUF, &buf)){ | |
| perror("Retrieving Frame"); | |
| return 1; | |
| } | |
| // Deactivate streaming | |
| if(ioctl(fd, VIDIOC_STREAMOFF, &buf.type) < 0){ | |
| perror("VIDIOC_STREAMOFF"); | |
| return 1 ; | |
| } | |
| // write buffer to output file | |
| int outfd ; | |
| if((outfd = open("logictec_notebookproo_out.jpg", O_RDWR | O_CREAT, 0660)) < 0 ){ | |
| perror("output file open"); | |
| return 1; | |
| } | |
| write(outfd, buffer, buf.length); | |
| close(outfd); | |
| return 0; | |
| } | |
| int main() | |
| { | |
| int fd; | |
| fd = open("/dev/video0", O_RDWR); | |
| if (fd == -1){ | |
| perror("Opening video device"); | |
| return 1; | |
| } | |
| if(print_caps(fd)) | |
| return 1; | |
| if(init_mmap(fd)) | |
| return 1; | |
| if(capture_image(fd)) | |
| return 1; | |
| close(fd); | |
| return 0; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <errno.h> | |
| #include <fcntl.h> | |
| #include <linux/videodev2.h> | |
| #include <stdint.h> | |
| #include <stdio.h> | |
| #include <string.h> | |
| #include <sys/ioctl.h> | |
| #include <sys/mman.h> | |
| #include <unistd.h> | |
| uint8_t *buffer; | |
| static int xioctl(int fd, int request, void *arg) | |
| { | |
| int r; | |
| do r = ioctl (fd, request, arg); | |
| while (-1 == r && EINTR == errno); | |
| return r; | |
| } | |
| int print_caps(int fd) | |
| { | |
| struct v4l2_capability caps = {}; | |
| if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &caps)) | |
| { | |
| perror("Querying Capabilities"); | |
| return 1; | |
| } | |
| printf( "Driver Caps:\n" | |
| " Driver: \"%s\"\n" | |
| " Card: \"%s\"\n" | |
| " Bus: \"%s\"\n" | |
| " Version: %d.%d\n" | |
| " Capabilities: %08x\n", | |
| caps.driver, | |
| caps.card, | |
| caps.bus_info, | |
| (caps.version>>16)&&0xff, | |
| (caps.version>>24)&&0xff, | |
| caps.capabilities); | |
| struct v4l2_cropcap cropcap = {0}; | |
| cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
| if (-1 == xioctl (fd, VIDIOC_CROPCAP, &cropcap)) | |
| { | |
| perror("Querying Cropping Capabilities"); | |
| return 1; | |
| } | |
| printf( "Camera Cropping:\n" | |
| " Bounds: %dx%d+%d+%d\n" | |
| " Default: %dx%d+%d+%d\n" | |
| " Aspect: %d/%d\n", | |
| cropcap.bounds.width, cropcap.bounds.height, cropcap.bounds.left, cropcap.bounds.top, | |
| cropcap.defrect.width, cropcap.defrect.height, cropcap.defrect.left, cropcap.defrect.top, | |
| cropcap.pixelaspect.numerator, cropcap.pixelaspect.denominator); | |
| int support_grbg10 = 0; | |
| struct v4l2_fmtdesc fmtdesc = {0}; | |
| fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
| char fourcc[5] = {0}; | |
| char c, e; | |
| printf(" FMT : CE Desc\n--------------------\n"); | |
| while (0 == xioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc)) | |
| { | |
| strncpy(fourcc, (char *)&fmtdesc.pixelformat, 4); | |
| if (fmtdesc.pixelformat == V4L2_PIX_FMT_SGRBG10) | |
| support_grbg10 = 1; | |
| c = fmtdesc.flags & 1? 'C' : ' '; | |
| e = fmtdesc.flags & 2? 'E' : ' '; | |
| printf(" %s: %c%c %s\n", fourcc, c, e, fmtdesc.description); | |
| fmtdesc.index++; | |
| } | |
| if (!support_grbg10) | |
| { | |
| printf("Doesn't support GRBG10.\n"); | |
| return 1; | |
| } | |
| struct v4l2_format fmt = {0}; | |
| fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
| fmt.fmt.pix.width = 752; | |
| fmt.fmt.pix.height = 480; | |
| fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SGRBG10; | |
| fmt.fmt.pix.field = V4L2_FIELD_NONE; | |
| if (-1 == xioctl(fd, VIDIOC_S_FMT, &fmt)) | |
| { | |
| perror("Setting Pixel Format"); | |
| return 1; | |
| } | |
| strncpy(fourcc, (char *)&fmt.fmt.pix.pixelformat, 4); | |
| printf( "Selected Camera Mode:\n" | |
| " Width: %d\n" | |
| " Height: %d\n" | |
| " PixFmt: %s\n" | |
| " Field: %d\n", | |
| fmt.fmt.pix.width, | |
| fmt.fmt.pix.height, | |
| fourcc, | |
| fmt.fmt.pix.field); | |
| return 0; | |
| } | |
| int init_mmap(int fd) | |
| { | |
| struct v4l2_requestbuffers req = {0}; | |
| req.count = 1; | |
| req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
| req.memory = V4L2_MEMORY_MMAP; | |
| if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req)) | |
| { | |
| perror("Requesting Buffer"); | |
| return 1; | |
| } | |
| struct v4l2_buffer buf = {0}; | |
| buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
| buf.memory = V4L2_MEMORY_MMAP; | |
| buf.index = 0; | |
| if(-1 == xioctl(fd, VIDIOC_QUERYBUF, &buf)) | |
| { | |
| perror("Querying Buffer"); | |
| return 1; | |
| } | |
| buffer = mmap (NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset); | |
| printf("Length: %d\nAddress: %p\n", buf.length, buffer); | |
| printf("Image Length: %d\n", buf.bytesused); | |
| return 0; | |
| } | |
| int capture_image(int fd) | |
| { | |
| struct v4l2_buffer buf = {0}; | |
| buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
| buf.memory = V4L2_MEMORY_MMAP; | |
| buf.index = 0; | |
| if(-1 == xioctl(fd, VIDIOC_QBUF, &buf)) | |
| { | |
| perror("Query Buffer"); | |
| return 1; | |
| } | |
| if(-1 == xioctl(fd, VIDIOC_STREAMON, &buf.type)) | |
| { | |
| perror("Start Capture"); | |
| return 1; | |
| } | |
| fd_set fds; | |
| FD_ZERO(&fds); | |
| FD_SET(fd, &fds); | |
| struct timeval tv = {0}; | |
| tv.tv_sec = 2; | |
| int r = select(fd+1, &fds, NULL, NULL, &tv); | |
| if(-1 == r) | |
| { | |
| perror("Waiting for Frame"); | |
| return 1; | |
| } | |
| if(-1 == xioctl(fd, VIDIOC_DQBUF, &buf)) | |
| { | |
| perror("Retrieving Frame"); | |
| return 1; | |
| } | |
| int outfd = open("out.img", O_RDWR); | |
| write(outfd, buffer, buf.bytesused); | |
| close(outfd); | |
| return 0; | |
| } | |
| int main() | |
| { | |
| int fd; | |
| fd = open("/dev/video0", O_RDWR); | |
| if (fd == -1) | |
| { | |
| perror("Opening video device"); | |
| return 1; | |
| } | |
| if(print_caps(fd)) | |
| return 1; | |
| if(init_mmap(fd)) | |
| return 1; | |
| if(capture_image(fd)) | |
| return 1; | |
| close(fd); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment