C++ VIDIOC_DQBUF挂起在摄像头断开连接上

C++ VIDIOC_DQBUF挂起在摄像头断开连接上,c++,multithreading,v4l2,C++,Multithreading,V4l2,我的应用程序正在使用在单独线程中运行的v4l2。如果相机断开连接,则在干净地终止线程之前,会向用户发送适当的消息。这在绝大多数情况下都有效。但是,如果相机断开连接时执行在VIDIOC_DQBUF ioctl内,则ioctl不会返回,从而导致整个线程锁定 我的系统如下: Linux内核:4.12.0 OS:Fedora25 编译器:gcc-7.1 以下是问题函数的简化示例 // Get Raw Buffer from the camera void v4l2_Processor::get_Ra

我的应用程序正在使用在单独线程中运行的v4l2。如果相机断开连接,则在干净地终止线程之前,会向用户发送适当的消息。这在绝大多数情况下都有效。但是,如果相机断开连接时执行在VIDIOC_DQBUF ioctl内,则ioctl不会返回,从而导致整个线程锁定

我的系统如下:

  • Linux内核:4.12.0
  • OS:Fedora25
  • 编译器:gcc-7.1
以下是问题函数的简化示例

// Get Raw Buffer from the camera
void v4l2_Processor::get_Raw_Frame(void* buffer)
{
struct v4l2_buffer buf;
memset(&buf, 0, sizeof (buf));

buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;

// Grab next frame
if (ioctl(m_FD, VIDIOC_DQBUF, &buf) < 0)
{   // If the camera becomes disconnected when the execution is
    // in the above ioctl, then the ioctl never returns.

    std::cerr << "Error in DQBUF\n";
}

// Queue for next frame
if (ioctl(m_FD, VIDIOC_QBUF, &buf) < 0)
{
    std::cerr << "Error in QBUF\n";
}

memcpy(buffer, m_Buffers[buf.index].buff, 
   m_Buffers[buf.index].buf_length);
}
//从相机获取原始缓冲区
void v4l2\u处理器::获取\u原始\u帧(void*缓冲区)
{
结构v4l2_缓冲区buf;
memset(&buf,0,sizeof(buf));
buf.type=V4L2\u buf\u type\u视频捕获;
buf.memory=V4L2\u memory\u MMAP;
//抓住下一帧
if(ioctl(m_FD,VIDIOC_DQBUF,&buf)<0)
{//如果执行时相机断开连接
//在上面的ioctl中,则ioctl永远不会返回。

我目前也有同样的问题。但是,我的整个线程没有锁定。ioctl超时(15秒),但太长了

如果视频正在流式传输,是否有查询V4L2(不会挂起)的方法?或者至少更改ioctl超时

更新:

@Amanda您可以在v4l2_捕获驱动程序源代码中更改出列超时,并重建内核/内核模块 修改dqueue函数中的超时:

if (!wait_event_interruptible_timeout(cam->enc_queue,
                                      cam->enc_counter != 0,
                                      50 * HZ)) // Modify this constant
祝你好运