Linux and multiple USB webcams cause reduced frame resolution and v4l2 error
I have two Logitech Pro 9000 webcams. I have discovered a strange behaviour in cv::VideoCapture::set() when setting the frame size (width and height) for my captures resulting in 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
for my second camera. In order to fix it I have to reduce my frame size almost 2 times from the initial one. Now here is the interesting thing:
Version 1 (without using cv::VideoCapture::set()) - I manage to get both cameras up and running at 15fps (I tried with 20fps but I get the error I have mentioned above) with a resolution of 640x480, which seems to be a sort of a hidden default for those cameras (I was unable to find in the source code of cv::VideoCapture where this is set) if you don't specify these. The two values are retrieved by using cv::VideoCapture::get(CV_CAP_PROP_FRAME_WIDTH) and cv::VideoCapture::get(CV_CAP_PROP_FRAME_HEIGHT) respectively. Here is a small example:
// The indices are 1 and 2 since 0 is my built-in webcam (I'm using a notebook) cv::VideoCapture cap1(1); cv::VideoCapture cap2(2); if(!cap1.isOpened()) { std::cout << "Cannot open the video cam [1]" << std::endl; return -1; } if(!cap2.isOpened()) { std::cout << "Cannot open the video cam [2]" << std::endl; return -1; } // Set both cameras to 15fps 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); // Here I display the frame size that OpenCV has picked for me - it is 640x480 for both cameras std:: cout << "cam[1] Frame size: " << dWidth1 << " x " << dHeight1 << std::endl; std::cout << "cam[2] Frame size: " << dWidth2 << " x " << dHeight2 << std::endl; cv::namedWindow("cam[1]",CV_WINDOW_AUTOSIZE); cv::namedWindow("cam[2]",CV_WINDOW_AUTOSIZE); while(1) { cv::Mat frame1, frame2; bool bSuccess1 = cap1.read(frame1); bool bSuccess2 = cap2.read(frame2); if (!bSuccess1) { std::cout << "Cannot read a frame from video stream [1]" << std::endl; break; } if (!bSuccess2) { std::cout << "Cannot read a frame from video stream [2]" << std::endl; break; } cv::imshow("cam[1]", frame1); cv::imshow("cam[2]", frame2); if(cv::waitKey(30) == 27) { std::cout << "ESC key is pressed by user" << std::endl; break; } }
This example is working without any issues.
Version 2 (using cv::VideoCapture::set()) - if I take the exact same values that I retrieve using cv::VideoCapture::get() and use them with cv::VideoCapture::set() to setup the exact same parameters the above mentioned error occurs:
cv::VideoCapture cap1(1); cv::VideoCapture cap2(2); if(!cap1.isOpened()) { std::cout << "Cannot open the video cam [1]" << std::endl; return -1; } if(!cap2.isOpened()) { std::cout << "Cannot open the video cam [2]" << std::endl; return -1; } cap1.set(CV_CAP_PROP_FPS, 15); cap2.set(CV_CAP_PROP_FPS, 15); // Values taken from output of Version 1 and used to setup the exact same parameters with the exact same values! cap1 ...