Click here to Skip to main content
Click here to Skip to main content

Pure .NET DirectShow Filters in C#

By , 13 Oct 2012
 

Introduction

In this post I describe how to make DirectShow filters in pure C#. I made the BaseClasses library also in pure C# and a few samples to show you how easily it can be used. I think beginner multimedia developers can use my library, but for extending it, you should have knowledge of COM, marshaling, and threading. I suggest you check my previous posts as I will not repeat major things described in there.

Content overview

The source code of filters consist two projects: BaseClasses and ExampleFilters. The BaseClasses library consists of these classes:

  • BaseEnum - base class for enumerations
  • EnumPins - implementation of IEnumPins interface.
  • EnumMediaTypes - implementation of IEnumMediaTypes interface.
  • BasePin - base class for pin.
  • BaseInputPin - base class for input pin.
  • BaseOutputPin - base class for output pin.
  • BaseFilter - base class for filter implementation.
  • TransformInputPin - transform filter input pin class.
  • TransformOutputPin - transform filter output pin class.
  • TransformFilter - transform filter base class.
  • TransInPlaceInputPin - trans-in-place filter input pin class.
  • TransInPlaceOutputPin - trans-in-place filter output pin class.
  • TransInPlaceFilter - trans-in-place filter base class.
  • RenderedInputPin - rendered input pin base class.
  • AMThread - Thread implementation base class.
  • ManagedThread - managed thread implementation of AMThread.
  • SourceStream - base output stream pin class.
  • BaseSourceFilter - base class for source filter implementation.
  • OutputQueue - class implements the queue to deliver media samples.
  • BasePropertyPage - class for implementation filter property page.
  • PosPassThru - class handles seek commands by passing them upstream to next filter.
  • RendererPosPassThru - class handles seek commands for renderer filters.
  • RendererInputPin - class implements input pin for BaseRendererFilter class.
  • MessageDispatcher - class handles unblocking notify from user thread and dispatching windows messages.
  • AsyncStream - System.IO.Stream implementation for IAsyncReader interface.
  • COMStream - System.IO.Stream implementation for IStream interface.
  • PacketData - base class for describing media data for queue.
  • PacketsQueue - queue class for PacketData objects.
  • BitStreamReader - helper class for reading binary data from System.IO.Stream object. It support IStream and IAsyncReader interfaces. Allows reading data by bits, by arrays, or by structures. Class also supports golomb SE and UE values. Reading performed via cache.
  • DemuxTrack - base class for implementation splitter track.
  • FileParser - base class for implementation file parsing support for splitters.
  • SplitterInputPin - class implements input pin for BaseSplitterFilter.
  • SplitterOutputPin - implementation of output pin for BaseSplitterFilter and BaseFileSourceFilter objects.
  • BaseSplitter - class implements core functionality for splitters or file sources implementation.
  • BaseSplitterFilter - base class for implementing splitter filter which has one input pin which supports connection to IAsyncReader, output pins created once it connected. Filter supports seeking.
  • BaseFileSourceFilter - base class for implementing file source filter, it has no input pins, but supports IFileSourceFilter interface, output pins created once file loaded.

Another project in the solution consists of these sample filters:

  • NullInPlaceFilter - in-place transform filter which can be used as base.
  • NullTransformFilter - transform filter which can be used as base.
  • DumpFilter - filter for saving incoming data into file.
  • TextOverFilter - transform filter display overlay text on incoming video.
  • ImageSourceFilter - push source filter which display loaded image file as a video stream.
  • ScreenCaptureFilter - push source filter which capture display and provide it as a video stream.
  • VideoRotationFilter - transform filter rotate video on 90 degree.
  • WavDestFilter - filter for saving incoming PCM data into a WAV file.
  • AudioChannelFilter - transform filter which combine incoming PCM audio data and send it to specified channel.
  • InfTeeFilter - filter delivers incoming samples to any connected output pins.
  • NullRendererFilter - filter implemented as standard "Null Renderer" filter, it inherited from base renderer filter and shows basic methods to override.
  • WAVESplitterFilter - filter implements splitter filter for WAVE files.
  • WAVESourceFilter - filter implements source filter for WAVE files.
  • NetworkSyncFilter and NetworkSource filters is an example how to implements multicast video steam.

