Click here to Skip to main content
15,069,133 members
Articles / Multimedia / DirectX
Posted 4 Jan 2006


57 bookmarked

Using third-party filters in a video application in C#

Rate me:
Please Sign up or sign in to vote.
4.14/5 (3 votes)
4 Jan 20065 min read
A simple application to test DirectShow filters.

Image 1


DirectShow filters are the basic building blocks of multimedia applications on the Windows platform. Many of these filters are provided by Microsoft as part of their operating systems. But even more filters are created by ISVs and developers. In this article, we'll see how to use filters that we have written previously in a simple video application.


In a previous article, I created two filters in C#. In this article, I'll create a simple application that makes use of these filters. The application will have two windows: one that displays the original video and, the second one showing the result of applying the filters on the video. Moreover, the application has widgets to control the video and the threshold value of the Sobel transformation.

Besides testing the filters, we'll make use of the "Infinite Tee" filter from MS in order to duplicate the video stream for our two windows. The graph created for this application is not completely trivial, and we'll have the opportunity to write a couple of methods in order to simplify the task.

Using the code

In order to run the application, the Black and White filter and the Sobel transformation filter must be installed on your machine. More information can be found in my previous article. In order to write programs that make use of these filters, or any other third-party filters, you need to have the GUID of the filter. They should be provided by the supplier; in our case, we have the source code of the filters and we find that the GUIDs, we are looking for, are:

// the Guids for our custom filters
Guid sobelGuid = new Guid( "1C826B9A-4008-4C41-B601-A783A40AFAB2" );
Guid bwGuid = new Guid( "0C017086-684E-41c9-A4BB-640570C64B28" );

Moreover, our Sobel filter provides a custom COM interface, so our code has the following declarations:

// The ISobel interface is a custom COM interface
// exposed by the Sobel filter, in order to access it
// from C#, we need to define it
public interface ISobel
    int SetThreshold( int newValue );

Points of Interest

Besides some common DirectShow interfaces, we use the following objects:

// We'll use an Infinite Tee filter object to duplicate the
// video stream by two
InfTee tee = null;

// We'll only treat wmv format 
WMAsfReader reader =  null;

// The Sobel object and filter interface
object sobelObject = null;
IBaseFilter sobel = null;
// the black and white filter interface
IBaseFilter bw = null;

The Infinite Tee filter is a MS-supplied filter that delivers the sample received on its input pin to an arbitrary number of output pins. We use it to have one sample (or in our case, video frame) displayed without any transformation and a copy of the frame fed to our black and white filter.

The graph we'd like to build is the following:

Image 2

We have to add the objects for the Black and White, the Infinite Tee, and Sobel filters to the filter graph. There is nothing unusual about these steps. Then, we configure a WMAsfReader object (if you'd like to treat other file types besides those from Windows Media, you'd have some extra code to write here). Now, we have to connect the pins of the Infinite Tee filter. For this, we have the following code:

// connect video source to infinite tee filter
IPin teeInput = DsFindPin.ByDirection( (IBaseFilter)tee, 
                                PinDirection.Input, 0 );
IPin vidOutput = DsFindPin.ByDirection( (IBaseFilter)reader, 
                                   PinDirection.Output, 0 );
// check if the video stream is on the first pin
if( CheckVideo( vidOutput ) )
  graphBuilder.Connect( vidOutput, teeInput );
else // video stream is on second pin
  vidOutput = DsFindPin.ByDirection( (IBaseFilter)reader, PinDirection.Output, 1 );
  graphBuilder.Connect( vidOutput, teeInput );

First, we grab the input pin of the Infinite Tee filter and the output pin of the WMAsfReader, and we check if the first output pin of the WMAsfReader is for a video stream. If it is, we connect this pin with the Infinite Tee input pin. If it is not a video stream, we assume that the second pin is a video stream and we connect it to the Infinite Tee filter. Since the first output pin of the Infinite Tee filter is now a video stream, we call Render (not shown) to complete this part of the graph. Because the Black and White filter and the Sobel filter were added to the graph before this call, "Intelligent Connect" will insert these before the video renderer that it will add to the graph to render this pin. Then, we configure the first video renderer window, in particular, we set its owner property to one of the panels used by our form. We expect this condition to be satisfied later on when we search the graph for the second video renderer.

Then we call Render for the second output pin of the Infinite Tee filter. Since our custom filters have been used in the first call to Render, this call will create a "standard" path to a new video renderer object. Now, we are faced with a problem: we have two video renderers in the graph and we would like to configure the second one, how do we do that? Well, the method GetSecondRenderer was written to simplify this task:

// This method find the second renderer in the filter graph;
// it assumes that the first renderer had its "owner" property set
IVideoWindow GetSecondRenderer() 
  IEnumFilters enumFilters;
  ArrayList filtersArray = new ArrayList();

  IFilterGraph filterGraph = (IFilterGraph)fg;
  filterGraph.EnumFilters(out enumFilters);
  IBaseFilter[] filters = new IBaseFilter[1];
  int fetched;

  while(enumFilters.Next(1, filters, out fetched) == 0)
    IVideoWindow ivw = filters[0] as IVideoWindow;
    if( ivw != null ) 
      IntPtr outPtr = new IntPtr();
      ivw.get_Owner( out outPtr );
      if( outPtr == IntPtr.Zero )
        return ivw;
  return null;

