Dmabuf mode for v4l2

  • What i also tried is to capture video using V4L2 dirver kernel api. It's working fine in MMAP mode, but with DMABUF it fails on VIDIOC_EXPBUF system call. According to v4l2-ctl util in --verbose mode the sequence of ioctl's is:

    Code: Select all

    VIDIOC_REQBUFS returned 0 (Success)
    		VIDIOC_QUERYBUF returned 0 (Success)
    		VIDIOC_QUERYBUF returned 0 (Success)
    		VIDIOC_QUERYBUF returned 0 (Success)
    		VIDIOC_QUERYBUF returned 0 (Success)
    		VIDIOC_REQBUFS returned 0 (Success)
    		VIDIOC_QUERYBUF returned 0 (Success)
    		VIDIOC_QUERYBUF returned 0 (Success)
    		VIDIOC_QUERYBUF returned 0 (Success)
    		VIDIOC_QUERYBUF returned 0 (Success)
    		VIDIOC_EXPBUF returned 0 (Success)
    		VIDIOC_EXPBUF returned 0 (Success)
    		VIDIOC_EXPBUF returned 0 (Success)
    		VIDIOC_EXPBUF returned 0 (Success)
    		VIDIOC_QBUF returned 0 (Success)
    		VIDIOC_QBUF returned 0 (Success)
    		VIDIOC_QBUF returned 0 (Success)
    		VIDIOC_QBUF returned 0 (Success)
    		VIDIOC_STREAMON returned 0 (Success)
    
    And looking at v4l2-utils source code (https://gitlab.collabora.com/dbrouwer/v ... ree/master) it is really doing something that it has to:

    Code: Select all

    	if (options[OptStreamDmaBuf]) {
    		if (exp_q.reqbufs(&exp_fd, reqbufs_count_cap))
    			goto done;
    		if (q.export_bufs(&exp_fd, exp_fd.g_type()))
    			goto done;
    	}
    
    Inside of reqbufs function there is VIDIOC_REQBUFS and VIDIOC_QUERYBUF ioctls:

    Code: Select all

    static inline int v4l_queue_reqbufs(struct v4l_fd *f,
    		struct v4l_queue *q, unsigned count, unsigned int flags = 0)
    {
    	struct v4l2_requestbuffers reqbufs;
    	int ret;
    
    	reqbufs.type = q->type;
    	reqbufs.memory = q->memory;
    	reqbufs.count = count;
    	reqbufs.flags = flags;
    	/*
    	 * Problem: if REQBUFS returns an error, did it free any old
    	 * buffers or not?
    	 */
    	ret = v4l_ioctl(f, VIDIOC_REQBUFS, &reqbufs);
    	if (ret)
    		return ret;
    	q->buffers = reqbufs.count;
    	q->capabilities = reqbufs.capabilities;
    	return v4l_queue_querybufs(f, q, 0);
    }
    

    Code: Select all

    static inline int v4l_queue_querybufs(struct v4l_fd *f, struct v4l_queue *q, unsigned from)
    {
    	unsigned b, p;
    	int ret;
    
    	for (b = from; b < v4l_queue_g_buffers(q); b++) {
    		struct v4l_buffer buf;
    
    		v4l_buffer_init(&buf, v4l_queue_g_type(q), v4l_queue_g_memory(q), b);
    		ret = v4l_ioctl(f, VIDIOC_QUERYBUF, &buf.buf);
    		if (ret)
    			return ret;
    		if (b == 0) {
    			q->num_planes = v4l_buffer_g_num_planes(&buf);
    			for (p = 0; p < v4l_queue_g_num_planes(q); p++)
    				q->lengths[p] = v4l_buffer_g_length(&buf, p);
    		}
    		if (q->memory == V4L2_MEMORY_MMAP)
    			for (p = 0; p < q->num_planes; p++)
    				q->mem_offsets[b][p] = v4l_buffer_g_mem_offset(&buf, p);
    	}
    	return 0;
    }
    

    Code: Select all

    static inline int v4l_queue_export_bufs(struct v4l_fd *f, struct v4l_queue *q,
    					unsigned exp_type)
    {
    	struct v4l2_exportbuffer expbuf;
    	unsigned b, p;
    	int ret = 0;
    
    	expbuf.type = exp_type ? : f->type;
    	expbuf.flags = O_RDWR;
    	memset(expbuf.reserved, 0, sizeof(expbuf.reserved));
    	for (b = 0; b < v4l_queue_g_buffers(q); b++) {
    		expbuf.index = b;
    		for (p = 0; p < v4l_queue_g_num_planes(q); p++) {
    			expbuf.plane = p;
    			ret = v4l_ioctl(f, VIDIOC_EXPBUF, &expbuf);
    			if (ret)
    				return ret;
    			v4l_queue_s_fd(q, b, p, expbuf.fd);
    		}
    	}
    	return 0;
    }
    
    But doing the same in my own application causes an error. Also v4l2-compliance say this thing about VIDIOC_EXPBUF ioctl that causes an error in my code:
    Screenshot from 2024-07-29 18-29-19.png
    Had anyone experienced this thing? There is such a feeling that i'm the only person working with camera on this board...
  • Hello,
    Although the SDK provides dynamic libraries for mpp, it's challenging to use them effectively in a real project with only the header files. Referencing the usage of the mpp library on other Rockchip platforms might lead to some progress, but currently, the mpi has more extensive examples and resources available that can serve as alternatives.

    I have only tested using v4l2 to capture raw images, and there currently isn't a successful solution for involving the ISP or enabling dmabuf mode. On the RV1103/RV1106, memory allocation for the camera is handled through CMA, which differs from the CMA in standard Linux. This might be the reason your experiments haven't been successful. The unique design of the RV1106 in multimedia provides good performance, but it significantly increases the difficulty of operations that do not use Rockchip libraries.