Page 1 of 1

How can I capture video directly from /dev/video0?

Posted: 2024-06-29 8:27
by cocoa
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
wiki-Luckfox-Pico-opencv-mobile.JPG
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;
}
How can I solve the problem?
I'm also curious if it's possible to capture video directly from /dev/video0.

Re: How can I capture video directly from /dev/video0?

Posted: 2024-07-31 3:39
by Crocodile
Hello,

When using a CSI camera on RV1103/RV1106, the multimedia framework differs from v4l2. The image obtained from `video0` may not be the correct camera image (it works correctly with a USB camera). You can refer to [url]https://github.com/LuckfoxTECH/luckfox-pico/issues/125[/usl] for more details.