# v4l2grab – Grabbing JPEGs from V4L2 devices

A friend of mine, wanted to use a standard USB WebCam as an IPCam. He used an old Media-Receiver Box (T-Online S100) and installed Gentoo Linux on an CF Card.

Since Kernel 2.6.27 most of the USB webcams are supported through the Linux UVC drivers, which provides an Video4Linux2 Interface to those cams. We found some programs who claimed being able to grab JPEG images from V4L2 Cams, but most of them either didn’t compile, supported only V4L Version 1 or just brought up some other errors.

So I checked up the Video for Linux Two API Specification and found there in Appendix B a small sample of howto communicate with the Cam. I adapted it to our needs and included an converter from YUV colorspace to RGB. Finally I added some code to support the export of JPEG images.

You can download it here: v4l2grab Version 0.1

The whole program is written in C and only needs libjpeg to compile. There are different ways to communicate with the camera, if you want to support all, you should go best with:

gcc v4l2grab.c -o v4l2grab -Wall -ljpeg -DIO_READ -DIO_MMAP -DIO_USERPTR

If you compiled the program, you can get some images with:

./v4l2grab -o image.jpg

With -W width -H height its possible to adjust the size of the image. If the camera doesn’t support the resolution the programs adjusts it automatically and prints an information on stderr.

The current version of V4L2grab can be found on github.

This entry was posted in Linux, Software and tagged , by twam. Bookmark the permalink.

## About the author

My name is Tobias Müller and I'm cur­rent­ly working on my PhD in theo­re­ti­cal astro­physics. I'm interested in com­puters, physics, elec­tronics and photo­graphy. more …

## 39 thoughts on “v4l2grab – Grabbing JPEGs from V4L2 devices”

1. I’m trying to use a webcam in V4L2_PIX_FMT_MJPEG format (not V4L2_PIX_FMT_YUYV) and grab image into jpeg files, some ideas on how do it?

2. Hoi,

Great work! It would be a good idea to add the compile statement to the readme file on github.
Works like a charm!

Groeten,
Frank.

3. I just built this for the DM3730 Logic SOM running Linux built from the 2.6.32 OMAP PSP_03.00.01.06 kernel from TI. I used libjpeg62-dev. Worked right out of the box. Great work.

Thanks,
Jemiah
.

4. I was running v4l2grab on ARM with logitech C200.
Even set the format by using VIDIOC_S_FMT, I still get 176×144 size of image.
I saw the notes in source as follow:
‘Note VIDIOC_S_FMT may change width and height.’

5. Hi,

I’m trying to compile v4l2grab for an ARM processor and can see that some of you have already succeded in that. Could you please give me a step by step guide on how to accomplish this task? Thanks in advanced

/Anders

6. On v5l ARM machine I have no compilation issue:

gcc v4l2grab.c -o v4l2grab -Wall -ljpeg -DIO_READ -DIO_MMAP -DIO_USERPTR

7. This is a very useful little utility, nice code, but has a stutter.

I’ve added some debugging text

static void imageProcess(const void* p)
{
unsigned char* src = (unsigned char*)p;
unsigned char* dst = malloc(width*height*3*sizeof(char));

// convert from YUV422 to RGB888
printf("Munge\n"); fflush(stdout);
YUV422toRGB888(width,height,src,dst);

// write jpeg
printf("Write\n"); fflush(stdout);
jpegWrite(dst);

// free temporary image
free(dst);
}
# ./v4l2grab -m -o test.jpg
1Open
Init
Start
Munge
Write
Munge
Write

Should it not read a frame once, process it once, and write t once ?

Thanks,
Jon

8. Jonathan Andrews:
Should it not read a frame once, process it once, and write t once ?

The program is reading the frame again, when the read returned an EAGAIN error.

9. Hallo Tobias,

super kleines Tool. Genau was ich gerade gesucht habe, um nicht mit Kanonen auf Spatzen zu schiessen.
Runter laden, übersetzen und laufen lassen. Ohne Fehler; einfach so !!!

Vielen Dank
Franz

10. Was ich vergessen habe:

I use OpenSuse 12.1 (64 Bit ) on AMD Quadcore 2,9 Ghz with USB – Logitech, Inc. Webcam C270 .

Thanks
Franz

11. /tmp/cc6gk2Pb.o: In function imageProcess’:
v4l2grab.c:(.text+0×258): undefined reference to YUV422toRGB888′
collect2: ld returned 1 exit status

i am getting this error when i compile the programme

12. @vijay
It look like you tried to compile it with the line given in the post above. The latest version supplies a makefile, so you just have to run ‘make’ to compile the program.

13. Thanks for sharing this example, it was very helpful! Moreover, work out of the box Thanks again Tobias.

14. This runs without error:
# gcc v4l2grab.c -o v4l2grab -Wall -ljpeg -DIO_READ -DIO_MMAP -DIO_USERPTR

But I am getting a “select timeout” error when I run the following (on a BeagleBone Armv7 processor)
# ./v4l2grab -o image.jpg

15. @twam The latest version from Github gives me the following error:

# make
gcc v4l2grab.c -c -Wall -march=native -Werror
cc1: error: bad value (native) for -march switch
make: *** [v4l2grab.o] Error 1
16. @Owen
Just try to remove the -march=native inside the makefile as this might be not support on old gcc versions.

