Building a DirectShow Code Sample in Visual Studio .NET

Recently, I had to write some Windows multimedia code--the idea was to build an extension to a media player with a bit of custom image processing. Not knowing a thing about multimedia under Windows, I had to spend a few hours reading about media APIs (DirectX, VideoLan, etc).

In the end, I decided that the path of least resistance was to employ DirectShow, which is a part of DirectX (at least, it used to be). DirectShow is a framework and API for handling media files, like audio and video; it has a nifty Pipes And Filters architecture. My plan-of-attack: I would find an existing application of the CTransformFilter baseclass, gut it, so to speak, and add my own image processing. How hard could it be?

A bit harder than it ought to be, as it turns out. Merely figuring out what software to download from the Microsoft site was a bit of a challenge, and once I had the relevant software development kit (or, actually, kits), it was still a slog to get the code in a useful state.

This article discusses the steps I took to download DirectShow, build a code sample (ezrgb24), then convert ezrgb24 to a Visual Studio .NET project.

Install SDKs

First, you'll need to download and install two Microsoft SDKs:

Recently, Microsoft decided to move their DirectShow code from the DirectX SDK into the Windows Platform SDK. This alone was confusing, but then it took a bit of sleuthing to determine that you actually need both the Windows Platform SDK and the DirectX to build the DirectShow library. sigh.

These are both hefty downloads, by the way. Don't dawdle.

Build DirectShow

Before using the DirectShow library, you must first build it. Currently, the source code is located in c:\platformsdk\Samples\Multimedia\DirectShow\BaseClasses (assuming you installed the Platform SDK under c:\platformsdk). We're going to build strmbasd.dll, the debug version of DirectShow.

  1. define an environment variable, DXSDK_DIR, which points to the top level of the DirectX SDK installation. The DirectShow makefile needs this environment variable to resolve DirectX references.

    • I installed the DirectX SDK directly under c:\, so I set DXSDK_DIR=c:\dxsdk

  2. using emacs, which is your favorite editor, open c:\platformsdk\Samples\Multimedia\DirectShow\BaseClasses\makefile.

  3. At the top of the file, define the symbol APPVER. The value of APPVER determines a number of other definitions in win32.mak. If you installed the SDKs, there are multiple versions of win32.mak hanging around on your PC (with conflicting definitions for APPVER). The critical file is the Visual Studio .NET win32.mak: C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\PlatformSDK\Include.

    • for Windows XP, set APPVER to 5.2 by adding this line: APPVER = 5.2

  4. Start the Visual Studio .NET Command prompt.
  5. Build the DirectShow debug library:

    • > cd c:\platformsdk\Samples\Multimedia\DirectShow\BaseClasses\ 
      > nmake clean
      > nmake
  6. The library, strmbasd.lib, is built in subdirectory .\xp32_debug (for APPVER=5.2).

Build the ezrgb32 Sample

Next, we'll build the DirectShow example ezrgb32. For mysterious reasons, Microsoft chose not to distribute Visual Studio solutions for building the examples, only nmake makefiles (it sounds like the examples once came with Visual Studio projects, but no longer). The makefiles are fine for building the examples, but there are obvious advantages to using the Visual Studio IDE--namely, the debugger works properly.

Build from Makefile

The first step is to build ezrgb32 from the makefile. The source code is located in c:/platformsdk/Samples/Multimedia/DirectShow/Filters/EZRGB24.

  1. open c:/platformsdk/Samples/Multimedia/DirectShow/Filters/EZRGB24/Makefile

  2. At the top of the makefile, define MSSDK to point to the Platform SDK directory. In my case, I add the line MSSDK=c:\platformsdk.

  3. At the top of the makefile, define APPVER to indicate your OS, as in the previous step. For Windows XP, use APPVER=5.2

  4. From the Visual Studio .NET Command Prompt, run nmake:
    • > nmake clean 
      > nmake
  5. If it works, the ezrgb32 filter will be built in .\XP32_DEBUG as ezrgb24.ax.

You can register the ezrgb24.ax filter (using regsvr32) and try out the filter with GraphEdit.

Migrate to a Visual Studio Project

