FocusUF or how to turn off the autofocus setting of the LifeCam HD-5000 webcam

Welcome to the FuzzyCam

Why am I out of focus? It’s because I have a Microsoft LfeCam HD-5000 and I’m running Windows 10. The LifeCam HD-5000 webcam is a decent webcam with an annoying feature. The autofocus keeps shifting the focus around if you move your head slightly. It goes in and out of focus and locks in after a second or two.  When you are in a video chat, this can get very annoying (very quickly) for the other viewers. Your face will shift in and out of focus and it’s just a distraction.  Microsoft used to supply drivers for the HD-5000 and it had a control app where you could adjust the focus settings. Since Windows 8, they stopped as the OS directly supported the webcam.

I’m not able to sit motionless while on a webcam. I needed a work around. There is a registry hack that lets you turn off autofocus. I prefer to avoid hacks like that when it’s something that I could code around. So after seeing some stuff on StackOverflow on how to use the IAMCameraControl interface in DirectShow, I wrote a tiny command line app called FocusUF.

FocusUF uses the DirectShowLib library library to provide nice, friendly C# access to DirectShow. The DirectShowLib library maps the DirectShow Interfaces for use from a .NET app. With that library, it was little more than a handful of lines of code to access webcam controls. The app is hard coded to connect to a LifeCam HD-5000, but it would be easy enough to change the code for other webcam.

The code was written with Visual Studio 2017, it has not been tested with any other compiler. The source code is up on GitHub via this handy little URL.

How it works

To use the DirectShowLib library, I added it via nuget.

Install-Package DirectShowLib

The next step was to get access to the webcam. Using DsDevice from DirectShowLib, I was able to get the list of devices for the category of VideoInputDevice. Then I do a LINQ query to filter that list for the first match “Microsoft® LifeCam HD-5000”. If you are having a autofocus problem with a different brand or model of webcam, just replace that name with the name of your webcam. You can dump out the list of DsDevices and peek at the name property until you see your webcam.

Now that I have a DirectShow  sDevice that represents the webcam, I create a filter to expose the control interface of the web cam. DirectShow uses a module system called filters to expose device functionality. I create a new object that implements the IFilterGraph2 interface so that we can add a new filter. After getting that filter, I cast it to an IAMCameraControl to get access to the setter and getter methods. I get the current focus level and mode from the webcam.  I then set the focus to the current level and force the focus mode to manual.

How to use

Launch the app that will be using the webcam. Wait until it is in focus and then run FocusUF. It will detect the webcam and flip the autofocus setting to manual and lock it to the current focus setting. The setting will persist until the webcam is reset or another app changes the focus setting.

I probably looked better out of focus…

The name “FocusUF” is a tip of the hat to the YouTube channel AvE, where the host uses the phrase “Focus You F@*&” whenever his video camera loses focus.

Debugging devices without displays or debuggers

I’ve been writing firmware for an RFID reader that connects over USB to an Android device.  Our installers will need to upgrade the readers out in the field and they have no way of knowing which firmware has been installed.  The reader, an Elatec TWN4, has a pretty decent API that you write code for, using the C language.  Their API includes a wonderful function called “Beep”.  You pass in the volume, frequency, how to play the tone (in ms), and finally, how long to be quiet after the tone has been played.  So I have been setting the readers to play a few notes on power up.  This allows the installers to know which firmware has been installed.

The original firmware plays the opening notes to “Smoke On The Water”.  Because anything that can produce at least 4 notes can play it.  The following C code will beep it’s way through some vintage Deep Purple

We added some code to the firmware to allow our app to put the reader is a sleep mode.  Our installers will need to upgrade a few devices out in the field, so it was time to change that tune.  By checking a few different sites, we found simplified chord progressions for some recognizable songs.  My choices were restricted to simple note changes, you can’t generated complicated chords from a device that only knows how to beep.  It does that beep very well, but at the end of the day it’s only a beep.

I needed to play something else to let the installers know that the firmware had been updated.  Something short, something simple, something simple.  One of my musically inclined co-workers worked out the opening notes of “The Final Countdown” by Europe.  That song has a distinctive opening riff.  And many cover versions.  Some might say too many,

I found a note to frequency conversion table and used that to create a set of constants for the notes I needed.  That allowed me to specify the beeps with readable note constants, instead of the frequency values. You can get those constants here.  With the use of those constants, you can play the opening notes of “The Final Countdown” with the following code:

When using the constants, the code is much easier to read.  And it becomes much easier to create new song intros. With that in place, the installers can quickly check the firmware version by powering up the RFID reader.  At some point I’ll refactor the code to just read the values from an array.  The current design is easy to setup and read, I may just stay with what works.

Right now, I need to use Elatec’s development tools to push the firrmware out via a simple GUI.  If I could get a command line tool for pushing the firmware out, I could add code to the firmware to return the version number from a query sent over USB.  That would allow me to write a simple app or Powershell script to identify a connected reader, query the version, and then push the update out.  If anyone from Elatec ever reads this, a command line firmware updater would be very helpful.

Decades of using development tools like Visual Studio has accustomed me to being able to use a debugger to step through the code.  Writing code where you can’t visually debug it, requires thinking out side the box.  I can test much of the code by having the reader send back text, but when testing with the device that it will be hooked up to, that would interfere with how they work.  Sometimes you just have to use a different path out of the machine to see what it’s doing.