17. @twam I was able to compile and run ./v4l2grab -o image.jpg without errors but I can’t seem to locate any produced image files.

18. hi again.
I believe to compile libjped. the screen gave this message

halil@toshiba:~/İndirilenler/jpeg-8d\$ ./configure
checking build system type... i686-pc-linux-gnu
[...]
config.status: executing libtool commands

But I tried to work gcc v4l2grab.c -o v4l2grab -Wall -ljpeg -DIO_READ -DIO_MMAP -DIO_USERPTR and I gave this error message

v4l2grab.c:26:2: error: #error You have to include one of IO_READ, IO_MMAP oder IO_USERPTR!
v4l2grab.c:45:21: error: jpeglib.h: Böyle bir dosya ya da dizin yok
[...]

Can you help me about this issue. what do I do? thanks you for your helps

19. @halo
After running configure, you usually need to run make; make install. Detailed information should be found in the README.

But you should think of installing it through your distributions package manager. There should be something like a libjpeg-dev package.

20. Hi @twan,
I compiled this app successful, and when I ran it with
# ./v4l2grab -d /dev/video0 -o out.jpg
and the only thing I’v got is
Using pixel format V4L2_PIX_FMT_YUYV.
and no any output images. Can you please help me out here? Thx.

21. @twam
No other ouput, and the app is pending so I have to use ctrl-c to exit.

22. @Jedisun
Then the app is waiting for images from the webcam. Do you get images from the webcam in other apps thru the v4l2 API, e.g. mplayer?

23. One error is caught:
Pixel format V4L2_PIX_FMT_JPEG not supported!

How to grab a JPEG frame from a usb camera with V4L2_PIX_FMT_JPEG support only?

24. @Yangpu
You would have to implement the function capable of reading the format. As my cameras doesn’t support this format, I’m not able to try this

25. HI,

Thanks for sharing!
I’m a beginner on Linux and we need our camera to take pictures for our project.
I am using a beagleboard xM that runs Angstrom with kernel 2.6.32.
I first installed libjpeg using tarbal from their website. And then i tired your v0.1 and latest version from github; both of them were built fine but when i run them they give:
./v4l2grab: error while loading shared libraries: libjpeg.so.9: cannot open shared object file: No such file or directory

Any idea?

Your help is very much appreciated!!

• You can run

ldd v4l2grab

to see against with librarys your program is linked. You should something like

	linux-vdso.so.1 =>  (0x00007fff70185000)
libjpeg.so.8 => /usr/lib/x86_64-linux-gnu/libjpeg.so.8 (0x00007f0630710000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0630351000)
/lib64/ld-linux-x86-64.so.2 (0x00007f0630984000)


If libjpeg.so.* is not found, check that the file is one of your lib directories or set LD_LIBRARY_PATH accordingly. Maybe you forgot an make install as root after compiling your libjpeg.

• Hi,

I did check with “ldd” and yes it says ” libjpeg.so.9 => not found”
However, when I do “ls /usr/local/lib”, the libjpeg.so* files are there…

So i copied the lbjpeg.so.9 from /usr/local/lib to /lib and now v4l2Grab works.

However, when I call imgcmp, which is a part of jasPer and that it seems to require libjpeg at runtime, it prompts” JPEG decoder not available”….and asks me to install libjpeg…
I did “ldd imgcmp” and it says:
libm.so.6 => /lib/libm.so.6 (0×40026000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0×40099000)
libc.so.6 => /lib/libc.so.6 (0x400ab000)
/lib/ld-linux.so.3 (0×40000000)
Which seems to say that all needed .so files are in /lib…

I don’t know whats going on…

Thanks,

26. Hi Tobias,
thanks for posting the code. I confirm that the code compiles flawlessly and works on my Debian Squeeze system. I was able to capture images at the highest possible resolution ( 2592 x 1944 pixes) from a Logitech C-910 webcam.
Cheers, Rob

• I should add that I compiled v0.1. Version 0.3 from the github complains that libv4l2.h is missing

• The latest version (0.4.1) should be noticeable faster, when you want to grab many pictures.

When you found out, how the corresponding packages you need are installed on Arch Linux, please add them to the Installation instructions.

27. Hi! I got some problem when I was cross-compiling the code in hope to port your program on ARM processor. The make error messages are something like that:

/opt/embedded/collections/v4l2grab/v4l2grab.c:118: undefined reference to v4l2_ioctl’

I know it’s linking errors. But I do have libv4l2.so and libv4lconvert.so as well as their header files in my arm-linux-gcc compiler directory. That’s weird. Your code has been successfully compiled on my i686 platform PC. So I want to ask what’s the problem there? Thank you!

28. Did you tell your compile to actually link the libraries? May you have to add the path to search in for the cross-compiled libraries.

• OK, I’ve solved the compiling problem. I’m not very familiar with gcc command so I just added into Makefile -I”compiler include directory” and -L”library directory” rather than -lv4l2 and -lv4lconvert.
Also, for arm-linux-gcc, there was also a problem occurred: undefined reference to rpl_malloc’. I solved this problem by deleting the line:
#undef malloc
in file config.h.in and then rerunning ./configure –host=arm-linux –target=arm-linux. After all those steps, I finally got an executable binary file. Hope this will help others who may have same problems. But I’m just curious about why this ‘rpl_malloc’ problem happens?