Using the Logitech C920 webcam with Gstreamer

Logitech HD Webcam C920You may already know about my existing enthusiasm for Logitech webcams, which is due to the combination of relatively good image quality, high resolution and easy to use UVC interface. I was therefore very happy to learn about their newest camera, the HD Pro Webcam C920, which in addition to the standard HD webcam stuff we already know from the C910, also provides hardware encoded H.264 video stream! This is rather new and there isn’t much software that can take advantage of it; however, with a little tweaking and hacking we can get the H.264 stream into Gstreamer, where after we can do pretty much whatever we want.

The camera

The camera looks very much like the C910. One significant exception is that it has a hole for mounting it on a standard photo tripod.

The camera can work in three different modes: YUV 4:2:2, H.264 and MJPG:

 # v4l2-ctl --list-formats  ioctl: VIDIOC_ENUM_FMT        Index       : 0
Type  : Video Capture
Pixel Format: 'YUYV' Name  : YUV 4:2:2 (YUYV) Index  : 1 Type  : Video Capture Pixel Format: 'H264' (compressed) Name  : H.264 Index  : 2 Type  : Video Capture Pixel Format: 'MJPG' (compressed) Name  : MJPEG

For each of these modes, the C920 has a huge amount of frame size and rate combinations going from 160×90 to 1920×1080 at 5 to 30 fps. There are of course exceptions, i.e. the framerate is reduced at high resolutions in YUV mode, and there are also a few higher resolutions for shooting stills. You can see the full list of natively supported formats on my C920 wiki page.

Software support

In MJPG and YUV mode the camera can be used as is on pretty much any Linux distribution with video4linux support. The problem is if we want to use H.264 mode, and of course we want to, since this is why we got the camera.

First, you need Linux kernel 3.2 or later to have “H264 pixel format” supported in the v4l2 drivers. I heard some people talk that earlier kernels can be patched to work – I do not know, nor do I care wish to explore that option. AFAIK most recent Linux distributions come with Linux 3.2 or later so it shouldn’t be a problem.

Next, you will need video4linux libraries and utilities. These include:

  • libv4l and libv4l-dev
  • v4l-utils
  • qv4l2 (may be part of v4l-utils)
  • v4l2ucp

These are sufficient to check that the camera is working.

Use v4l2-ctl to check that you have proper H.264 support for the camera:

  # v4l2-ctl --list-formats
  # v4l2-ctl --list-formats-ext

See the help for other cool stuff you can do with v4l2-ctl.

You can use v4l2ucp to see all the parameters that can be adjusted. This is basically the same as “guvcview -o”. Unfortunately, guvcview does not yet support H.264 mode so we can’t use it to test that we have a working H.264 camera. For this purpose we can use qv4l2, which is a small Qt application very similar to guvcview. It can show the H.264 video coming from the camera at any of the supported sizes and frame rates. Unfortunately, it can not save the stream.

Capture the H.264 stream to disk

This H.264 pixel format seems to be so new, that not even the examples in the v4l2 documentation supports it. Thanks to Google, I found a hacked version of it which could be used to capture individual frames to disk. If the camera is set to H.264 format using v4l2-ctl, the frames would be H.264 frames, or at least part of an H.264 stream. I have since modified the hacked version so that it can save a continuous stream, either to a file or stdout. It is available here: https://github.com/csete/bonecam/tree/master/capture

To use this application, first set the C920 into H.264 mode at a specific resolution and framerate (I will use 800×448 at 30 fps):

  # v4l2-ctl --set-fmt-video=width=800,height=448,pixelformat=1
  # v4l2-ctl --set-parm=30

Next, start the capture program. Without any options it will save to a file, with the -o it will dump the stream to standard out. You can use this to pipe the stream to another applciation, such as a Gstreamer pipeline as I will show you in the next section.

Please note that for now my version of the capture application is part of a complete project with specific needs and I do not have time to maintain it as a project or anything. So don’t ask me to implement this or that feature – you can do it yourself.

Gstreamer

Although Gstreamer has a v4l2src input element, it does not yet support the video/x-264 format yet – at least not the version that I have installed on my Linux Mint 13 workstation. But this is really not a big deal! As we already can capture the H.264 stream and send to a file or even standard out, we can simply pipe it to the standard input of a gstreamer pipeline using a file source:

  #  ./capture -c 100000 -o | gst-launch -v -e filesrc location=/dev/fd/0 ! h264parse ! decodebin2 ! xvimagesink sync=false

To verify the framerate you can replace xvimagesink with fpsdisplaysink:

  #  ./capture -c 100000 -o | gst-launch -v -e filesrc location=/dev/fd/0 ! h264parse ! decodebin2 ! fpsdisplaysink fps-update-interval=5000

That’s it, you have your hardware encoded H.264 video stream in Gstreamer. Now you know why you are using Linux.

RTP unicast

The encoded video stream can be sent over the network using Gstreamer. On one machine with IP 192.168.1.100 start the player:

  #  gst-launch -v udpsrc port=4000 caps='application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264' ! 
          rtph264depay ! ffdec_h264 ! xvimagesink sync=false

Then start the server:

  # ./capture -c 10000 -o | gst-launch -v -e filesrc location=/dev/fd/0 ! h264parse ! rtph264pay ! udpsink  host=192.168.1.100 port=4000

The tests directory in the gst-plugins-good source tree contains many useful tips and tricks, see http://cgit.freedesktop.org/gstreamer/gst-plugins-good/


*** Important update February, 2014 ***

On recent Linux and Gstreamer 1.2 it is now possible to read H.264 streams from the Logitech C920 camera without using any external applications. See my followup post: Using the Logitech C920 webcam with Gstreamer 1.2