C++ VIDIOC_QBUF:设备或资源繁忙的V4L2内存用户PTR
以下所有内容都在使用C++ VIDIOC_QBUF:设备或资源繁忙的V4L2内存用户PTR,c++,linux,kernel,C++,Linux,Kernel,以下所有内容都在使用 #include <linux/videodev2.h> #include <vector> 小心 不允许将排队请求与排队缓冲区直接混合。如果第一个缓冲区直接排队,然后应用程序尝试将请求排队,则返回EBUSY,反之亦然。关闭文件描述符、调用VIDIOC_STREAMOFF或调用ioctl VIDIOC_REQBUFS后,将重置对此的检查。 对于内存到内存设备,您可以仅为输出缓冲区而不是捕获缓冲区指定请求。尝试为捕获缓冲区指定此选项将导致EBADR错
#include <linux/videodev2.h>
#include <vector>
小心
不允许将排队请求与排队缓冲区直接混合。如果第一个缓冲区直接排队,然后应用程序尝试将请求排队,则返回EBUSY,反之亦然。关闭文件描述符、调用VIDIOC_STREAMOFF或调用ioctl VIDIOC_REQBUFS后,将重置对此的检查。
对于内存到内存设备,您可以仅为输出缓冲区而不是捕获缓冲区指定请求。尝试为捕获缓冲区指定此选项将导致EBADR错误。第一件事不要阅读文档,这只是一些误导性的词语
/*
Allocate 5 buffers and form and abstraction to buffers with a continous loop of buffers.
CameraChannel must require a buffer from CameraStream class.
Pass that buffer to v4l2 to fill with frame data
*/
#include <cstdint>
#include <linux/videodev2.h>
#include <fcntl.h>
#include <iostream>
#include <sys/mman.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <vector>
#define FRAME_NUM 5
class CameraStream{
public:
CameraStream(int fd);
void allocateBuffer();
uint8_t *returnBufferAddress();
private:
int sfd;
unsigned int n_buffers;
v4l2_requestbuffers requestBuffers{0};
std::vector<uint8_t*> v4l2_buffers;
};
为了将MEMORY_USR指针与VIDIOC_QBUF一起使用,首先必须执行以下操作
使用以下工具查询摄像头的功能:
if (xioctl(mFd, VIDIOC_QUERYCAP, &capability) < 0) {
perror("Failed to get device capabilities");
}
if (!(capability.capabilities & V4L2_CAP_VIDEO_CAPTURE)
|| !(capability.capabilities & V4L2_CAP_STREAMING))
{
perror("This device cannot stream video");
exit(1);
}
printf("%s\n","This device has capabilities");
查询索引为0的缓冲区
CLEAR(mBuffferInfo);
mBuffferInfo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
mBuffferInfo.memory = V4L2_MEMORY_USERPTR;
mBuffferInfo.index = 0;
if(-1 == xioctl(mFd,VIDIOC_QUERYBUF,&mBuffferInfo)){
perror("VIDIOC_QUERYBUF");
}
激活StreamOn
type = mBuffferInfo.type;
if(-1 == xioctl(mFd,VIDIOC_STREAMON,&type)){
perror("STREAMON");
}
}
使用以下尺寸示例制作框架:
void Camera::captureFrame(uint8_t* frame){
memset(frame,0,sizeImage);
CLEAR(mBuffferInfo);
mBuffferInfo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
mBuffferInfo.memory = V4L2_MEMORY_USERPTR;
mBuffferInfo.index = 0;
mBuffferInfo.m.userptr = (unsigned long)frame;
mBuffferInfo.length = sizeImage;
if(-1 == xioctl(mFd,VIDIOC_QBUF,&mBuffferInfo)){
perror("VIDIOC_QBUF");
}
CLEAR(mBuffferInfo);
mBuffferInfo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
mBuffferInfo.memory = V4L2_MEMORY_USERPTR;
if(-1 == xioctl(mFd,VIDIOC_DQBUF,&mBuffferInfo)){
perror("VIDIOC_DQBUF");
}
}
我不熟悉这个工具,所以我帮不上忙,但看起来你已经接近成功了。你应该把它做完,让那些能回答这个问题的人和那些将来来寻找类似问题答案的人更容易回答。再加上为你经常发现的问题打包代码,然后自己解决问题。如果您这样做,请向前支付并自行回答。感谢您的回复,也许我只是个傻瓜。嗯,您是否尝试过将requestBuffers.count设置为>0?在您的情况下,它看起来将默认为0(即,没有请求的缓冲区,然后没有要排队的对象)。这只是我的一个想法,但根据文档说明,在内存_USERPTR的情况下,您不需要这样做,因为缓冲区将在用户空间中分配。这就意味着我只需要为所有我想用的缓冲区提供视频,但它不起作用。如果世界上有人能帮助我,我会感谢我被卡住了。我希望我更聪明
if (xioctl(mFd, VIDIOC_QUERYCAP, &capability) < 0) {
perror("Failed to get device capabilities");
}
if (!(capability.capabilities & V4L2_CAP_VIDEO_CAPTURE)
|| !(capability.capabilities & V4L2_CAP_STREAMING))
{
perror("This device cannot stream video");
exit(1);
}
printf("%s\n","This device has capabilities");
v4l2_format format;
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
format.fmt.pix.pixelformat = pfmt;
format.fmt.pix.width = 640;
format.fmt.pix.height = 480;
if(ioctl(mFd,VIDIOC_S_FMT,&format) == -1){
perror("Unable to set format");
}
sizeImage = format.fmt.pix.sizeimage;
std::cout<<"imgsize :\n"<<sizeImage<<std::endl;
v4l2_requestbuffers bufrequest;
CLEAR(bufrequest);
bufrequest.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
bufrequest.memory = V4L2_MEMORY_USERPTR;
bufrequest.count = 1;
if(-1 == xioctl(mFd,VIDIOC_REQBUFS,&bufrequest)){
if(EINVAL == errno) {
perror("Device does not support user pointer\n");
} else {
perror("VIDIOC_REQBUFS");
}
}
CLEAR(mBuffferInfo);
mBuffferInfo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
mBuffferInfo.memory = V4L2_MEMORY_USERPTR;
mBuffferInfo.index = 0;
if(-1 == xioctl(mFd,VIDIOC_QUERYBUF,&mBuffferInfo)){
perror("VIDIOC_QUERYBUF");
}
type = mBuffferInfo.type;
if(-1 == xioctl(mFd,VIDIOC_STREAMON,&type)){
perror("STREAMON");
}
}
void Camera::captureFrame(uint8_t* frame){
memset(frame,0,sizeImage);
CLEAR(mBuffferInfo);
mBuffferInfo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
mBuffferInfo.memory = V4L2_MEMORY_USERPTR;
mBuffferInfo.index = 0;
mBuffferInfo.m.userptr = (unsigned long)frame;
mBuffferInfo.length = sizeImage;
if(-1 == xioctl(mFd,VIDIOC_QBUF,&mBuffferInfo)){
perror("VIDIOC_QBUF");
}
CLEAR(mBuffferInfo);
mBuffferInfo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
mBuffferInfo.memory = V4L2_MEMORY_USERPTR;
if(-1 == xioctl(mFd,VIDIOC_DQBUF,&mBuffferInfo)){
perror("VIDIOC_DQBUF");
}
}