Last updated: January 2026
DirectShow.NET Alternative: Migration Guide to VisioForge .Net SDK
Step-by-step guide to migrate from DirectShow.NET (abandoned) to VisioForge .NET SDK for video capture, playback, and processing on .NET 6-10.
C# developers migrating from DirectShow.NET (directshowlib) to a modern .NET 6-10 video capture, playback, and processing SDK
Why Replace DirectShow.NET?
DirectShow.NET has been abandoned since February 2010 — 15+ years without updates. It provides raw COM interface definitions for Microsoft's DirectShow API, which Microsoft itself has deprecated in favor of Media Foundation.
| Risk | Impact |
|---|---|
| DirectShow deprecated by Microsoft | No new features, codecs, or platform support |
| Library unmaintained | .NET Framework 2.0, no .NET 6+ support |
| COM complexity | Hundreds of lines for basic tasks, manual memory management |
| Codec hunting | Must find, install, and register third-party DirectShow filters |
| Filter graph debugging | Opaque pipeline failures, no diagnostic tools |
| Windows-only | COM/DirectShow cannot run on macOS, Linux, or mobile |
| No modern codecs | No native H.265, AV1, VP9 without third-party filters |
| Registry issues | Filter registration problems on modern Windows |
DirectShow Concepts Explained
Understanding how DirectShow architecture maps to VisioForge SDKs helps you plan your migration. The table below shows how each core DirectShow concept translates to the modern .NET equivalent.
DirectShow Architecture to VisioForge Equivalents
| DirectShow Concept | VisioForge Equivalent |
|---|---|
| Filter Graph (IGraphBuilder) | Pipeline — managed automatically by SDK, or explicit MediaBlocksPipeline |
| Source Filter (device/file) | Source settings: VideoCaptureDeviceSourceSettings, RTSPSourceSettings, etc. |
| Transform Filter (effects/encoder) | Built-in video/audio effects + encoder classes (H264EncoderSettings, etc.) |
| Renderer Filter (video window) | VideoView control (WinForms, WPF, MAUI, Avalonia) |
| Mux Filter (AVI/MP4 mux) | Output format classes: MP4Output, AVIOutput, MKVOutput, WebMOutput |
| Pin connections | Automatic — or explicit Block.Connect() in Media Blocks SDK |
| Media Types (AM_MEDIA_TYPE) | Handled automatically — no manual format negotiation |
| Filter Categories (device enumeration) | DeviceEnumerator.Shared.VideoSourcesAsync() / AudioSourcesAsync() |
| DirectShow filter registration (regsvr32) | NuGet packages — no system registration needed |
| GraphEdit debugging tool | Pipeline events, logging, typed exceptions |
Which VisioForge SDK Replaces What?
DirectShow.NET Usage to VisioForge Replacement
| DirectShow.NET Usage | VisioForge Replacement |
|---|---|
| C# webcam capture via filter graph | Video Capture SDK .Net — `VideoCaptureCoreX` |
| C# IP camera capture (RTSP/MJPEG) | Video Capture SDK .Net — `RTSPSourceSettings` |
| C# screen capture and recording | Video Capture SDK .Net — `ScreenCaptureSourceSettings` |
| File playback via `IGraphBuilder` | Media Player SDK .Net — `MediaPlayerCoreX` |
| DVD playback via `IDvdControl2` | Media Player SDK .Net — DVD navigation API |
| TV tuner via `IAMTVTuner` | Video Capture SDK .Net — `VideoCaptureCore` |
| File transcoding | Video Edit SDK .Net — `VideoEditCoreX` |
| Custom filter graphs | Media Blocks SDK .Net — modular pipeline (400+ blocks) |
| `ISampleGrabber` frame access | `OnVideoFrameBuffer` event on any SDK |
C# DirectShow Interface Mapping
C# DirectShow Interface Mapping
| DirectShow.NET Interface | VisioForge Equivalent |
|---|---|
| `IGraphBuilder` | Pipeline built automatically by SDK |
| `ICaptureGraphBuilder2` | `VideoCaptureCoreX` constructor |
| `IMediaControl` (Run/Stop/Pause) | `StartAsync()` / `StopAsync()` / `PauseAsync()` |
| `IMediaEvent` | SDK events (`OnError`, `OnStop`, etc.) |
| `IVideoWindow` | `VideoView` control (WinForms/WPF/MAUI/Avalonia) |
| `ISampleGrabber` | `OnVideoFrameBuffer` event |
| `IBaseFilter` | Not needed — SDK manages filters internally |
| `IPin` / pin connections | Not needed — SDK connects pipeline automatically |
| `DsDevice.GetDevicesOfCat()` | `DeviceEnumerator.Shared.VideoSourcesAsync()` |
| `FilterCategory.VideoInputDevice` | `DeviceEnumerator.Shared.VideoSourcesAsync()` |
| `FilterCategory.AudioInputDevice` | `DeviceEnumerator.Shared.AudioSourcesAsync()` |
| `IAMTVTuner` | `VideoCaptureCore.TVTuner` property |
| `IDvdControl2` | `MediaPlayerCore.DVD_*` methods |
| `Marshal.ReleaseComObject()` | `await sdk.DisposeAsync()` |
C# Webcam Capture with Preview
DirectShow.NET — webcam capture (before)
C#// 80+ lines of COM interop
var graphBuilder = (IGraphBuilder)new FilterGraph();
var captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
int hr = captureGraph.SetFiltergraph(graphBuilder);
DsError.ThrowExceptionForHR(hr);
// Find video device
var devices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
IBaseFilter sourceFilter;
hr = graphBuilder.AddSourceFilterForMoniker(
devices[0].Mon, null, devices[0].Name, out sourceFilter);
DsError.ThrowExceptionForHR(hr);
// Render preview
hr = captureGraph.RenderStream(
PinCategory.Preview, MediaType.Video, sourceFilter, null, null);
DsError.ThrowExceptionForHR(hr);
// Set video window
var videoWindow = (IVideoWindow)graphBuilder;
videoWindow.put_Owner(panelHandle);
videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings);
videoWindow.SetWindowPosition(0, 0, panel.Width, panel.Height);
// Start
var mediaControl = (IMediaControl)graphBuilder;
hr = mediaControl.Run();
DsError.ThrowExceptionForHR(hr);
// Cleanup (must release EVERY COM object)
Marshal.ReleaseComObject(sourceFilter);
Marshal.ReleaseComObject(captureGraph);
Marshal.ReleaseComObject(graphBuilder);VisioForge — C# webcam capture (after)
C#var capture = new VideoCaptureCoreX(videoView);
var devices = await DeviceEnumerator.Shared.VideoSourcesAsync();
capture.Video_Source = new VideoCaptureDeviceSourceSettings(devices[0]);
await capture.StartAsync();
// Cleanup
await capture.StopAsync();
await capture.DisposeAsync();C# Webcam Recording to MP4
DirectShow.NET — webcam to MP4 (before)
C#// Must find H.264 encoder filter, MP4 mux filter, file writer
// Each requires separate COM object management
var graphBuilder = (IGraphBuilder)new FilterGraph();
var captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
captureGraph.SetFiltergraph(graphBuilder);
// Add source
var devices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
IBaseFilter sourceFilter;
graphBuilder.AddSourceFilterForMoniker(
devices[0].Mon, null, devices[0].Name, out sourceFilter);
// Find and add H.264 encoder (must be installed on system!)
// This varies by system — no guarantee the filter exists
Guid h264Clsid = new Guid("some-encoder-guid");
IBaseFilter encoder = (IBaseFilter)Activator.CreateInstance(
Type.GetTypeFromCLSID(h264Clsid));
graphBuilder.AddFilter(encoder, "H.264 Encoder");
// Find and add MP4 mux
// Find and add file writer
// Connect source → encoder → mux → writer pins manually
// Each pin connection can fail silently or throw cryptic COM errors
// Configure encoder properties via ICodecAPI or IPropertyBag
// Different for every encoder filter...
var mediaControl = (IMediaControl)graphBuilder;
mediaControl.Run();
// Cleanup: release 5+ COM objectsVisioForge — C# webcam recording to MP4 (after)
C#var capture = new VideoCaptureCoreX(videoView);
var devices = await DeviceEnumerator.Shared.VideoSourcesAsync();
capture.Video_Source = new VideoCaptureDeviceSourceSettings(devices[0]);
capture.Outputs_Add(new MP4Output("recording.mp4"), true);
await capture.StartAsync();C# Video File Playback
DirectShow.NET — video playback (before)
C#var graphBuilder = (IGraphBuilder)new FilterGraph();
int hr = graphBuilder.RenderFile("video.mp4", null);
DsError.ThrowExceptionForHR(hr);
var videoWindow = (IVideoWindow)graphBuilder;
videoWindow.put_Owner(panelHandle);
videoWindow.put_WindowStyle(WindowStyle.Child);
videoWindow.SetWindowPosition(0, 0, panel.Width, panel.Height);
var mediaControl = (IMediaControl)graphBuilder;
mediaControl.Run();
// Seeking
var mediaSeeking = (IMediaSeeking)graphBuilder;
long position = 50000000; // 5 seconds in 100ns units
mediaSeeking.SetPositions(
ref position, AMSeekingSeekingFlags.AbsolutePositioning,
null, AMSeekingSeekingFlags.NoPositioning);VisioForge — C# video player (after)
C#var player = new MediaPlayerCoreX(videoView);
await player.OpenAsync(new Uri("video.mp4"));
await player.PlayAsync();
// Seeking
await player.SeekAsync(TimeSpan.FromSeconds(5));C# Video Frame Grabbing
DirectShow.NET — ISampleGrabber frame capture (before)
C#// Must insert ISampleGrabber into filter graph
var sampleGrabber = (ISampleGrabber)new SampleGrabber();
var mediaType = new AMMediaType();
mediaType.majorType = MediaType.Video;
mediaType.subType = MediaSubType.RGB24;
sampleGrabber.SetMediaType(mediaType);
graphBuilder.AddFilter((IBaseFilter)sampleGrabber, "Grabber");
// Connect pins...
sampleGrabber.SetBufferSamples(true);
// In callback: manually read buffer, create Bitmap from raw bytes
sampleGrabber.GetCurrentBuffer(ref bufferSize, buffer);
// Manual pixel format conversion, stride calculation, etc.VisioForge — C# video frame capture (after)
C#capture.OnVideoFrameBuffer += (s, e) =>
{
// Frame data available as managed buffer
// Or convert to SKBitmap/Bitmap directly
var bitmap = e.Frame.ToBitmap();
ProcessFrame(bitmap);
};C# IP Camera (RTSP) Capture
DirectShow.NET — RTSP capture (before)
C#// Must find and install RTSP source filter (e.g., LAV, ffdshow)
// No standard DirectShow RTSP filter ships with Windows
var graphBuilder = (IGraphBuilder)new FilterGraph();
// Add RTSP source filter (if installed)
Guid rtspFilterClsid = new Guid("some-rtsp-filter-guid");
IBaseFilter rtspSource = (IBaseFilter)Activator.CreateInstance(
Type.GetTypeFromCLSID(rtspFilterClsid));
graphBuilder.AddFilter(rtspSource, "RTSP Source");
// Configure URL via IFileSourceFilter or custom interface
var fileSource = (IFileSourceFilter)rtspSource;
fileSource.Load("rtsp://camera-ip:554/stream", null);
// Must manually connect pins to decoder, renderer
// No reconnection logic — if stream drops, graph stops
// No authentication helpers
// No ONVIF supportVisioForge — RTSP capture (after)
C#var capture = new VideoCaptureCoreX(videoView);
capture.Video_Source = new RTSPSourceSettings(
new Uri("rtsp://camera-ip:554/stream"))
{
Login = "admin",
Password = "password",
ReconnectOnDrop = true
};
capture.Outputs_Add(new MP4Output("recording.mp4"), true);
await capture.StartAsync();C# Screen Capture and Recording
DirectShow.NET — screen capture (before)
C#// DirectShow has no built-in screen capture filter
// Must use third-party filter or custom push source
// Common approach: manually capture GDI/BitBlt in a thread,
// feed frames through a custom IBaseFilter implementation
// 200+ lines of custom filter code:
// - Implement IBaseFilter, IPin, IMediaSample
// - Manual frame rate timing with Thread.Sleep
// - Manual pixel format conversion
// - No GPU acceleration
// - No mouse cursor rendering
// - No multi-monitor supportVisioForge — screen capture (after)
C#var capture = new VideoCaptureCoreX(videoView);
capture.Video_Source = new ScreenCaptureSourceSettings()
{
FrameRate = new VideoFrameRate(30),
Rectangle = new Rect(0, 0, 1920, 1080),
CaptureCursor = true
};
capture.Outputs_Add(new MP4Output("screen.mp4"), true);
await capture.StartAsync();C# Audio Recording from Microphone
DirectShow.NET — audio capture (before)
C#var graphBuilder = (IGraphBuilder)new FilterGraph();
var captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
captureGraph.SetFiltergraph(graphBuilder);
// Find audio device
var audioDevices = DsDevice.GetDevicesOfCat(
FilterCategory.AudioInputDevice);
IBaseFilter audioSource;
graphBuilder.AddSourceFilterForMoniker(
audioDevices[0].Mon, null, audioDevices[0].Name,
out audioSource);
// Must find WAV/MP3 encoder filter
// Must find file writer filter
// Must connect pins manually
// Configure sample rate/channels via IAMStreamConfig
var mediaControl = (IMediaControl)graphBuilder;
mediaControl.Run();
// Manual COM cleanup for all objectsVisioForge — audio capture (after)
C#var capture = new VideoCaptureCoreX();
var audioDevices = await DeviceEnumerator.Shared
.AudioSourcesAsync();
capture.Audio_Source = new AudioCaptureDeviceSourceSettings(
audioDevices[0]);
capture.Audio_Record = true;
capture.Video_Record = false;
capture.Outputs_Add(new MP4Output("audio.mp4"), true);
await capture.StartAsync();C# Custom Processing Pipeline
DirectShow.NET — custom filter graph (before)
C#// Building a custom graph: source > resize > overlay > encode > mux > write
// Each step requires finding/creating a filter, adding to graph,
// connecting pins with compatible media types
var graphBuilder = (IGraphBuilder)new FilterGraph();
// Add source filter...
// Add resize filter (must find one that's installed)...
// Add overlay filter (must write custom or find one)...
// Add H.264 encoder (system-dependent)...
// Add MP4 mux (system-dependent)...
// Add file writer...
// Connect each pair of pins manually...
// Handle format negotiation failures...
// Total: 150-300 lines, fragile, system-dependentVisioForge Media Blocks — custom pipeline (after)
C#var pipeline = new MediaBlocksPipeline();
var source = new SystemVideoSourceBlock(
new VideoCaptureDeviceSourceSettings(device));
var resize = new ResizeBlock(1920, 1080);
var overlay = new TextOverlayBlock("Recording...");
var encoder = new H264EncoderBlock();
var sink = new MP4SinkBlock("output.mp4");
pipeline.Connect(source.Output, resize.Input);
pipeline.Connect(resize.Output, overlay.Input);
pipeline.Connect(overlay.Output, encoder.Input);
pipeline.Connect(encoder.Output, sink.Input);
await pipeline.StartAsync();Migration Checklist
- Audit DirectShow.NET usage — Find all `using DirectShowLib` references
- Identify filter graph purpose — Capture, playback, transcoding, or custom processing
- Choose VisioForge SDK — Video Capture, Media Player, Video Edit, or Media Blocks
- Install NuGet packages — Replace DirectShowLib NuGet with VisioForge packages
- Replace filter graph code
- Remove COM cleanup code — VisioForge uses `IAsyncDisposable`
- Remove third-party DirectShow filter dependencies — VisioForge includes codecs
- Target modern .NET — .NET 6-10
- Test cross-platform
- Remove DirectShow filter registration — No longer needed
What You Gain After Migration
| Aspect | DirectShow.NET | After Migration |
|---|---|---|
| Lines of code | 100+ per feature | 5-10 per feature |
| Framework | .NET Framework 2.0 | .NET 6-10 |
| Platforms | Windows only | Windows, macOS, Linux, iOS, Android |
| API style | Raw COM, manual pin connections | Typed async C# API |
| Codecs | Must find and install DirectShow filters | Built-in (H.264, H.265, AV1, VP9) |
| Memory management | Manual `Marshal.ReleaseComObject` | `IAsyncDisposable` |
| Debugging | Opaque COM errors (HRESULT) | Typed exceptions, events |
| Video effects | Must find effect filters | 40+ built-in (GPU + CPU) |
| Audio effects | None | 40+ (EQ, reverb, chorus, 3D) |
| Streaming | Not available | RTMP, HLS, SRT, NDI |
| Detection | Not available | Motion (MOG2), face (Haar/DNN/DLib), pedestrian (HOG+SVM), barcode |
| Hardware encoding | Must find encoder filters | NVENC, QSV, AMF, VideoToolbox |
| IP cameras | Manual filter graph | RTSP, RTMP, HLS, ONVIF with auto-reconnection |
| Maintenance | Abandoned (2010) | Active development |
Frequently Asked Questions
Is DirectShow.NET still maintained?
What is the best DirectShow.NET alternative for C# video capture?
Can VisioForge replace custom DirectShow filter graphs?
Does VisioForge support .NET 6, .NET 8, .NET 9, and .NET 10?
Do I still need DirectShow filters installed on the system?
Can I migrate from DirectShow.NET incrementally?
Start Your Migration
Installation guide
Setup for Visual Studio, Rider, and VS for Mac
Video Capture SDK
Replaces DirectShow capture filter graphs
Media Player SDK
Replaces DirectShow playback and DVD graphs
Media Blocks SDK
Replaces custom filter graphs with 400+ typed blocks
Documentation
API reference, tutorials, and deployment guides
Browse code samples
Working C# examples
