How can I capture video directly from /dev/video0?
Posted: 2024-06-29 8:27
If I look at the WIKI content related to opencv-mobile in the link below, it is explained as if a video in Bayerd format can be read directly from /dev/video0.
https://wiki.luckfox.com/Luckfox-Pico/L ... ncv-mobile However, I tried to capture video from /dev/video0 by referring to the following blog, but it did not work well.
Capture a picture with V4L2 : https://www.marcusfolkesson.se/blog/cap ... with-v4l2/
As explained in the blog, the information of /dev/video0 is as follows.
I tested the code on the blog by slightly modifying it as follows.
When I compile and run the program, the error "Device is no video capture device" occurs.
How can I solve the problem?
I'm also curious if it's possible to capture video directly from /dev/video0.
https://wiki.luckfox.com/Luckfox-Pico/L ... ncv-mobile However, I tried to capture video from /dev/video0 by referring to the following blog, but it did not work well.
Capture a picture with V4L2 : https://www.marcusfolkesson.se/blog/cap ... with-v4l2/
As explained in the blog, the information of /dev/video0 is as follows.
Code: Select all
[root@luckfox root]$ v4l2-ctl -d /dev/video0 --get-fmt-video
Format Video Capture Multiplanar:
Width/Height : 2304/1296
Pixel Format : 'BG10' (10-bit Bayer BGBG/GRGR)
Field : None
Number of planes : 1
Flags : 0x000000b4
Colorspace : Unknown (0x0000053d)
Transfer Function : Unknown (0x00000051)
YCbCr/HSV Encoding: BT.2020 Constant Luminance
Quantization : Default
Plane 0 :
Bytes per Line : 3072
Size Image : 3981312
[root@luckfox root]$ v4l2-ctl -d /dev/video10 --info
Driver Info:
Driver name : rkcif
Card type : rkcif
Bus info : platform:rkcif-mipi-lvds
Driver version : 5.10.110
Capabilities : 0x84201000
Video Capture Multiplanar
Streaming
Extended Pix Format
Device Capabilities
Device Caps : 0x04201000
Video Capture Multiplanar
Streaming
Extended Pix Format
Media Driver Info:
Driver name : rkcif
Model : rkcif-mipi-lvds
Serial :
Bus info :
Media version : 5.10.110
Hardware revision: 0x00000000 (0)
Driver version : 5.10.110
Interface Info:
ID : 0x0300002b
Type : V4L Video
Entity Info:
ID : 0x00000029 (41)
Name : rkcif_tools_id2
Function : V4L2 I/O
Pad 0x0100002a : 0: Sink
Link 0x02000057: from remote pad 0x100002f of entity 'rockchip-mipi-csi2' (Unknown V4L2 Sub-Device): Data
Link 0x0200006d: from remote pad 0x1000030 of entity 'rockchip-mipi-csi2' (Unknown V4L2 Sub-Device): Data
Link 0x02000083: from remote pad 0x1000031 of entity 'rockchip-mipi-csi2' (Unknown V4L2 Sub-Device): Data
Link 0x02000099: from remote pad 0x1000032 of entity 'rockchip-mipi-csi2' (Unknown V4L2 Sub-Device): Data
Link 0x020000af: from remote pad 0x1000033 of entity 'rockchip-mipi-csi2' (Unknown V4L2 Sub-Device): Data
Link 0x020000c5: from remote pad 0x1000034 of entity 'rockchip-mipi-csi2' (Unknown V4L2 Sub-Device): Data
Link 0x020000db: from remote pad 0x1000035 of entity 'rockchip-mipi-csi2' (Unknown V4L2 Sub-Device): Data
Link 0x020000f1: from remote pad 0x1000036 of entity 'rockchip-mipi-csi2' (Unknown V4L2 Sub-Device): Data
Link 0x02000107: from remote pad 0x1000037 of entity 'rockchip-mipi-csi2' (Unknown V4L2 Sub-Device): Data
Link 0x0200011d: from remote pad 0x1000038 of entity 'rockchip-mipi-csi2' (Unknown V4L2 Sub-Device): Data
Link 0x02000133: from remote pad 0x1000039 of entity 'rockchip-mipi-csi2' (Unknown V4L2 Sub-Device): Data, Enabled
I tested the code on the blog by slightly modifying it as follows.
When I compile and run the program, the error "Device is no video capture device" occurs.
Code: Select all
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#define NBUF 3
void query_capabilites(int fd)
{
struct v4l2_capability cap;
if (-1 == ioctl(fd, VIDIOC_QUERYCAP, &cap)) {
perror("Query capabilites");
exit(EXIT_FAILURE);
}
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
fprintf(stderr, "Device is no video capture device\n");
exit(EXIT_FAILURE);
}
if (!(cap.capabilities & V4L2_CAP_READWRITE)) {
fprintf(stderr, "Device does not support read i/o\n");
}
if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
fprintf(stderr, "Devices does not support streaming i/o\n");
exit(EXIT_FAILURE);
}
}
int set_format(int fd)
{
struct v4l2_format format = {0};
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
format.fmt.pix.width = 320;
format.fmt.pix.height = 240;
format.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR10; //V4L2_PIX_FMT_SBGGR10 = BG10, V4L2_PIX_FMT_YUYV
format.fmt.pix.field = V4L2_FIELD_NONE;
int res = ioctl(fd, VIDIOC_S_FMT, &format);
if(res == -1) {
perror("Could not set format");
exit(EXIT_FAILURE);
}
return res;
}
int request_buffer(int fd, int count)
{
struct v4l2_requestbuffers req = {0};
req.count = count;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) {
perror("Requesting Buffer");
exit(EXIT_FAILURE);
}
return req.count;
}
int query_buffer(int fd, int index, unsigned char **buffer)
{
struct v4l2_buffer buf = {0};
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = index;
if(ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) {
perror("Could not query buffer");
exit(EXIT_FAILURE);
}
*buffer = (u_int8_t*)mmap (NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
return buf.length;
}
int queue_buffer(int fd, int index)
{
struct v4l2_buffer bufd = {0};
bufd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
bufd.memory = V4L2_MEMORY_MMAP;
bufd.index = index;
if (ioctl(fd, VIDIOC_QBUF, &bufd) == -1) {
perror("Queue Buffer");
exit(EXIT_FAILURE);
}
return bufd.bytesused;
}
int start_streaming(int fd)
{
unsigned int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if(ioctl(fd, VIDIOC_STREAMON, &type) == -1) {
perror("VIDIOC_STREAMON");
exit(EXIT_FAILURE);
}
return 0;
}
int dequeue_buffer(int fd)
{
struct v4l2_buffer bufd = {0};
bufd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
bufd.memory = V4L2_MEMORY_MMAP;
bufd.index = 0;
if (ioctl(fd, VIDIOC_DQBUF, &bufd) == -1) {
perror("DeQueue Buffer");
exit(EXIT_FAILURE);
}
return bufd.index;
}
int stop_streaming(int fd)
{
unsigned int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if(ioctl(fd, VIDIOC_STREAMOFF, &type) == -1) {
perror("VIDIOC_STREAMON");
exit(EXIT_FAILURE);
}
return 0;
}
int main()
{
unsigned char *buffer[NBUF];
int fd = open("/dev/video0", O_RDWR);
int size;
int index;
int nbufs;
/* Step 1: Query capabilities */
query_capabilites(fd);
/* Step 2: Set format */
set_format(fd);
/* Step 3: Request Format */
nbufs = request_buffer(fd, NBUF);
if ( nbufs > NBUF) {
fprintf(stderr, "Increase NBUF to at least %i\n", nbufs);
exit(EXIT_FAILURE);
}
for (int i = 0; i < NBUF; i++) {
/* Step 4: Query buffers
* Assume all sizes is equal.
* */
size = query_buffer(fd, i, &buffer[i]);
/* Step 5: Queue buffer */
queue_buffer(fd, i);
}
/* Step 6: Start streaming */
start_streaming(fd);
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");
exit(1);
}
/* Step 7: Dequeue buffer */
index = dequeue_buffer(fd);
int file = open("output.raw", O_RDWR | O_CREAT, 0666);
write(file, buffer[index], size);
/* Step 8: Stop streaming */
stop_streaming(fd);
/* Cleanup the resources */
for (int i =0; i < NBUF; i++) {
munmap(buffer[i], size);
}
close(file);
close(fd);
return 0;
}
I'm also curious if it's possible to capture video directly from /dev/video0.