Skip to content

Instantly share code, notes, and snippets.

@Circuitsoft
Created August 4, 2011 22:02
Show Gist options
  • Star 22 You must be signed in to star a gist
  • Fork 15 You must be signed in to fork a gist
  • Save Circuitsoft/1126411 to your computer and use it in GitHub Desktop.
Save Circuitsoft/1126411 to your computer and use it in GitHub Desktop.
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

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

@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.

@TzuHuanTai
Copy link

TzuHuanTai commented Jul 29, 2022

@lingxd try below

  1. set fmt.fmt.pix.pixelformat into V4L2_PIX_FMT_JPEG or V4L2_PIX_FMT_MJPEG
  2. modify int outfd = open("out.img", O_RDWR); to
int outfd = open("img.jpg", O_WRONLY | O_CREAT | O_EXCL, 0600);
if ((outfd == -1) && (EEXIST == errno))
{
    /* open the existing file with write flag */
    outfd = open("img.jpg", O_WRONLY);
}

@lingxd
Copy link

lingxd commented Aug 1, 2022

@lingxd try below

  1. set fmt.fmt.pix.pixelformat into V4L2_PIX_FMT_JPEG or V4L2_PIX_FMT_MJPEG
  2. modify int outfd = open("out.img", O_RDWR); to
int outfd = open("img.jpg", O_WRONLY | O_CREAT | O_EXCL, 0600);
if ((outfd == -1) && (EEXIST == errno))
{
    /* open the existing file with write flag */
    outfd = open("img.jpg", O_WRONLY);
}

thanks, it's useful.

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