We enumerate all the filters in the graph and we QI for the IVideoWindow interface. If this succeeds, then we check the "owner" property. If it is "null", we know that we have found the correct renderer. After that, we set a few properties and we are ready to run the graph.

One interesting event handler is the handler for the trackbar ValueChanged event. We want to change the threshold for the Sobel transformation filter. But this property is a custom COM interface on the Sobel filter object, so we use the following code:

// access the ISobel interface on the sobel object
ISobel isobel = sobelObject as ISobel;
if( isobel != null ) 
  isobel.SetThreshold( trackBar1.Value );
  label1.Text = "Treshold value: " + trackBar1.Value.ToString();

We query the COM component object for the ISobel interface and we call the SetThreshold method on this interface.

Limitations and known issues

The Black and White filter is really minimal, its processing will work for common "320X240" video files, but might run into difficulties with other settings.

There is small lag between the original frame and the transformed one. As Sobel transformation is computationally expensive, this was to be expected but I haven't measured the "Infinite Tee" overhead (if any).

The application only treats Windows Media Files, it wouldn't be hard to modify it in order to treat .mpeg and .avi files, for examples.


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

United States United States
You can read my blog entries at:

Comments and Discussions

GeneralVideos to RAW format Pin
spoonfeeder28-May-09 20:47
Memberspoonfeeder28-May-09 20:47 
Generalproblem to use sober filter Pin
thorodin12329-Apr-09 1:58
Memberthorodin12329-Apr-09 1:58 
GeneralInfTee Filter Pin
owen99244-Nov-08 20:55
Memberowen99244-Nov-08 20:55 
Questionmodifications to play .avi files? Pin
whitehat.c7-Sep-08 1:52
Memberwhitehat.c7-Sep-08 1:52 
AnswerRe: modifications to play .avi files? Pin
daniel0497-Sep-08 2:49
Memberdaniel0497-Sep-08 2:49 
GeneralRe: modifications to play .avi files? [modified] Pin
whitehat.c7-Sep-08 6:40
Memberwhitehat.c7-Sep-08 6:40 
Generalhelp ! No Audio Pin
桉树28-May-08 0:29
Member桉树28-May-08 0:29 
GeneralRe: help ! No Audio Pin
daniel04931-May-08 11:01
Memberdaniel04931-May-08 11:01 
GeneralRe: help ! No Audio Pin
桉树3-Jun-08 15:13
Member桉树3-Jun-08 15:13 
Generaladding third-party filter Pin
vaddr4-Oct-07 5:03
Membervaddr4-Oct-07 5:03 
GeneralRe: adding third-party filter Pin
daniel0495-Oct-07 3:03
Memberdaniel0495-Oct-07 3:03 
GeneralRe: adding third-party filter Pin
vaddr5-Oct-07 7:33
Membervaddr5-Oct-07 7:33 
GeneralRe: adding third-party filter Pin
vaddr5-Oct-07 7:39
Membervaddr5-Oct-07 7:39 
Generalput_Owner(null) is missing Pin
PetoG24-Sep-07 10:58
MemberPetoG24-Sep-07 10:58 
GeneralRe: put_Owner(null) is missing Pin
daniel04924-Sep-07 14:15
Memberdaniel04924-Sep-07 14:15 
QuestionWindows Media Encoder Pin
shfnet12-Apr-07 1:55
Membershfnet12-Apr-07 1:55 
AnswerRe: Windows Media Encoder Pin
daniel04913-Apr-07 6:16
Memberdaniel04913-Apr-07 6:16 
QuestionHow can I give a byte array as input to a filter graph ? Pin
Ghoditsttoawn29-Mar-07 22:37
MemberGhoditsttoawn29-Mar-07 22:37 
AnswerRe: How can I give a byte array as input to a filter graph ? Pin
daniel04930-Mar-07 4:25
Memberdaniel04930-Mar-07 4:25 
Generalpoor TV Graphic /picture quality problem Pin
Lalit N Dubey19-Mar-07 22:02
MemberLalit N Dubey19-Mar-07 22:02 
GeneralRe: poor TV Graphic /picture quality problem Pin
daniel04920-Mar-07 16:35
Memberdaniel04920-Mar-07 16:35 
GeneralError openin wfm file Pin
Marco Delgado14-Mar-06 9:29
MemberMarco Delgado14-Mar-06 9:29 
GeneralRe: Error openin wfm file Pin
daniel04915-Mar-06 2:03
Memberdaniel04915-Mar-06 2:03 
GeneralNeed help Pin
maroq20-Mar-07 10:28
Membermaroq20-Mar-07 10:28 
GeneralRe: Need help Pin
daniel04920-Mar-07 16:42
Memberdaniel04920-Mar-07 16:42 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.