Thursday, October 30, 2008

Accessing Webcam & pre-process frame

One evening I asked myself how to access my laptop webcam (a noname 1.3MP cam integrated into my HP Pavillon dv6XXX) by code. As I faced a little problem with this, I want to share my experience with you.

A look at msdn/internet revealed the Windows Capture Functions, all starting with the prefix cap. Creating the capture window, connecting to the driver, scaling, enabling preview - all very easy as these are just simple function calls. Cause I wanted to preprocess the frame (in order to implement some algorithms to make nice effects - which is not done yet and will take some more time...) I engaged a frame callback function without problem.

But then a little obstacle occured: how is the frame data stored? Using capGetVideoFormat, I accessed the bitmapinfoheader structure and checked the biBitCount member - 16 Bits. Ok - nice - and started coding immediuately which turned out to be a mistake!
The color members were not stored as specified in the msdn library: least significant five bits blue, followed by five bits each for green and red and the most significant bit is unused.

At first I thought I introduced a bug on my bit operations to extract these bits - but no, works perfectly.

Ok, no big deal - as I wished the data to be 24bit RGB, I wanted to use capSetVideoFormat to change the captued video data to this format. But of course this solution would have been too easy - this function always returned FALSE meaning my webcam driver does not like another format :-(

So what was the problem?
While tracing the program I saw the bitmapheader structure values in the debugging window inside visual studio and the biCompression member caught my eyes: 844715353. Hm such a value is not predefined as e.g. BI_RGB etc. I converted this number to hex = 0x32595559 and searched the internet to find out that this is the fourcc of YUY2! Another search brought my to the great website where this format (and many others) is explained:
a simple 4:2:2 YUV format with byte order Y1 U Y2 V. With this info it's of course easy to preprocess each frame of my webcam as I want.
Of course a better BitmapInfoHeader Page at msdn would have saved me a lot of time... Although interestingly a few days later I found this page at msdn where I found exactly my required information - but just too late.

I hope this will help someone facing the same problem while accessing a webcam!