title: Multiple MJPEG USB webcams on Linux - VideoCapture behaves differently within and outside a class
body: <p>I have 2 Logitech Pro 9000 webcams. I want to do some stereocalibration and pose estimation but I'm currently stuck on some weird (for me at least) behaviour on part of cv::VideoCapture. Note that this question is related to the one <a href="https://superuser.com/questions/431759/using-multiple-usb-webcams-in-linux">here</a>. </p>
  
  <p>I have two classes, which will be used as a base for creating capture modules for various cameras in order to include those in a bigger system. The first one - CameraSettings - contains camera-specific settings. These settings are used in the second class - Camera - which handles the video stream, calibration and so on. The constructor of a camera simply uses the values in the CameraSettings object with cv::VideoCapture::set(CV_CAP_PROP_ ...):</p>
  
  <pre><code>#ifndef CAMERASETTINGS_H
  #define CAMERASETTINGS_H
  
  #include &lt;string&gt;
  using std::string;
  namespace Camera {
    class CameraSettings {
      private:
        double deviceIndex; /// Device index (starts from 0)
        double frameRateLimit;  /// Limits the frames per second. Depending on the number of cameras and the amount of data that is retrieved from those setting this to a lower (supported by the camera model!) value will prevent data clogging
        double frameWidth;  /// Width of the frame
        double frameHeight; /// Height of the frame
  
      public:
        /// Creates an empty set of settings
        CameraSettings();
        /// Creates a partially predefined set of settings
        CameraSettings(double deviceIndex, double frameRateLimit=25, double frameWidth=320, double frameHeight=240);
        CameraSettings(string devideIpAddrAndFormat, double frameRateLimit=25, double frameWidth=320, double frameHeight=240);
        ~CameraSettings();
  
        /*
         * Getters and setters for all settings of a camera
         */
  
        double getDevice() const;
        void setDevice(double value);
  
        double getFrameRateLimit() const;
        void setFrameRateLimit(double value);
  
        double getFrameWidth() const;
        void setFrameWidth(double value);
  
        double getFrameHeight() const;
        void setFrameHeight(double value);
    };
  }
  namespace Camera {
    class Camera {
      private:
        CameraSettings settings;  // Various camera settings
        VideoCapture *capture;  // Points at the video stream generated by the camera
  
      public:
        /*
         * Creates a new camera using a set of given settings
         * @param settings Contains an object with camera settings
         */
        Camera(CameraSettings&amp; settings);
        ~Camera();
  
        /*
         * Retrieves the next frame in the stream
         * @param frame Contains a retrieved frame from the video stream
         */
        void getFrame(Mat&amp; frame);
    };
  </code></pre>
  
  <p>Note: this is still an early work in progress!</p>
  
  <p>The problem comes from my getFrame() method, which looks as follows:</p>
  
  <pre><code>void Camera::getFrame(Mat &amp;frame)
  {
    cout &lt;&lt; "Reading frame..." &lt;&lt; endl;
    // Check if stream is opened
    if(capture-&gt;isOpened()) {
      // Store next frame and check if frames can actually be read from the specified capture
      if(!capture-&gt;read(frame))
        cout &lt;&lt; MSG_PREFIX_ERROR &lt;&lt; ERROR_CAPT_UNABLE_TO_READ &lt;&lt; endl;
    }
  }
  </code></pre>
  
  <p>After I create a CameraSettings object I can additionally tweak the parameters and pass it to a newly created Camera object:</p>
  
  <pre><code>// Set both sets of settings to framerate of 15 and resolution of 352x288
  Camera::CameraSettings cs1(1, 15);
  Camera::CameraSettings cs2(2, 15);
  cs1.setFrameHeight(288);
  cs1.setFrameWidth(352);
  cs2.setFrameHeight(288);
  cs2.setFrameWidth(352);
  
  // Create two cameras using the specified above settings
  Camera::Camera cam1(cs1);
  Camera::Camera cam2(cs2);
  </code></pre>
  
  <p>I discovered that the VideoCapture that I have in my Camera object allows a much lower resolution and frame rate compared to the following direct approach:</p>
  
  <pre><code>main(int argc, char **argv) {
    VideoCapture cap1(1);
    VideoCapture cap2(2);
  
    if(!cap1.isOpened())
    {
      cout &lt;&lt; "Cannot open the video cam [1]" &lt;&lt; endl;
      return -1;
    }
  
    if(!cap2.isOpened())
    {
      cout &lt;&lt; "Cannot open the video cam [2]" &lt;&lt; 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 &lt;&lt; "cam[1] Frame size: " &lt;&lt; dWidth1 &lt;&lt; " x " &lt;&lt; dHeight1 &lt;&lt; endl;
    cout &lt;&lt; "cam[2] Frame size: " &lt;&lt; dWidth2 &lt;&lt; " x " &lt;&lt; dHeight2 &lt;&lt; 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 &lt;&lt; "Cannot read a frame from video stream [1]" &lt;&lt; endl;
        break;
      }
  
      if (!bSuccess2)
      {
        cout &lt;&lt; "Cannot read a frame from video stream [2]" &lt;&lt; endl;
        break;
      }
  
      imshow("cam[1]", frame1);
      imshow("cam[2]", frame2);
  
      if(waitKey(30) == 27)
      {
        cout &lt;&lt; "ESC key was pressed by user" &lt;&lt; endl;
        break;
      }
    }
  }
  </code></pre>
  
  <p>The way I am handling things in my class is the exact same as the second piece of code I posted with the difference that here I use the default settings of cv::VideoCapture. I checked the dimensions of the frames and they are 640x480. In the case of using my Camera class however I can't get such a high resolution because I get the infamous error:</p>
  
  <blockquote>
    <p>libv4l2: error turning on stream: No space left on device</p>
    
    <p>VIDIOC_STREAMON: No space left on device</p>
  </blockquote>
  
  <p>For example if I do the following:</p>
  
  <pre><code>cs1.setFrameHeight(288);
  cs1.setFrameWidth(352);
  cs2.setFrameHeight(288);
  cs2.setFrameWidth(352);
  </code></pre>
  
  <p>for both of my cameras at 15 fps it is working as expected. Using 640x480 as in the case without my classes is not possible.</p>
  
  <p>Note that I have checked the supported resolutions using <strong>v4l2-ctl</strong>. I have also tested the framerates in both cases because they DO affect how high the data volumes are from both cameras.</p>
  
  <p>Obviously my question is why this is happening and how does my class affects the capabilities of cv::VideoCapture when it comes to FPS and resolution.</p>
  
  <p><strong>EDIT:</strong> Removed code that is not required for the problem at hand. Thanks @Wug!</p>