Additionaly I include solution with the sample applications which show you how to use my helper classes and embedding filters into applications to use without registration:

  • DxCapture - example shows how to build video capture applications.
  • DxGrabber - an example of usage sample grabber.
  • DxPlayer - basic audio video player application.
  • WavCapture - example demonstrates how to build audio capture applications, sample embed wave out filter.
  • WavExtract - example shows how to extract audio data from media files and save them into WAVE format, sample embed wave out filter.
  • WavPlay - example of usage embeded WAVE source filter to play audio .wav files.

BaseClasses

Base classes also use some stuff in my class library and COM helper objects. Those objects are partially described in my previous posts. For tracing and debugging I suggest to use the TRACE, TRACE_ENTER, and ASSERT functions; and do not use Debug.Write and throwing exceptions - why not is described in the previous article. Plus I suggest reading my description regarding threading in my previous post (just don't want to repeat it here). My implementation has similar methods as Microsoft native, so I'll describe only the differences. OK, if you are following all that aspects let's start reviewing.

Filter registration

The filter registering process is similar to a .NET COM object. The filter DLL should be signed. You can embed the type library as an unmanaged resource in the DLL but that's not mandatory. In sample filters the registration is performed automatically, see the install.bat and uninstall.bat files and the post build events. You can specify the registration in the project settings but that may not work. I made the filter registration very simple. For that there is a class attribute with different constructors:

// Class declaration
[AttributeUsage(AttributeTargets.Class)]
public class AMovieSetup : Attribute 
//.............
// Constructors
public AMovieSetup() 
public AMovieSetup(bool _register) 
public AMovieSetup(string _name) 
public AMovieSetup(Merit _merit) 
public AMovieSetup(Merit _merit, Guid _category) 
public AMovieSetup(string _name, Merit _merit) 
public AMovieSetup(string _name, Merit _merit, Guid _category) 

That attribute should be specified to the class which should be registered as a DirectShow filter. Class should be inherited from any base filter class, such as BaseFilter, TransInPlaceFilter, TransformFilter, or BaseSourceFilter. In attribute you can specify filter name filter merit and filter category. If name not specified then will be used name which is specified in a filter class. Default Merit value is DoNotUse, default registering category is AmLegacyFiltersCategory. Another mandatory attribute of the filter should be the Guid that will be CLSID of the filter. How performed registering and un-registering you can see in following routines of the BaseFilter class

[ComRegisterFunctionAttribute]
public static void RegisterFunction(Type _type) 
 
[ComUnregisterFunctionAttribute] 
public static void UnregisterFunction(Type _type)

Example of filter declaration:

// Here name not specified and will be used name setted in constructor 
// Category will be used by default AmLegacyFilters an merit - do not use 
[ComVisible(true)] 
[Guid("eeb3eef7-0592-491b-b7d4-8c65763c79c6")] // Filter CLSID 
[AMovieSetup(true)] // We should register 
public class NullInPlaceFilter : TransInPlaceFilter 
{ 
    public NullInPlaceFilter() 
    : base("CSharp Null InPlace Filter") {} // this name will be used 
//.............. 
}

Another difference from native BaseClasses is pin access. For used Pins property and initialization is OnInitializePins routine which is abstract in BaseFilter class.

protected abstract int OnInitializePins();

Along with pins initialization you can dynamically manipulation of the pins by next helper routines:

public int AddPin(BasePin _pin) 
public int RemovePin(BasePin _pin) 

How registered filters looks in GraphEdit:

To make your own filter just inherit it from any base filter class specify required attributes and add functionality.

Customizing filters registration

In some cases may require to perform custom registration of the filters along with or without base registration. For this purpose have been added few methods. For example you may use that methods for registering file extensions for your splitter/source filter.

protected virtual int BeforeInstall(ref RegFilter2 _reginfo,ref IFilterMapper2 _mapper2)
{
    return NOERROR;
}

protected virtual int AfterInstall(HRESULT hr,ref RegFilter2 _reginfo, ref IFilterMapper2 _mapper2)
{
    return NOERROR;
}

protected virtual int BeforeUninstall(ref IFilterMapper2 _mapper2)
{
    return NOERROR;
}

protected virtual int AfterUninstall(HRESULT hr, ref IFilterMapper2 _mapper2)
{
    return NOERROR;
}

You can reconfigure _reginfo variable before registering filter and allocate memory for some fields in BeforeInstall method. And in AfterInstall method free that allocated memory. In case if BeforeInstall returns failure - filter does not register and AfterInstall not called. Into AfterInstall passed an HRESULT value of registration, so you can check if filter successfully registered and performs additional registration functionality.

Property Pages

Making filter property pages is also very simple. You should create Window Form and inherit it from BasePropertyPage class instead of Windows.Form. Form you created also require the Guid attribute as this is also COM object. BasePropertyPage class have same methods to override as base class from native BaseClasses. To assign your property page to a filter you should specify an attribute to your filter. This attribute looks:

[ComVisible(true)]
[AttributeUsage(AttributeTargets.Class)]
public class PropPageSetup : Attribute
//........

public PropPageSetup(Guid _guid)
public PropPageSetup(Guid _guid1,Guid _guid2)
public PropPageSetup(Guid _guid1,Guid _guid2,Guid _guid3)
public PropPageSetup(Type _type)
public PropPageSetup(Type _type1, Type _type2)
public PropPageSetup(Type _type1,Type _type2,Type _type3)

Attribute have couple of constructors. Example of specifying property page to a filter:

[ComVisible(true)]
[Guid("701F5A6E-CE48-4dd8-A619-3FEB42E4AC77")] 
[AMovieSetup(true)] 
[PropPageSetup(typeof(AudioChannelForm),typeof(AboutForm))] 
public class AudioChannelFilter : TransformFilter, IAudioChannel 

How property page looks for AudioChannelFilter:

File Splitters and File sources implementation

In this part I briefly overview class library as there are no similar stuff in native BaseClasses, but that stuff will helps you to implement demultiplexors of existing formats or even make your own media file format. The base classes for demultiplexors are BaseSplitterFilter and BaseFileSourceFilter, which to choose depend on functionaly you needed. Mostly you not require to modify that base classes. But for your file format you should create at least 2 classes and inherit them from FileParser and DemuxTrack.

FileParser base class for performing file checking and initializing tracks. In it you should override at least two methods. CheckFile - in here you should validate that you can parse given file or stream. Note this method called for both file or stream implementation in case of usage file source first time will be called with just m_sFileName variable initialized and second time, in case if first time failed it called with m_Stream, which is object of BitStreamReader class. Another method to override is LoadTracks abstact - here you should initialize the tracks (your classes inherited from DemuxTrack) and put them into m_Tracks list. Also in that method you can initialize file duration in nanosecond UNITS (m_rtDuration variable). Parsing works in 2 models: single parsing thread model - there exists one main thread and in there performed demultiplexing, and multithreaded parsing model - here each pin takes care of parsing data. Note: accessing bit stream for reading data is thread safe. To specify which model to use specified boolean parameter in FileParser constructor - bRequireDemuxThread - true means single threading model (default). About that 2 models and how to decide which to you I planing to describe in other article, here just implementation overview.

Single thread model - to use that model you should override another 2 methods in FileParser class. SeekToTime - for support seeking - in that method you should set reading position according specified time. ProcessDemuxPackets - main method for demultiplexing data and put it into track queue. In here you should create PacketData object, fill it with data and put into DemuxTrack by calling AddToCache method. Note: once queue is full this method will block until samples will be delivered in filter. Note: in case critical unblocking to avoid hanging exists Reset method in DemuxTrack class, plus all threads automatically exits due setting quit event in BaseSplitter. But I not suggest you to use any of that manually - as this all handled in classes.

Multithreading model - in that model each track reading and delivering data and the queue may not be used. To implement that model you should override at least 2 methods in your class which inherited from DemuxTrack : GetNextPacket - which returns filled PacketData object or null in case of EOS, and SeekToTime - for same purpose as in single model but here seeking performed on each track directly.

DemuxTrack - base class for each track. You should override it GetMediaType abstract method. Other methods can be overridden according model you choose or specific track implementation.

PacketData - base class for specify media data for the track. It can consist of actual data or pointed to a file position. Anyway you can override this class for your own way providing media data, in that case you should override Dispose method to clear the resources and maybe FillSampleBuffer method in DemuxTrack class to fill media sample buffer from your class.

PacketsQueue - the samples queue class which used in single thread model. Class allows to add and remove PacketData object from queue and signal if queue is full or empty. Queue can sort samples by their timestamps - this used in case of you performing demultiplexing and decoding in your filter. Default cached size is 2 seconds - allocated once pin become active.

BitStreamReader - class for performing reading data from given stream. Helper class allows to thread safty reading data by objects, bits, bytes or golomb values.

In examples there are 2 filters shows you the basics of demultiplexors implementation: WAVESplitterFilter and WAVESourceFilter. But it simplify allows to make your own classes which I planing to more describe in next articles, for example I made Windows Media Splitter which shows in next picture (yes there are 4 streams in single file - was just operating with my own multiplexor - but splitter handle that without problems):

Saving Filter Parameters in Registry

For better configuring filter from previously setted parameters there are exists two helper methods. They  allows write or read string or numeric parameters from system registry. Methods are located in BaseFilter class.

// Retrieve value from registry for current filter
protected object GetFilterRegistryValue(string _name,object _default)

// Set registry value for current filter
protected bool SetFilterRegistryValue(string _name,object _value)

Parameters are stored on filter registration registry subkey so it is personal filter data. Note: all setting are removed during filter unregistering.

Saving Filter Parameters in Graph File

Along with saving parameters into registry, filter allows to save and load it persistent data from saved graphs. Each filter supports IPersistStream interface, and have some helper methods to use it.

// Set or clear flag that properties are modified
protected HRESULT SetDirty(bool bDirty)
// Get's the size of persistent data
protected virtual long SizeMax()
// Write filter properties to the stream
protected virtual HRESULT WriteToStream(Stream _stream)
// Read filter properties from stream
protected virtual HRESULT ReadFromStream(Stream _stream)

To mark that the persistend data is modified you should use SetDirty method. An argument for loading and saving information is .NET type System.IO.Stream. Note: If you not override the SizeMax method then stream writing may be performed two times: first for calculating maximum output size, and second time for actual writing data. In your filter implementation you should override at least WriteToStream and ReadFromStream methods.

Embedding Filters Into Application

You maybe not know that filters may be created inside application and inserted to the filter graph. For that filter isn't registred in registry and only your application can use it. That is also possible with .NET. Make your filter with attribute of [ComVisible(false)] if your filter located in assembly which will be registered as a COM library, in application you may not use that attribute. Also we not require any other registration attributes, so all of them can be removed, even Guid attribute, as registration of the filter will not be called. Keep in mind that saving persistent data will not working in that case, including registry values. Property Pages if they are required should be registered as a COM, but I not sure that property page require for embedded filters as you can configure all settings manually in application.  Example of filter declaration in app:

public class WAVESourceFilter : BaseSourceFilterTemplate<WaveParser>
{
    public WAVESourceFilter()
        : base("CSharp WAVE Source")
    {
    }
}

Once filter class prepared you can create it as particular .NET object. As filter supports IBaseFilter interface you can insert it into Filter Graph and use it without problems.

public class WavPlayback : DSFilePlayback
{
    protected override HRESULT OnInitInterfaces()
    {
        // Create Filter
        DSBaseSourceFilter _source = new DSBaseSourceFilter(new WAVESourceFilter());
        // load the file
        _source.FileName = m_sFileName;
        // Add to the filter Graph
        _source.FilterGraph = m_GraphBuilder;
        // Render the output pin
        return _source.OutputPin.Render();
    }
}

In Sample Applications download there are 3 examples (WavCapture, WavExtract and WavPlay) which shows how to use embedded filters in application.

DirectShowNET Library

BaseClasses does not uses the DirectShowNET library, it consist of couple same interfaces and structures but marshaled differently. That is necessary and very important, because in a lot of cases we need IntPtr instead of actual interface due threading issues which I described in previous article. Accessing to the actual interfaces done via my magic class (also from previous post) VTableInterface. I modify it a little and add more functionality. You also can use DirectShowNET library in your filters but keep in mind ability of ambiguous issue. Instead of DirectShowNET library I put my directshow helper classes for easy way building filter graphs into this article as separate stuff for downloading.

Sample Filters

NullInPlaceFilter

Example in-place transfor filter which doesn't modify data and can be used as start point of development your filters.

NullTransformFilter

Example transform filter which just copy media samples without modifications. This example can be used as start point of developing your own transform filters.

DumpFilter

Example filter which performs writing incoming data into specified file. Filter supports IFileSinkFilter and IAMFilterMiscFlags. Filter accept any incoming types.

TextOverFilter

Example of transform filter which demonstrates how to draw text on the video stream. Accepted Media Type RGB32, filter not performing pitch correction and will be connected to the video renderer via ColorSpace Converter.

VideoRotationFilter

Example of transform filter which performing rotation of the video on 90 degree. Accepted Media Type RGB24, filter not performing pitch correction and will be connected to the video renderer via ColorSpace Converter.

ImageSourceFilter

Example of implementation push source filter which provides loaded image file as a video stream. Filter supports IFileSourceFilter interface. Output Width and Height are set according loaded image resolutions. Default FPS is 20. Output media format is RGB32. Filter not performs pitch correction and will be connected to the video renderer via ColorSpace Converter.

ScreenCaptureFilter

Example of push source filter provide copy of current desktop image via GDI. Output Width and Height set to 640x480 and filter performs resizing to fit that resolution. Default FPS is 20.Output media format RGB32. Filter not performs pitch correction and will be connected to the video renderer via ColorSpace Converter.

WavDestFilter

Example of the filter which writes an audio stream to a WAV file. Filter supports IFileSinkFilter and IAMFilterMiscFlags. Filter accept PCM media type and WaveFormatEx format type.

AudioChannelFilter

Example of transform filter which performs an audio output to specified channel. Filter support PCM input of WAVE_FORMAT_PCM format and BitsPerSample 8 or 16 bits. Output media format is WaveFormatExtensible with one channel output and speaker configuration. Filter supports custom interface by using it you can specify the output channel.

public enum AudioChannel : int 
{ 
    FRONT_LEFT = 0x1, 
    FRONT_RIGHT = 0x2, 
    FRONT_CENTER = 0x4, 
    LOW_FREQUENCY = 0x8, 
    BACK_LEFT = 0x10, 
    BACK_RIGHT = 0x20, 
    SIDE_LEFT = 0x200, 
    SIDE_RIGHT = 0x400, 
} 
 
[ComVisible(true)] 
[System.Security.SuppressUnmanagedCodeSecurity, 
Guid("29D64CCD-D271-4390-8CF2-89D445E7814B"), 
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
public interface IAudioChannel 
{ 
    [PreserveSig] 
    int put_ActiveChannel([In] AudioChannel _channel); 
 
    [PreserveSig] 
    int get_ActiveChannel([Out] out AudioChannel _channel); 
}

InfTeeFilter

Example is similar to Microsoft InfTee sample DirectShow filter.

Null Renderer Filter

Filter inherited from BaseRendererFilter and works same way as standard "Null Renderer" - by discarding every samples it receives without displaying or rendering them.

WAVE Splitter Filter

Splitter filter example which parse WAVE file data and delivery it to downstream filter. Filter have one input pin and support for connection to pin with IAsyncReader interface: such as "File Source Async" filter. Output pin created once input pin is connected. Filter does not registered for usage automatically, so you should build graph manually.

WAVE Source Filter

Example of source filter which parse WAVE file data and delivery it to downstream filter. Filter suppots IFileSourceFilter and have no input pins. Output pin created once input pin is connected. Filter does not registered for usage automatically, so you should build graph manually.

Network Sync and Source Filters

Example of 2 filters: sender and receiver which performs multicast a video data compressed into JPEG. To one Sync filter can be connected few source filters. Sync filter inherited from BaseRendrerFilter and supports RGB24 input. Once graph become active sync filter start multicast incoming samples. Multicast settings can be configured via INetworkConfig interface.

[ComVisible(true)]
[System.Security.SuppressUnmanagedCodeSecurity]
[Guid("96D8A0B7-8EE7-4325-98D4-BB7C66F27B1A")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface INetworkConfig
{
    string IP { get; set; }
    int Port { get; set; }
}

Interface allows to specify multicast IP address and port. In GraphEdit you may use property page for it.

Source filter start waiting for a samples in separate thread once it added into filter graph. MediaType on output pin available only if at least one sample heve beed received. Filter also supports INetworkConfig interface. Note filter may not work on high resolutions due data to send may be large and not supported on system level.

Advanced samples

More sample filters I posting as separate articles as they require to review the code. For now available next samples:

History

  • 13-07-2012 - Initial version.
  • 15-07-2012 - Added property pages, OutputQueue and InfTeeFilter sample.
  • 09-08-2012 - Made some improvements.
  • 14-08-2012 - Implemented BaseRenderer, BaseSplitter and BaseFileSource, added couple of samples.
  • 19-09-2012 - Added application samples.
  • 13-10-2012 - Solved .NET Framework 2.0 Issue with missed methods. Modified class library due some other fixes.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Maxim Kartavenkov
Software Developer (Senior)
Russian Federation Russian Federation
Member
I'm a professional multimedia developer (more than 10 years) in any kind of applications and technologies related to it, such as DirectShow, Direct3D, WinMM, OpenGL, MediaFoundation, WASAPI, Windows Media and other including drivers development of Kernel Streaming, Audio/Video capture drivers and audio effects. Have experience in following languages: C, C++, C#, delphi, C++ builder, VB and VB.NET. Strong knowledge in math and networking.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Questionhow to Grab single frame?membersaharkroglen12 May '13 - 0:52 
Hello Maxim
how can i grab a single frame without any filter currently used (meaning grabbing the original image captured) ?
where should such hooking be placed and how?
 
regards
sahar.
AnswerRe: how to Grab single frame?mvpMaxim Kartavenkov12 May '13 - 1:14 
Hello,
 
You can check DxGrapper application in samples it uses SampleGrabber filter to hook frames with specified format.
You can create your own filter and connect it to the output pin.
You can create your own VMR or EVR allocators and get the surface.
You can use check IVMRWindowlessControl or IVMRWindowlessControl9 or IBasicVideo interfaces depending on your renderer and mode.
 
Maxim.
QuestionTextoverFilter doesn't work on integrated webcam but does work for external USB webcammembersaharkroglen1 May '13 - 8:13 
Hi
i am trying to run a text over filter. was able to make it work with an external USB web cam but got blank preview and no text over while trying to work with the integrated laptop web cam (toggled beween the different sources in the combo box of the DXCapture project).
here is the code.
any advise?
regards
 

protected override HRESULT OnInitInterfaces()
{
HRESULT hr;

// Create Capture Graph Builder
ICaptureGraphBuilder2 _capture = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
// Set Filter Graph
_capture.SetFiltergraph(m_GraphBuilder);
// Insert Capture Device into the Graph
m_pCaptureDevice.FilterGraph = m_GraphBuilder;
IBaseFilter _muxer = null;
IFileSinkFilter _sync = null;
// if we output into a file too
if (!string.IsNullOrEmpty(m_sOutputFileName))
{
// Setup output for an avi file
hr = (HRESULT)_capture.SetOutputFileName(MediaSubType.Avi, m_sOutputFileName, out _muxer, out _sync);
hr.Assert();
if (SUCCEEDED(hr))
{
// Connect capture
hr = (HRESULT)_capture.RenderStream(PinCategory.Capture, MediaType.Video, m_pCaptureDevice.Value, null, _muxer);
hr.Assert();
}
}
 
//// Make preview
hr = (HRESULT)_capture.RenderStream(PinCategory.Preview, MediaType.Video, m_pCaptureDevice.Value, null, null);
Marshal.FinalReleaseComObject(_capture);
 

//----------------
DSFilter textOverlay = new DSFilter((IBaseFilter)new TextOverFilter());
// Add it to filter graph)
textOverlay.FilterGraph = m_GraphBuilder;
// Call base class for render file
hr = base.OnInitInterfaces();
// if succeeded we should check if rotate filter connected
if (hr.Succeeded)
{
if (!textOverlay.InputPin.IsConnected) // rotate filter not connected
{
//// You can connect here manually -
//// probably necessary some colorspace conversion filter
//// Reconnection will be looks next way
///////////////////////////////////////////////////////
//// Start: Manual reconnection code
///////////////////////////////////////////////////////
DSFilter _renderer = VideoRenderer; // get video renderer
if (_renderer != null) // probably we have no video in a file
{
DSPin _output = _renderer.InputPin.ConnectedTo; // get output pin to which renderer input is connected
hr = _output.Disconnect(); // disconnect it
DSFilter _colorspace = null; // we should create colorspace one filter
if (_colorspace != null) // if you have use colorspace
{
hr = _output.Connect(_colorspace.InputPin); // we connect it to output previously disconnected
_output = _colorspace.OutputPin; // and set the new output pin
}
if (SUCCEEDED(hr)) // we can have error in case colorspace can't connect
{
hr = _output.Connect(textOverlay.InputPin); // connect output pin to rotate input
if (SUCCEEDED(hr)) // if ok
{
hr = textOverlay.OutputPin.Connect(_renderer.InputPin); // connect output from rotate to renderer
}
}
}
/////////////////////////////////////////////////////
// End: Manual reconnection code
/////////////////////////////////////////////////////
// We just returns an error - comment next line if you use code above
//hr = VFW_E_CANNOT_CONNECT;
}
}
return hr;
AnswerRe: TextoverFilter doesn't work on integrated webcam but does work for external USB webcammvpMaxim Kartavenkov3 May '13 - 23:08 
One camera supports the colorspace requires for filter another one - not. You are not inspecting the results of an operations that's why you not getting any errors.
 
Maxim.
QuestionSet Camera Properties at RuntimememberMarioWtal8 Apr '13 - 3:40 
Hi,
 
first of all, my English is not as well, so I hope you understand my Question.
Second I like to say: "Greate Solution"
 
I played around with the DxCapture Example and it works greate.
 
I work with a XIMEA - Camera and the Problem that I have, is setting Camera Properties, like "GAIN, EXPOSURE, Video - Size" and so on at Camera - Runtime.
 
But if I try to set those Properties at Camera Runtime, I got the Errormessage that the Filter is in a wrong state.
 
Is it possible and if so how can I set Camera Parameters (If the Cam run in Acquisition Mode)?
 
Kind regards
Mario
Mario Baum

AnswerRe: Set Camera Properties at RuntimemvpMaxim Kartavenkov21 Apr '13 - 22:40 
Hi Mario,
 
Sorry for late responce I was on vacations. Some properties you can't change at runtime that's why you received error message. For "Ximea" cameras I hardcode some properties which are not availble to be changed at runtime (don't know if you know or not but that I made filter for XIMEA cameras). Properties are: XI_PRM_OFFSET_X, XI_PRM_OFFSET_Y, XI_PRM_DOWNSAMPLING_TYPE, XI_PRM_DOWNSAMPLING, XI_PRM_EXPOSURE, XI_PRM_BUFFER_POLICY, XI_PRM_IMAGE_DATA_FORMAT, XI_PRM_WIDTH, XI_PRM_HEIGHT, XI_PRM_FRAMERATE (if they are not modify that in code) those parameters affest a lot of output settings including resolution and they require realocation of output and reconnection of downsampling filters.
 
Regards,
Maxim.
QuestionHow to use in WPFmemberSundaramA7 Apr '13 - 19:54 
Hi Maxim,
 
I want to preview video from Webcam (or) Capture card in wpf application how to use your library?
Please give me some sample code.
AnswerRe: How to use in WPFmvpMaxim Kartavenkov21 Apr '13 - 22:46 
Hi,
 
Right now I have no sample code for WPF but you can check the WPFMediaKit. Maybe later I extend my library with helper classes for WPF.
 
Regards,
Maxim.
QuestionExcellent Work...memberMark H23 Apr '13 - 22:21 
..and article.
 
Enabled me to produce a simple filter to provide peak & vu metering with volume control in a day. When I have time I'll write an article on that and link back here.
 
Thanks Maxim. Thumbs Up | :thumbsup:

If your neighbours don't listen to The Ramones, turn it up real loud so they can.
 
“We didn't have a positive song until we wrote 'Now I Wanna Sniff Some Glue!'” ― Dee Dee Ramone

"The Democrats want my guns and the Republicans want my porno mags and I ain't giving up either" - Joey Ramone

GeneralRe: Excellent Work...mvpMaxim Kartavenkov4 Apr '13 - 0:37 
Welcome.
QuestionPropertydialogs crashmemberNiclas Åström26 Mar '13 - 0:20 
Hi!
 
First of all, thanks for great articles and source code! Thumbs Up | :thumbsup: Thumbs Up | :thumbsup: Thumbs Up | :thumbsup: Thumbs Up | :thumbsup: Thumbs Up | :thumbsup:
 
I'm building a transform filter having a property dialog. Everything works like a charm except one major error:
 
If I use the filter in GraphEditPlus32 and GraphStudioNext the filter will crash after [opening the property dialog and pressing OK] 2-3 times. Using Montivision Workbench as graph editor does not render the error.
 
Debugging my code renders a crash in DSHelper.cs, and the _Release() method.
 
I got the same crash using your original binaries and the CSharp Network Source Filter.
 
I'm running Windows 7 SP1 and .NET Framework 4. The problem can be reproduced on 3 different computers.
 
Any ideas?
AnswerRe: Propertydialogs crashmvpMaxim Kartavenkov26 Mar '13 - 1:51 
Not sure but probably some additional release called and as result the object already released then _Release called. If you research more and provide more details I can check and solve that if it my issue.I didn't got such behaviour, you should try with different applications and with different filters in graph.Plus description see how it reproduced.
 
Maxim.
QuestionColor Space Convertermembersitussoft25 Mar '13 - 0:09 
Maxim,
 
I'd like to congratulate you one an excellent series of articles an work.
 
I do have a question though.
 
Do you understand why the filter graph manager adds a color space converter between these filters?
 
For example, I specify the "CSharp Screen Capture Filter" and render the output pin. The resulting graph has the Capture filter, a color space converter and the renderer, yet the media types and allocators of the pins on the capture and other filters all appear to be identical.
 
Thanks
 
Chris.
AnswerRe: Color Space ConvertermvpMaxim Kartavenkov25 Mar '13 - 0:33 
Hi, Chris
 
Sure I know why the Color Space converter can be inserted.
Main reason: The filter have output format which is not compatible with renderer and changing it not allowed by the filter.
Example 1: your filter have output RGB24 or ARGB32 you want to connect to the renderer directly, in that case renderer check the formats output from your filter and it see the RGB24, but RGB24 isn't good for renderer and it try to query for accepting RGB32 if that query is passed then renderer connect and after starts it query change type of your filter, if your filter not accept sucha change during runtime the filter graph stops with error, if you not handle that change in runtime you may see the striped output video or something like that. And in case if you not accept the format changes during connection then the ColorSpace filter will be inserted.
Example 2: You have RGB32 output from your filter but it still inserted the ColorSpace Converter oce you try to connect to the renderer. This bcs the resolution is not good for the rendrer. So renderer also try to query format with new resolution, but with specifing target rectangle same as your output, that is require to enlarge the buffer according GPU acceptable render target, prefered resolutions you can find in DirectX Caps Viewer tool.
 
Actually that is described in one of my article, probably in article abt Virtual Video Capture Device.
 
Regards,
Maxim.
QuestionSave property page settingsmemberdadluk0318 Mar '13 - 1:50 
Hi,
 
currently it seems that the filters built with BaseClasses doesn't have support for saving its properties when saving a graph. I need two have two different .grf files containg the same filters but with different properties.
 
Do you know if this is possible to do using your code?
 
Cheers
/Dave
AnswerRe: Save property page settingsmvpMaxim Kartavenkov20 Mar '13 - 0:12 
My classes already have embedded ability for that.
You should read article proper - there is even topic for that.
 
Maxim.
GeneralRe: Save property page settingsmemberdadluk0321 Mar '13 - 22:57 
Ok, thanks.
 
I tried to add WriteToStream and ReadFromStream to the Null Transform Filter in the Examplefilter project. I added the code just beneath #region Overridden Methods, when I save the graph the messagebox "SaveToSteam" is shown but when I load the saved graph I can't get the "ReadFromStream" messagebox to show, any idea what I'm doing wrong? My code is posted below:
 
protected override HRESULT WriteToStream(Stream _stream)
       {
           MessageBox.Show("SaveToStream");
 
           return NOERROR;
       }
 
       protected override HRESULT ReadFromStream(Stream _stream)
       {
           MessageBox.Show("ReadFromStream");
 
           return NOERROR;
       }

AnswerRe: Save property page settingsmvpMaxim Kartavenkov21 Mar '13 - 23:12 
Sure it not will be called bcs you have not saved anything - what you are want to load in that case?
GeneralRe: Save property page settingsmvpMaxim Kartavenkov22 Mar '13 - 0:26 
Also keep in mind that Save called 2 times:
1st to determine the size of required for data to be saved and 2nd is for an actual data saving.
 
Maxim.
Questionwhile (true) MyVote++;memberflash-mmb12 Mar '13 - 23:28 
Hi Maxim , excelent article

Is WavExtract only supports 16-bit audio files.
Please tell me How can I get samples data of 32 bits audio files?

Thanks
AnswerRe: while (true) MyVote++;mvpMaxim Kartavenkov12 Mar '13 - 23:43 
WavExtract does not check for 16 bit 24 bit or 32 bit audio. To check your type see CheckMediaType method of writer filter.
 
Maxim.
GeneralRe: while (true) MyVote++; [modified]memberflash-mmb13 Mar '13 - 1:33 
I tried WavExtract with several files (with different file formats and bit types , Like avi , mpg , wav , mp3 - 16 & 32 bits) , but that did not work Without any exception Occur , but the output wave file is corrupted.
in output wave file header saved correctly but chunk data is not correct.
 
Why for all 32 bits audio files _writer.InputPin.IsConnected is false??
please help me
 
thanks

modified 13 Mar '13 - 8:21.

GeneralRe: while (true) MyVote++;mvpMaxim Kartavenkov13 Mar '13 - 2:30 
Does it not play in winamp or wavplay example?
GeneralRe: while (true) MyVote++;memberflash-mmb13 Mar '13 - 2:45 
No it doesn't . I tried with winamp , kmplayer ,windows media player and Audacity.
GeneralRe: while (true) MyVote++;mvpMaxim Kartavenkov13 Mar '13 - 2:52 
You probably have any bug filter which performs output data with PCM subtype but no PCM stream which cause of writing wrong data into a file.

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

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 13 Oct 2012
Article Copyright 2012 by Maxim Kartavenkov
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid