VEYE imx385 驱动问题+
-
@veye_xumm 我看了 那个源码 内存采用 普通的内存,我希望的是用 drm 或dmaheap 的,这样可以实现零copy
-
@flaty 我的理解中,相机驱动并不涉及到BUFF模式的限制。实际上数据的收取和防止到内存是rk的mipi接收单元的驱动所决定的。
下面是网上插到的信息,希望能有帮助。从你贴的代码来看,报错
Failed to queue buffer: Invalid argument(EINVAL)通常意味着结构体成员设置有问题,或者驱动不支持 DMABUF 模式。结合你写的代码,我帮你逐条排查一下:
1.
v4l2_buffer初始化问题你这里写的是:
struct v4l2_buffer buf={0}; struct v4l2_plane planes[1]={0};这是对的,但要注意
buf.length必须和planes数组元素数量一致,并且buf.m.planes不能为空。
2.
buf关键字段设置你代码里:
buf.index = 0; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; buf.memory = V4L2_MEMORY_DMABUF; buf.length = 1; buf.m.planes = planes;
buf.type用V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE是对的(说明驱动是 multiplanar 类型)。
buf.memory设置成DMABUF正确。
buf.index不是 0 就行,它必须是你在VIDIOC_REQBUFS时分配的 buffer 数量里的一个合法索引。比如如果你req.count = 4,那么只能用0..3。
3. plane 字段设置
planes[0].m.fd = frame_buffers[i].dmabuf_fd; planes[0].length = buffer_size;问题可能出在这里:
planes[0].m.fd:必须是dma-buf的有效fd。planes[0].length:应该是该 plane 的大小,但 通常驱动并不依赖这个值。有些驱动要求设置bytesused,即:
planes[0].bytesused = buffer_size;如果
bytesused没设,驱动可能直接返回EINVAL。
4. 建议的正确写法
试着改成这样:
struct v4l2_buffer buf; struct v4l2_plane planes[VIDEO_MAX_PLANES]; // 通常 >= 1 memset(&buf, 0, sizeof(buf)); memset(planes, 0, sizeof(planes)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; buf.memory = V4L2_MEMORY_DMABUF; buf.index = i; // 循环里的 buffer 索引 buf.length = 1; // plane 数量 buf.m.planes = planes; planes[0].m.fd = frame_buffers[i].dmabuf_fd; planes[0].length = buffer_size; // plane 总大小 planes[0].bytesused = buffer_size; // 必须加上
5. 确认驱动是否支持 DMABUF
不是所有 V4L2 驱动都支持
V4L2_MEMORY_DMABUF。你可以用下面的方法确认:v4l2-ctl -d /dev/video0 --querycap如果
ioctl里不支持DMABUF,就算代码写对了也会EINVAL。
有些驱动只支持MMAP,那就得用V4L2_MEMORY_MMAP。
建议:先在 QBUF前打印出buf和planes[0]的值,确认index、fd、bytesused都合理。
-
@veye_xumm V4L2-CTL 如下
Driver Info: Driver name : rkcif Card type : rkcif Bus info : platform:rkcif-mipi-lvds2 Driver version : 5.10.198 Capabilities : 0x84201000 Video Capture Multiplanar Streaming Extended Pix Format Device Capabilities Device Caps : 0x04201000 Video Capture Multiplanar Streaming Extended Pix Format修改了代码:
for(int i = 0; i < req_buffer.count; ++i) { struct v4l2_buffer buf; struct v4l2_plane planes[num_planes]; memset(&buf, 0, sizeof(struct v4l2_buffer)); memset(&planes, 0, sizeof(planes)); buf.index = i; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; buf.memory = V4L2_MEMORY_DMABUF; buf.m.planes = planes; buf.length = 1; buf.bytesused = fmt.fmt.pix.sizeimage; buf.m.planes[0].m.fd = dmabuf_fds[i]; planes[0].bytesused = fmt.fmt.pix.sizeimage; planes[0].m.fd = dmabuf_fds[i]; planes[0].length = fmt.fmt.pix.sizeimage; printf("index: %d\n bytesused: %d fd: %d length: %d\n", buf.index,planes[0].bytesused,planes[0].m.fd ,planes[0].length ); if (0 != ioctl(cam_dev_fd, VIDIOC_QBUF, &buf)) { perror("Unable to queue buffer"); return -1; } }我打印了信息,如下:
dam申请内存是没问题的
alloc dma_heap buffer. fd: 5, raw_buf: 0x7f7df08000, size: 3110400
alloc dma_heap buffer. fd: 6, raw_buf: 0x7f7dc10000, size: 3110400
alloc dma_heap buffer. fd: 7, raw_buf: 0x7f7d918000, size: 3110400
qbuf第一个缓冲区就报错
index: 0
bytesused: 3110400 fd: 5 length: 3110400
Unable to queue buffer: Invalid argument
我用了3个缓冲,DMA_AALLOC都正确,目前看似乎是这个相机驱动不支持DMA-BUF的模式,您看呢 -
@flaty
DMA BUFF模式的支持,并不是相机驱动所决定的,而是rockchip的rkcif这个驱动决定的。 数据的传递顺序是:camera-->mipi rx--->rkcif。我查阅了一些资料,显示5.10版本的rk3588的驱动好像是比较明确不支持DMA BUFF模式的。这也就限制了你camera到其他外设驱动的buffer零拷贝传递的能力。 不过如果你只是想零拷贝从camera驱动中拿到数据,进入算法的话,V4L2_MEMORY_MMAP模式应该就可以支持。
rkcif驱动在kernel6以上版本是否支持了DMA buffer模式,没有确切的说法。
-
@veye_xumm 感谢 感谢,,,mmap的方式 已经OK了,我继续去问一下firefly
-
@flaty 不客气。如果有后续的解决方案也欢迎告知我一下。
-
@veye_xumm 好的 一定
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register Login