Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Capture single image V4L2
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
#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;
}
@Phi-Van-Lam
Copy link

Phi-Van-Lam commented Mar 21, 2018

Driver Caps:
Driver: "pwc"
Card: "Logitech QuickCam Pro 4000"
Bus: "usb-3f980000.usb-1.3"
Version: 1.0
Capabilities: 85200001
Querying Cropping Capabilities: Inappropriate ioctl for device

Could you help me check?
I am using Raspbian on Raspberry pi 3.
Thank you very much!

@lingxd
Copy link

lingxd commented Mar 21, 2022

Driver Caps:
  Driver: "uvcvideo"
  Card: "HD Camera: HD Camera"
  Bus: "usb-0000:00:14.0-11"
  Version: 1.0
  Capabilities: 84a00001
Camera Cropping:
  Bounds: 640x480+0+0
  Default: 640x480+0+0
  Aspect: 1/1
  FMT : CE Desc
--------------------
  MJPG: C  Motion-JPEG
  YUYV:    YUYV 4:2:2
Selected Camera Mode:
  Width: 640
  Height: 480
  PixFmt: YUYV
  Field: 1
Length: 614400
Address: 0x7f230dc9e000
Image Length: 0

@lingxd
Copy link

lingxd commented Mar 21, 2022

I can't capture an out.img

@Circuitsoft
Copy link
Author

Circuitsoft commented Mar 22, 2022

@lingxd This example is (a) four years old and (b) specifically for a raw camera connected straight to an SoC. If doesn't really apply to any usb devices.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment