Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Multiplecameras and using set() for frame's width and height result in libv4l2 error

Hello!

I have two Logitec Pro 9000 webcams connected to my 64bit Debian notebook. I want to do some stereo-vision and so far it is working great (stereoCalibrate etc.). As you know if the data output is too great (resolution and framerate) you get (especially when using USB cameras) the infamous error:

libv4l2: error turning on stream: No space left on device
VIDIOC_STREAMON: No space left on device
ERROR: Could not read from video stream

I have discovered that for some reason that

cv::VideoCapture::set(CV_CAP_PROP_FRAME_HEIGHT, some_value)

and

cv::VideoCapture::set(CV_CAP_PROP_FRAME_WIDTH, some_value)

don't seem to be working. If I run 2 VideoCapture-s simultaneously I see that the default resolution for these two cameras is 640x480, which I see when I call the cv::VideoCapture::get() equivalent of those two methods I mentioned above. I have to limit the framerate to 15 in order to avoid that libv4l2 related error. Below I have two versions of a very simple program where I set my framerate to 15 and in the second version I also set the exact same resolution that I get when I call cv::VideoCapture::get(CV_CAP_PROP_FRAME_WIDTH/HEIGHT) in the first version:

  • Version 1 (working, no manual setup of the resolution, only framerate):

    VideoCapture cap1(1);
    VideoCapture cap2(2);
    
    if(!cap1.isOpened())
    {
      cout << "Cannot open the video cam [1]" << endl;
      return -1;
    }
    
    if(!cap2.isOpened())
    {
      cout << "Cannot open the video cam [2]" << endl;
      return -1;
    }
    
    cap1.set(CV_CAP_PROP_FPS, 15);
    cap2.set(CV_CAP_PROP_FPS, 15);
    
    double dWidth1 = cap1.get(CV_CAP_PROP_FRAME_WIDTH);
    double dHeight1 = cap1.get(CV_CAP_PROP_FRAME_HEIGHT);
    double dWidth2 = cap2.get(CV_CAP_PROP_FRAME_WIDTH);
    double dHeight2 = cap2.get(CV_CAP_PROP_FRAME_HEIGHT);
    
    cout << "cam[1] Frame size: " << dWidth1 << " x " << dHeight1 << endl;
    cout << "cam[2] Frame size: " << dWidth2 << " x " << dHeight2 << endl;
    namedWindow("cam[1]",CV_WINDOW_AUTOSIZE);
    namedWindow("cam[2]",CV_WINDOW_AUTOSIZE);
    
    while(1)    
    {    
      Mat frame1, frame2;    
      bool bSuccess1 = cap1.read(frame1);    
      bool bSuccess2 = cap2.read(frame2);
    
      if (!bSuccess1)
      {
        cout << "Cannot read a frame from video stream [1]" << endl;
        break;
      }
    
      if (!bSuccess2)
      {
        cout << "Cannot read a frame from video stream [2]" << endl;
        break;
      }
    
      cv::addText(frame1, "cam[1]", Point2f(10,25), cv::fontQt("FONT_HERSHEY_SCRIPT_SIMPLEX", 15, cv::Scalar(255,0,0)));
      cv::addText(frame2, "cam[2]", Point2f(10,25), cv::fontQt("FONT_HERSHEY_SCRIPT_SIMPLEX", 15, cv::Scalar(255,0,0)));
      imshow("cam[1]", frame1);
      imshow("cam[2]", frame2);
    
      if(waitKey(30) == 27)
      {
        cout << "ESC key is pressed by user" << endl;
        break;
      }
    }
    
  • Version 2 (not working, manual setup framerate, manual setup of the resolution results in error I've mentioned at the beginning of my question once I try to capture from the second camera):

    VideoCapture cap1(1);
    VideoCapture cap2(2);
    
    if(!cap1.isOpened())
    {
      cout << "Cannot open the video cam [1]" << endl;
      return -1;
    }
    
    if(!cap2.isOpened())
    {
      cout << "Cannot open the video cam [2]" << endl;
      return -1;
    }
    
    cap1.set(CV_CAP_PROP_FPS, 15);
    cap2.set(CV_CAP_PROP_FPS, 15);
    
    // Values taken from output of Version 1
    cap1.set(CV_CAP_PROP_FRAME_WIDTH, 640);
    cap1.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
    cap2.set(CV_CAP_PROP_FRAME_WIDTH, 640);
    cap2.set(CV_CAP_PROP_FRAME_HEIGHT, 480);    
    
    double dWidth1 = cap1.get(CV_CAP_PROP_FRAME_WIDTH);
    double dHeight1 = cap1.get(CV_CAP_PROP_FRAME_HEIGHT);
    double dWidth2 = cap2.get(CV_CAP_PROP_FRAME_WIDTH);
    double dHeight2 = cap2.get(CV_CAP_PROP_FRAME_HEIGHT);
    
    cout << "cam[1] Frame size: " << dWidth1 << " x " << dHeight1 << endl;
    cout << "cam[2] Frame size: " << dWidth2 << " x " << dHeight2 << endl;
    namedWindow("cam[1]",CV_WINDOW_AUTOSIZE);
    namedWindow("cam[2]",CV_WINDOW_AUTOSIZE);
    
    while(1)    
    {    
      Mat frame1, frame2;    
      bool bSuccess1 = cap1.read(frame1);    
      bool bSuccess2 = cap2.read(frame2);
    
      if (!bSuccess1)
      {
        cout << "Cannot read a frame from video stream [1]" << endl;
        break;
      }
    
      if (!bSuccess2)
      {
        cout << "Cannot read a frame from video stream [2]" << endl;
        break;
      }
    
      cv::addText(frame1, "cam[1]", Point2f(10,25), cv::fontQt("FONT_HERSHEY_SCRIPT_SIMPLEX", 15, cv::Scalar(255,0,0)));
      cv::addText(frame2, "cam[2]", Point2f(10,25), cv::fontQt("FONT_HERSHEY_SCRIPT_SIMPLEX", 15, cv::Scalar(255,0,0)));
      imshow("cam[1]", frame1);
      imshow("cam[2]", frame2);
    
      if(waitKey(30) == 27)
      {
        cout << "ESC key is pressed by user" << endl;
        break;
      }
    }
    

Here is also something interesting - if I swap the frame's width value with the height and vice versa I don't get the error but instead I get a resolution of 352x288. O_O So it seems that this is another hidden default value since this resolution is not supported by my cameras.

Any ideas why this is happening? I don't believe I need to multithread here but also even if I had to this still doesn't explain why it's working when I don't use the corresponding set() and not working when I do.

Best regards, RBA