Search code examples
c++linuxopencvcameradirectshow

UVC Camera "Still Pin" capture in Linux C++


I have a USB camera here that I am very familiar with and have worked with for a while. I can capture "still images" in OpenCV and with Gstreamer without problems. However one of the use cases for this camera involves a button on the camera itself to capture stills.

The camera has a "still pin" which I have wired up a button to. In Windows with DirectShow it works as you would expect. I have spent the past week in search of a way to replicate this behavior in Linux for my embedded project. So far I have not been able to find anything that I can make use of. It seems all the support for this feature is Windows only.

I have searched through the following: V4l2 Documentation OpenCV Gstreamer uvc-streamer uvccapture luvcview

I have also done USB sniffing on Windows which revealed a "capture begin" packet is sent. Though I have not found a way I can monitor the USB traffic from the camera during streaming. While capturing from the device, /dev/video0 is in use by V4l2 and I cannot read the bytes traveling on the bus. If there is a way I could read the raw data from the camera, I could also just handle a "still pin" button press in my application.

Any possible solutions/ideas are welcome at this point. I am out of ideas and web resources.


Solution

  • So it turns out there is a way to see a "still pin" button press in linux!

    The button press shows up as an evevent. Using something such as libevdev I can use that in my code. This answer was mostly found here:

    can't get the mouse move event from /dev/input/event*

    And here is a sample output from the camera button:

    # input-events 15
    /dev/input/event15
       bustype : BUS_USB
       vendor  : 0xc45
       product : 0x62c0
       version : 256
       name    : "Celestron Digital Microscope"
       phys    : "usb-0000:00:14.0-1/button"
       bits ev : EV_SYN EV_KEY
    
    waiting for events
    08:34:01.980650: EV_KEY KEY_CAMERA (0xd4) pressed
    08:34:01.980650: EV_SYN code=0 value=0
    08:34:02.180637: EV_KEY KEY_CAMERA (0xd4) released
    08:34:02.180637: EV_SYN code=0 value=0
    08:34:02.580673: EV_KEY KEY_CAMERA (0xd4) pressed
    08:34:02.580673: EV_SYN code=0 value=0
    08:34:02.680676: EV_KEY KEY_CAMERA (0xd4) released
    08:34:02.680676: EV_SYN code=0 value=0
    08:34:03.580618: EV_KEY KEY_CAMERA (0xd4) pressed
    08:34:03.580618: EV_SYN code=0 value=0
    08:34:03.780657: EV_KEY KEY_CAMERA (0xd4) released
    08:34:03.780657: EV_SYN code=0 value=0
    08:34:04.280631: EV_KEY KEY_CAMERA (0xd4) pressed
    08:34:04.280631: EV_SYN code=0 value=0
    08:34:04.580679: EV_KEY KEY_CAMERA (0xd4) released
    08:34:04.580679: EV_SYN code=0 value=0
    08:34:05.080636: EV_KEY KEY_CAMERA (0xd4) pressed
    08:34:05.080636: EV_SYN code=0 value=0
    08:34:05.380704: EV_KEY KEY_CAMERA (0xd4) released
    08:34:05.380704: EV_SYN code=0 value=0
    

    So as you can see, button press/release is clearly visible to the system. I hope this helps anybody else in their search.

    I suppose I should also mention that the button press saves a still image in guvcviewer so I know support has to be there for this type of thing.