This post is a quick little ditty about how to enumerate over all video capture devices on your machine using the DirectShow.NET library.

The DirectShow.NET library is a C# library that sits atop Microsoft’s DirectShow API. This library helps you avoid some of the headaches associated with accessing unmanaged libraries from managed code. For our simple example of iterating over all video input devices, we will see that it does a marvelous job of achieving this goal.

We will be using Visual Studio 2010, NUnit, and TestDriven.NET to power this sample in a TDD way.

Start out by downloading the DirectShow.NET library and extracting the contents. At the time of this writing, the latest version is 2.1. Once everything is extracted, you should see a lib folder which contains the single DLL for the library. Remember this location, as we will need it soon.

 

Setup

Next, spin up a couple of new class library projects, one for the code to find our video capture devices, and the other to test. Use NuGet (you do have NuGet installed, right?) to pull down NUnit into your test project. Next, create folders in each of your new projects called “ReferencedLibraries” and copy the DirectShowLib-2005.dll file we found in the lib folder up above into each of these folders. Finally, add references to this library from each of the projects you have just created. Your solution should appear as below.

baseSolution

 

Code

Now we get to write some code. We’ll assume that you have at least one video input device connected to your computer (otherwise why are you here?). We start with a test.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using CamEnumeration;

namespace CamEnumerationTests
{
    [TestFixture]
    public class CaptureDeviceEnumeratorTests
    {
        [Test]
        public void CanDetectMyWebCamTest()
        {
            var x = new CaptureDeviceEnumerator();

            int numberOfDevices = x.AvailableVideoInputDevices.Count;

            Assert.That(numberOfDevices, Is.AtLeast(1));
        }
    }
}

 

From this we can intuit that our class will be called “DeviceEnumerator” and we will be depending on a property called “AvailableVideoInputDevices” to find our web cam. Next we add a reference from our test project to our main project and write some code that will make our test pass.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DirectShowLib;

namespace CamEnumeration
{
    public class CaptureDeviceEnumerator
    {
        public CaptureDeviceEnumerator()
        {
            AvailableVideoInputDevices = new List<DsDevice>();
            GetAvailableVideoInputDevices();
        }

        public List<DsDevice> AvailableVideoInputDevices { get; private set; }

        private void GetAvailableVideoInputDevices()
        {
            DsDevice[] videoInputDevices =
                DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
            AvailableVideoInputDevices.AddRange(videoInputDevices);
        }
    }
}

 

The good stuff is happening in the GetAvailableVideoInputDevices method here. This is all the DirectShow.NET library shielding us from the pain of actually interfacing with DirectShow, well, directly. DsDevice is a helper class that the DirectShow.NET library exposes and makes getting a list of DirectShow-supported devices trivial. Changing our test to spit out the names of our devices during the test, we can see the kind of information we get back. First, the code we add at the bottom of the test.

// diagnostic
foreach (DirectShowLib.DsDevice d in x.AvailableVideoInputDevices)
{
    Console.WriteLine(d.Name);
}

 

Finally, the output on my system.

devicesOnMySystem

 

We have constrained ourselves to video input devices for this sample, but a quick inspection of the FilterCategory enumeration reveals quite a few more supported devices.

using System;

namespace DirectShowLib
{
    public static class FilterCategory
    {
        public static readonly Guid ActiveMovieCategories;
        public static readonly Guid AMKSAudio;
        public static readonly Guid AMKSCapture;
        public static readonly Guid AMKSCrossbar;
        public static readonly Guid AMKSDataCompressor;
        public static readonly Guid AMKSRender;
        public static readonly Guid AMKSSplitter;
        public static readonly Guid AMKSTVAudio;
        public static readonly Guid AMKSTVTuner;
        public static readonly Guid AMKSVBICodec;
        public static readonly Guid AMKSVideo;
        public static readonly Guid AudioCompressorCategory;
        public static readonly Guid AudioEffects1Category;
        public static readonly Guid AudioEffects2Category;
        public static readonly Guid AudioInputDevice;
        public static readonly Guid AudioRendererCategory;
        public static readonly Guid BDANetworkProvidersCategory;
        public static readonly Guid BDAReceiverComponentsCategory;
        public static readonly Guid BDARenderingFiltersCategory;
        public static readonly Guid BDASourceFiltersCategory;
        public static readonly Guid BDATransportInformationRenderersCategory;
        public static readonly Guid CPCAFiltersCategory;
        public static readonly Guid DeviceControlCategory;
        public static readonly Guid DMOFilterCategory;
        public static readonly Guid KSAudioDevice;
        public static readonly Guid KSCommunicationsTransform;
        public static readonly Guid KSDataDecompressor;
        public static readonly Guid KSDataTransform;
        public static readonly Guid KSInterfaceTransform;
        public static readonly Guid KSMixer;
        public static readonly Guid LegacyAmFilterCategory;
        public static readonly Guid LTMMVideoProcessors;
        public static readonly Guid MediaEncoderCategory;
        public static readonly Guid MediaMultiplexerCategory;
        public static readonly Guid MidiRendererCategory;
        public static readonly Guid TransmitCategory;
        public static readonly Guid VideoCompressorCategory;
        public static readonly Guid VideoEffects1Category;
        public static readonly Guid VideoEffects2Category;
        public static readonly Guid VideoInputDevice;
        public static readonly Guid WDMStreamingEncoderDevices;
        public static readonly Guid WDMStreamingMultiplexerDevices;
    }
}

 

A simple example, but it demonstrates some of the capabilities of the DirectShow.NET library. Enjoy.

  7 Responses to “Finding Your Web Cam with C# & DirectShow.NET”

  1. When I try to implement it, C# cannot find CaptureDeviceEnumerator(). Where is it located?

    • Did you make sure you are importing all the correct libraries?

      • Yes, there was a very small mistake I made, a typo one can say.

        I am very new to C# (a few days…), and this is fascinating. I might be captain obvious here, but I couldn’t display the name of the device, until I added the following line before the diagnostic code:

        CamEnumeration.CaptureDeviceEnumerator x= new CamEnumeration.CaptureDeviceEnumerator();

        Thank you, this is wonderful. Now I need some followup on how to make a user to pic a specific device in a dialog, and I am done ;)

        Thank you!!!

  2. [...] post builds upon prior work where we used C# with DirectShow.NET to enumerate video capture devices on a given machine. We use [...]

 Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

   
© 2011 Musings of the Bare Bones Coder Suffusion theme by Sayontan Sinha