Finally, let's create a Visual Studio project which accomplishes the same thing as the makefile.

  1. Copy the ezrgb24 directory to a new directory, e.g. c:\ezrgb24_vs

    • This step avoids some file naming problems later; for example, Visual Studio will generate .cpp, .h, and .def files, and the new files will clobber any existing files
  2. Define some handy environment variables for the compiler & linker:

    • Define STRMBASE_INCL to point to the directory containing DirectShow header files

    • Define STRMBASE to point to the location of the DirectShow library you just built

    • STRMBASE_INCL=c:\platformsdk\samples\multimedia\directshow\baseclasses 
      STRMBASE=STRMBASE_INCL=c:\platformsdk\samples\multimedia\directshow\baseclasses\xp32_debug
  3. Start Visual Studio.
  4. Select File->New->Project

  5. Under Visual C++ Projects/MFC, select the MFC DLL template.

  6. Specify the name & location of your new solution: c:\ezrgb24_vs

  7. In the Solution Explorer pane, delete all of the default stuff which comes with the solution:
    • ezrgb24_vs.cpp, ezrgb24_vs.def, stdafx.cpp, ezrgb24_vs.h, stdafx.h, resource.h, ezrgb24_vs.rc, ezrgb24_vs.rc2
  8. Add the existing files
    • ezprop.*
    • ezrgb24.*
    • iez.h
    • ezprop.rc
    • ezrgb.def (not strictly necessary, but nice to have around)
  9. Under Project->Properties, set the compiler options (under C/C++)

    • Additional Include Directories:  $(STRMBASE_INCL); $(DXSDK_DIR)\include;   
      Preprocessor Definitions:  WIN32;_WINDOWS;_DEBUG;_USRDLL
      Runtime Library:  Multi-threaded Debug DLL (/MDd)
      Treat wchar_t as Built-in Type:  No
      Create/Use Precompiled Header:  Not Using Precompiled Headers
      Calling Convention:  __stdcall (/Gz)
  10. Set Linker options:
    • OutputFile:  $(OutDir)/ezrgb24_vs.ax 
      Additional Library Directories:  $(STRMBASE);
    • Additional Dependencies:
      strmbasd.lib msvcrtd.lib atlsd.lib quartz.lib vfw32.lib winmm.lib kernel32.lib    
      ws2_32.lib mswsock.lib advapi32.lib version.lib user32.lib gdi32.lib comctl32.lib ole32.lib
      olepro32.lib oleaut32.lib uuid.lib
    • Ignore All Default Libraries:  Yes (/NODEFAULTLIB) 
      Module Definition File:  .\ezrgb24.def
      Import Library:  $(OutDir)/ezrgb24.lib
  11. Set Resource build options:
    • Additional Include Directories:  $(IntDir); $(STRMBASE_INCL)

At this point, you should be able to build the filter directly from Visual Studio (Build->Rebuild Solution). The output file will be debug\ezrgb24_vs.ax.

At this point, you can throw that Makefile away.

Bonus Tip: Register as Part of the Build

You can make Visual Studio register the filter with regsvr32 as part of the build process:

Project->Properties->Custom Build Step

Command Line:c:\windows\system32\regsvr32.exe $(OutDir)\ezrgb24_vs.ax
Description:register filter w/ regsvr32
Outputs:faketarget.dat
Additional Dependencies:$(OutDir)\ezrgb24_vs.ax

Bonus Tip: Debugging

Debugging: Since we've gone to all this effort to set up a Visual Studio project, we may as well set up the debugger. The ezrgb24 filter runs as part of a DirectShow application, so we'll use GraphEdit to run the filter.

  1. Using GraphEdit, create and save a render graph using ezrgb24_vs.ax. Call it render.grf. If you don't know how to use GraphEdit, go spend some time with google and come back when you're ready.

  2. In Visual Studio, set the debugger properties:
    • Project -> Properties

    • In the left pane, click Debugging
    • Command:  graphedt.exe (replace with appropriate path to your graphedt.exe) 
      Command Arguments:  render.grf
  3. At this point, you should be able to set a breakpoint in your filter code then select Debug->Start. GraphEdit should execute with your predefined graph. Start rendering. When the code hits your breakpoint, you'll magically drop into the debugger.



CategoryNerd