- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试使用带有 Raspberry Pi 相机的官方 V4L2 驱动程序在 Raspberry Pi 上流式传输视频,来自 raspbian(2015-02 版本)上的 C++,但我遇到了低 FPS 问题。
目前我只是创建一个窗口并将缓冲区复制到屏幕(这需要大约 30 毫秒),而 select()
需要大约 140 毫秒(总共 5-6 fps)。我还尝试休眠 100 毫秒,它减少了类似数量的 select()
时间(导致相同的 fps)。 CPU 负载约为 5-15%。
我还尝试从控制台(或 system()
)更改驱动程序 fps,但它只能向下工作(例如,如果我将驱动程序 fps 设置为 1fps,我将得到 1fps,但如果我将它设置为 90fps 我仍然得到 5-6fps,即使驱动程序确认将它设置为 90fps)。此外,在查询所用分辨率的 FPS 模式时,我得到 90fps。
我包含了与 V4L2 相关的部分代码(不同部分之间省略了代码):
//////////////////
// Open device
//////////////////
mFD = open(mDevName, O_RDWR | O_NONBLOCK, 0);
if (mFD == -1) ErrnoExit("Open device failed");
//////////////////
// Setup format
//////////////////
struct v4l2_format fmt;
memset(&fmt, 0, sizeof(fmt));
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Xioctl(VIDIOC_G_FMT, &fmt);
mImgWidth = fmt.fmt.pix.width;
mImgHeight = fmt.fmt.pix.height;
cout << "width=" << mImgWidth << " height=" << mImgHeight << "\nbytesperline=" << fmt.fmt.pix.bytesperline << " sizeimage=" << fmt.fmt.pix.sizeimage << "\n";
// For some reason querying the format always sets pixelformat to JPEG
// no matter the input, so set it back to YUYV
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
if (Xioctl(VIDIOC_S_FMT, &fmt) == -1)
{
cout << "Set video format failed : " << strerror(errno) << "\n";
}
//////////////////
// Setup streaming
//////////////////
struct v4l2_requestbuffers req;
memset(&req, 0, sizeof(req));
req.count = 20;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (-1 == Xioctl(VIDIOC_REQBUFS, &req))
{
ErrnoExit("Reqbufs");
}
if (req.count < 2)
throw "Not enough buffer memory !";
mNBuffers = req.count;
mBuffers = new CBuffer[mNBuffers];
if (!mBuffers) throw "Out of memory !";
for (unsigned int i = 0; i < mNBuffers; i++)
{
struct v4l2_buffer buf;
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if (-1 == Xioctl(VIDIOC_QUERYBUF, &buf))
ErrnoExit("Querybuf");
mBuffers[i].mLength = buf.length;
mBuffers[i].pStart = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, mFD, buf.m.offset);
if (mBuffers[i].pStart == MAP_FAILED)
ErrnoExit("mmap");
}
//////////////////
// Start streaming
//////////////////
unsigned int i;
enum v4l2_buf_type type;
struct v4l2_buffer buf;
for (i = 0; i < mNBuffers; i++)
{
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if (-1 == Xioctl(VIDIOC_QBUF, &buf))
ErrnoExit("QBUF");
}
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1==Xioctl(VIDIOC_STREAMON, &type))
ErrnoExit("STREAMON");
主循环的最后两部分:
//////////////////
// Get frame
//////////////////
FD_ZERO(&fds);
FD_SET(mFD, &fds);
tv.tv_sec = 3;
tv.tv_usec = 0;
struct timespec t0, t1;
clock_gettime(CLOCK_REALTIME, &t0);
// This line takes about 140ms which I don't get
r = select(mFD + 1, &fds, NULL, NULL, &tv);
clock_gettime(CLOCK_REALTIME, &t1);
cout << "select time : " << ((float)(t1.tv_sec - t0.tv_sec))*1000.0f + ((float)(t1.tv_nsec - t0.tv_nsec))/1000000.0f << "\n";
if (-1 == r)
{
if (EINTR == errno)
continue;
ErrnoExit("select");
}
if (r == 0)
throw "Select timeout\n";
// Read the frame
//~ struct v4l2_buffer buf;
memset(&mCurBuf, 0, sizeof(mCurBuf));
mCurBuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
mCurBuf.memory = V4L2_MEMORY_MMAP;
// DQBUF about 2ms
if (-1 == Xioctl(VIDIOC_DQBUF, &mCurBuf))
{
if (errno == EAGAIN) continue;
ErrnoExit("DQBUF");
}
clock_gettime(CLOCK_REALTIME, &mCaptureTime);
// Manage frame in mBuffers[buf.index]
mCurBufIndex = mCurBuf.index;
break;
}
//////////////////
// Release frame
//////////////////
if (-1 == Xioctl(VIDIOC_QBUF, &mCurBuf))
ErrnoExit("VIDIOC_QBUF during mainloop");
最佳答案
我一直在研究使用 picamera 的各种方法,但我算不上专家,但似乎默认相机设置是阻碍您的因素。有很多模式和开关。我不知道它们是否通过 ioctls 暴露或如何暴露,我才刚刚开始。但是我必须使用一个名为 v4l-ctl 的程序来为我想要的模式做好准备。深入了解该源代码并提升一些代码应该会让您取得成就。哦,我怀疑 select 调用是个问题,它只是在等待描述符变得可读很慢。根据模式等,可能会强制等待自动曝光等。编辑:我的意思是说“默认设置”,因为你已经改变了一些。还有一些规则没有编入驱动程序。
关于c++ - 是否有可能在 C++ 中使用 Raspberry Pi camera v4l2 获得良好的 FPS?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29704406/
我有一个 k*n矩阵 X 和 k*k矩阵A。对于X的每一列,我想计算标量 X[:, i].T.dot(A).dot(X[:, i]) (或者,数学上, Xi' * A * Xi )。 目前,我有一个
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我是 VueJS 的新手。我已经使用 vuetify/webpack-ssr 模板创建了一个项目,现在我想创建一个登录页面,但是没有显示表单,控制台给了我以下信息: [Vue warn]: Unkno
我尝试将 value 插入到 C++ vector v 之前的第 i 元素(或元素 (i-1) 之后) )。代码很简单 v.insert(v.begin() + i, value); 我确信当 i 介
我需要显示使用合并排序算法排序的 vector 。然而,当我使用 v.begin() 时,我的 friend 使用 v.data() 来传递 vector 。他的代码运行良好,而我的却不行。请解释。
这是我的命令(url1、url2、url3、url4 是占位符): ffmpeg -i url1 -i url2 -i url3 -i url4 -filter_complex “[1:v:0] [1
我以前用过Vue,我知道怎么用v-for渲染元素序列,v-if或v-show有条件地显示元素,并且 v-model例如,控制段落的内容。 但现在我需要对 DOM 进行更精细的控制: 我有一个range
我正在学习所有权和借用。 borrow1 和borrow2 的区别在于在borrow2 打印时使用了&: fn borrow1(v: &Vec) { println!("{}", &v[10]
我找不到一种方法来选择不同的选项来渲染 v-for 中的文本。是否有可能或者我是否需要以不同的方式构建逻辑来执行类似于下面的代码的操作? // i
Iterable 的三个直接子类型是 Map , Seq , 和 Set .除了性能问题之外,似乎还有一个 Seq是从整数到值的映射,以及 Set是从值到 bool 值的映射(如果值在集合中,则为 t
我想应用一个计算方法,如果键存在则增加值,否则将 1。有 Map map = new HashMap<>(); 我不明白为什么 for (int i = 0; i v != null ? v++ :
标准(IEEE 754/C)是否保证以下代码断言永远不会失败? int main() { for ( /* all possible float / double values */ )
代码由Vue语言编写,使用Element-ui框架, 如果一个对象包含某些内容,则会显示该内容,如果不包含则禁用菜单按钮。 输出应该是这样的: a、b(禁用)、c、d、e 但我的是这样的: a、a(禁
如果我这样做: {{ morevalue }} {{ value }} v-else 中的跨度也会在第二个 V-FOR 上循环,即使它上面没有任何 v-for,为什么? 这是
如果我这样做: {{ morevalue }} {{ value }} v-else 中的跨度也会在第二个 V-FOR 上循环,即使它上面没有任何 v-for,为什么? 这是
我将 Vue.js 与 Vuetify 一起使用,我正在尝试使用 v-data-table 从后端加载菜单列表并使用 对其设置一些权限v-switches 但我在尝试 v-model 数组时遇到问题:
我在 Java 的流式操作中努力维护我想要的数据结构,这很可能是由于缺乏正确的理解和实践。 public class Main { public static void main(String
我正在尝试为匹配中的每个匹配呈现一些 HTML,但是,我不太确定 实际上是正确的。 更具体地说,我不确定我是否可以使用 v-bind:match='match'在与循环相同的元素上 v-for='ma
所以我想知道为什么这个 v-if 和 v-else 语句不起作用,为什么我要以不同的方式解决它。 代码如下 Required: Select a Workflow {{ isChain ?
我有一个 VueJS 组件 ,我在同一个模板中使用了两次来显示两组不同的数据。每个都显示在自己的 使用 v-if 切换的容器在导航选项卡上。 似乎这些组件被实例化为同一个实例。我调用 console
我是一名优秀的程序员,十分优秀!