Processing Filters Pack - Code Examples¶
Overview¶
This page provides practical code examples for using the Processing Filters Pack, which includes:
- Video Effects - 35+ real-time effects (text, graphics, color adjustments, denoise)
- Video Mixer - 2-16 source mixing with PIP, alpha blending, chroma key
- Chroma Key - Green/blue screen compositing
Prerequisites¶
C++ Projects¶
#include <dshow.h>
#include <streams.h>
#include "IVFEffects45.h"
#include "IVFVideoMixer.h"
#include "IVFChromaKey.h"
#pragma comment(lib, "strmiids.lib")
C# Projects¶
using VisioForge.DirectShowAPI;
using VisioForge.DirectShowLib;
using System.Runtime.InteropServices;
using System.Drawing;
Video Effects Examples¶
Example 1: Basic Video Effect¶
Apply a single video effect to a source.
C# Implementation¶
using System;
using System.Runtime.InteropServices;
using VisioForge.DirectShowAPI;
using VisioForge.DirectShowLib;
public class VideoEffectsBasicExample
{
private IFilterGraph2 filterGraph;
private IMediaControl mediaControl;
private IBaseFilter sourceFilter;
private IBaseFilter effectFilter;
public void PlayWithEffect(string filename, IntPtr videoWindowHandle)
{
filterGraph = (IFilterGraph2)new FilterGraph();
mediaControl = (IMediaControl)filterGraph;
// Add source filter (e.g., File Source)
filterGraph.AddSourceFilter(filename, "Source", out sourceFilter);
// Add Video Effects filter
effectFilter = FilterGraphTools.AddFilterFromClsid(
filterGraph,
Consts.CLSID_VFVideoEffects,
"Video Effects");
// Configure effect using IVFEffects45 interface
var effects = effectFilter as IVFEffects45;
if (effects != null)
{
// Enable Greyscale effect via VideoEffectSimple struct
var eff = new VideoEffectSimple
{
Type = (int)VideoEffectType.Greyscale,
Enabled = true
};
effects.add_effect(eff);
}
captureGraph.SetFiltergraph(filterGraph);
// Render through effect filter
captureGraph.RenderStream(null, MediaType.Video, sourceFilter, effectFilter, null);
captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, null, null);
// Set up video window
var videoWindow = (IVideoWindow)filterGraph;
videoWindow.put_Owner(videoWindowHandle);
videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings);
// Run
mediaControl.Run();
Marshal.ReleaseComObject(captureGraph);
}
public void Stop()
{
mediaControl?.Stop();
FilterGraphTools.RemoveAllFilters(filterGraph);
if (sourceFilter != null) Marshal.ReleaseComObject(sourceFilter);
if (effectFilter != null) Marshal.ReleaseComObject(effectFilter);
if (mediaControl != null) Marshal.ReleaseComObject(mediaControl);
if (filterGraph != null) Marshal.ReleaseComObject(filterGraph);
}
}
C++ Implementation¶
HRESULT ApplyVideoEffect(LPCWSTR filename)
{
IGraphBuilder* pGraph = NULL;
IBaseFilter* pSource = NULL;
IBaseFilter* pEffect = NULL;
IVFEffects45* pEffects = NULL;
// Create filter graph
HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void**)&pGraph);
if (FAILED(hr)) return hr;
// Add source
hr = pGraph->AddSourceFilter(filename, L"Source", &pSource);
if (FAILED(hr)) goto cleanup;
// Create Video Effects filter
hr = CoCreateInstance(CLSID_VFVideoEffects, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (void**)&pEffect);
if (FAILED(hr)) goto cleanup;
hr = pGraph->AddFilter(pEffect, L"Video Effects");
if (FAILED(hr)) goto cleanup;
// Configure effect
hr = pEffect->QueryInterface(IID_IVFEffects45, (void**)&pEffects);
if (SUCCEEDED(hr))
{
// Enable greyscale via VideoEffectSimple struct
VideoEffectSimple effect;
ZeroMemory(&effect, sizeof(effect));
effect.Type = ef_greyscale;
effect.Enabled = TRUE;
pEffects->add_effect(&effect);
pEffects->Release();
}
// Connect filters and render...
// (Use RenderStream or ConnectFilters)
cleanup:
if (pEffect) pEffect->Release();
if (pSource) pSource->Release();
if (pGraph) pGraph->Release();
return hr;
}
Example 2: Multiple Effects Chain¶
Apply multiple effects simultaneously.
C# Multiple Effects¶
public class MultipleEffectsExample
{
public void ApplyMultipleEffects(IBaseFilter effectFilter)
{
var effects = effectFilter as IVFEffects45;
if (effects != null)
{
// Add darkness/brightness effect (VideoEffectType.Darkness, AmountI controls level)
effects.add_effect(new VideoEffectSimple
{
Type = (int)VideoEffectType.Darkness,
Enabled = true,
AmountI = 50 // 0 = darkest, 100 = brightest
});
// Add contrast effect (AmountI controls intensity)
effects.add_effect(new VideoEffectSimple
{
Type = (int)VideoEffectType.Contrast,
Enabled = true,
AmountI = 75 // Contrast intensity
});
// Add saturation effect (AmountI controls saturation level)
effects.add_effect(new VideoEffectSimple
{
Type = (int)VideoEffectType.Saturation,
Enabled = true,
AmountI = 120 // Saturation level
});
}
}
}
¶
public class MultipleEffectsExample
{
public void ApplyMultipleEffects(IBaseFilter effectFilter)
{
var effects = effectFilter as IVFEffects45;
if (effects != null)
{
// Add darkness/brightness effect (VideoEffectType.Darkness, AmountI controls level)
effects.add_effect(new VideoEffectSimple
{
Type = (int)VideoEffectType.Darkness,
Enabled = true,
AmountI = 50 // 0 = darkest, 100 = brightest
});
// Add contrast effect (AmountI controls intensity)
effects.add_effect(new VideoEffectSimple
{
Type = (int)VideoEffectType.Contrast,
Enabled = true,
AmountI = 75 // Contrast intensity
});
// Add saturation effect (AmountI controls saturation level)
effects.add_effect(new VideoEffectSimple
{
Type = (int)VideoEffectType.Saturation,
Enabled = true,
AmountI = 120 // Saturation level
});
}
}
}
Example 3: Text Overlay¶
Add text logo overlay to video.
C# Text Overlay¶
public void ApplyTextOverlay(IBaseFilter effectFilter)
{
var effects = effectFilter as IVFEffects45;
if (effects != null)
{
var eff = new VideoEffectSimple
{
Type = (int)VideoEffectType.TextLogo,
Enabled = true,
TextLogo = new MFPTextLogo
{
X = 50,
Y = 50,
Text = "My Video Title",
FontName = "Arial",
FontSize = 36,
FontColor = 0xFFFFFF, // White
FontBold = true,
TransparentBg = true,
Transp = 255, // Fully opaque
BorderMode = 4, // bm_outline
OuterBorderColor = 0x000000, // Black outline
OuterBorderSize = 2
}
};
effects.add_effect(eff);
}
}
See effects-reference.md for the full MFPTextLogo structure (text alignment, gradient, date/time display, anti-aliasing, etc.).
Example 4: Image Overlay¶
Add graphic watermark or logo.
C# Image Overlay¶
public void ApplyImageOverlay(IBaseFilter effectFilter, string imagePath)
{
var effects = effectFilter as IVFEffects45;
if (effects != null)
{
var eff = new VideoEffectSimple
{
Type = (int)VideoEffectType.ImageLogo,
Enabled = true,
GraphicalLogo = new MFPGraphicalLogo
{
X = 10, // X position in pixels
Y = 10, // Y position in pixels
Filename = imagePath,
TranspLevel = 200, // Semi-transparent (0-255)
StretchMode = 2 // 0=None, 1=Stretch, 2=Proportional fit
}
};
effects.add_effect(eff);
}
}
See effects-reference.md for the full MFPGraphicalLogo structure.¶
Example 5: Denoise Filters¶
Apply noise reduction for cleaner video.
C# Denoise Examples¶
public void ApplyDenoise(IBaseFilter effectFilter, VideoEffectType denoiseType)
{
var effects = effectFilter as IVFEffects45;
if (effects != null)
{
var eff = new VideoEffectSimple
{
Type = (int)denoiseType,
Enabled = true
};
switch (denoiseType)
{
case VideoEffectType.DenoiseCAST:
// CAST denoise — configure via DenoiseCAST sub-struct
eff.DenoiseCAST = new MFPDenoiseCAST
{
TemporalDifferenceThreshold = 16,
StrongEdgeThreshold = 8
};
break;
case VideoEffectType.DenoiseAdaptive:
// Adaptive denoise — threshold controls sensitivity
eff.DenoiseAdaptiveThreshold = 20; // 0-255
eff.DenoiseAdaptiveBlurMode = 0; // 0-3
break;
case VideoEffectType.DenoiseMosquito:
// Mosquito denoise — AmountI controls reduction strength
eff.AmountI = 30;
break;
}
effects.add_effect(eff);
}
}
Example 6: All Available Effects¶
Complete list of effects with basic configuration.
C# All Effects Reference¶
public class AllEffectsExample
{
public void DemonstrateAllEffects(IBaseFilter effectFilter)
{
var effects = effectFilter as IVFEffects45;
if (effects == null) return;
// Color Filters
effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Greyscale, Enabled = true });
effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Invert, Enabled = true });
effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.FilterRed, Enabled = true });
effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.FilterGreen, Enabled = true });
effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.FilterBlue, Enabled = true });
// Image Adjustment (AmountI controls intensity)
effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Darkness, Enabled = true, AmountI = 50 });
effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Contrast, Enabled = true, AmountI = 75 });
effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Saturation, Enabled = true, AmountI = 120 });
effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Lightness, Enabled = true, AmountI = 45 });
// Spatial Transforms
effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.FlipRight, Enabled = true });
effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.FlipDown, Enabled = true });
effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.MirrorHorizontal, Enabled = true });
effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Rotate, Enabled = true, AmountI = 90 });
// Artistic Effects
effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Blur, Enabled = true, AmountI = 5 });
effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Sharpen, Enabled = true, AmountI = 2 });
effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Posterize, Enabled = true, AmountI = 8 });
effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Solorize, Enabled = true, AmountI = 128 });
effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Mosaic, Enabled = true, SizeI = 10 });
// Noise Reduction
effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.DenoiseCAST, Enabled = true });
effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.DenoiseAdaptive, Enabled = true, DenoiseAdaptiveThreshold = 20 });
effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.DenoiseMosquito, Enabled = true, AmountI = 30 });
// Deinterlacing
effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.DeinterlaceBlend, Enabled = true });
effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.DeinterlaceTriangle, Enabled = true });
effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.DeinterlaceCAVT, Enabled = true });
// Overlays (TextLogo/ImageLogo need sub-struct — see Examples 3 & 4)
// To disable/remove an effect:
// effects.remove_effect(effectId);
// effects.clear_effects();
}
}
Note: For the full list of
VideoEffectTypemembers and sub-struct parameters, see effects-reference.md.
Video Mixer Examples¶
Example 7: Picture-in-Picture (PIP)¶
Mix two video sources with PIP layout.
C# Picture-in-Picture¶
public class VideoMixerPIPExample
{
private IFilterGraph2 filterGraph;
private IBaseFilter mixerFilter;
public void CreatePIP(string mainVideoPath, string pipVideoPath, IntPtr videoWindowHandle)
{
filterGraph = (IFilterGraph2)new FilterGraph();
// Add main video source
filterGraph.AddSourceFilter(mainVideoPath, "Main Source", out IBaseFilter mainSource);
// Add PIP video source
filterGraph.AddSourceFilter(pipVideoPath, "PIP Source", out IBaseFilter pipSource);
// Add Video Mixer filter
mixerFilter = FilterGraphTools.AddFilterFromClsid(
filterGraph,
Consts.CLSID_VFVideoMixer,
"Video Mixer");
// Configure mixer — real IVFVideoMixer interface
var mixer = mixerFilter as IVFVideoMixer;
if (mixer != null)
{
// Set output size
mixer.SetOutputParam(new VFPIPVideoOutputParam
{
Width = 1920,
Height = 1080,
FrameRateTime = 30
});
// Configure main video (input 0) - fullscreen
mixer.SetInputParam(0, new VFPIPVideoInputParam
{
X = 0, Y = 0,
Width = 1920, Height = 1080,
Alpha = 255
});
// Configure PIP video (input 1) - bottom-right corner
mixer.SetInputParam(1, new VFPIPVideoInputParam
{
X = 1440, // 1920 - 480
Y = 810, // 1080 - 270
Width = 480,
Height = 270,
Alpha = 255
});
// Set Z-order (layering) — per-pin, not bulk array
mixer.SetInputOrder(0, 0); // Main behind
mixer.SetInputOrder(1, 1); // PIP on top
}
// Connect filters
ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
captureGraph.SetFiltergraph(filterGraph);
// Connect main source to mixer input 0
captureGraph.RenderStream(null, MediaType.Video, mainSource, null, mixerFilter);
// Connect PIP source to mixer input 1
// Note: Requires connecting to specific input pin
IPin mixerInput1 = DsFindPin.ByDirection(mixerFilter, PinDirection.Input, 1);
captureGraph.RenderStream(null, MediaType.Video, pipSource, null, null);
// Connect to mixerInput1 explicitly...
// Render mixer output
captureGraph.RenderStream(null, MediaType.Video, mixerFilter, null, null);
// Setup video window
var videoWindow = (IVideoWindow)filterGraph;
videoWindow.put_Owner(videoWindowHandle);
videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings);
// Run
var mediaControl = (IMediaControl)filterGraph;
mediaControl.Run();
Marshal.ReleaseComObject(captureGraph);
}
}
Example 8: Multi-Source Mixing (4 inputs)¶
Create a 2x2 grid layout with 4 video sources.
C# 2x2 Grid Layout¶
public class VideoMixerGridExample
{
public void Create2x2Grid(string[] videoPaths, IntPtr videoWindowHandle)
{
if (videoPaths.Length != 4)
{
throw new ArgumentException("Requires exactly 4 video sources");
}
var filterGraph = (IFilterGraph2)new FilterGraph();
// Add all source filters
IBaseFilter[] sources = new IBaseFilter[4];
for (int i = 0; i < 4; i++)
{
filterGraph.AddSourceFilter(videoPaths[i], $"Source {i}", out sources[i]);
}
// Add Video Mixer
var mixerFilter = FilterGraphTools.AddFilterFromClsid(
filterGraph,
Consts.CLSID_VFVideoMixer,
"Video Mixer");
var mixer = mixerFilter as IVFVideoMixer;
if (mixer != null)
{
// Set output size
mixer.SetOutputParam(new VFPIPVideoOutputParam
{
Width = 1920,
Height = 1080,
FrameRateTime = 30
});
int halfWidth = 960; // 1920 / 2
int halfHeight = 540; // 1080 / 2
// Top-left (Input 0)
mixer.SetInputParam(0, new VFPIPVideoInputParam { X = 0, Y = 0, Width = halfWidth, Height = halfHeight, Alpha = 255 });
// Top-right (Input 1)
mixer.SetInputParam(1, new VFPIPVideoInputParam { X = halfWidth, Y = 0, Width = halfWidth, Height = halfHeight, Alpha = 255 });
// Bottom-left (Input 2)
mixer.SetInputParam(2, new VFPIPVideoInputParam { X = 0, Y = halfHeight, Width = halfWidth, Height = halfHeight, Alpha = 255 });
// Bottom-right (Input 3)
mixer.SetInputParam(3, new VFPIPVideoInputParam { X = halfWidth, Y = halfHeight, Width = halfWidth, Height = halfHeight, Alpha = 255 });
// Set Z-order (per-pin)
for (int i = 0; i < 4; i++)
{
mixer.SetInputOrder(i, i);
}
}
// Connect sources to mixer and render...
// (Similar to PIP example)
var mediaControl = (IMediaControl)filterGraph;
mediaControl.Run();
}
}
¶
public class VideoMixerGridExample
{
public void Create2x2Grid(string[] videoPaths, IntPtr videoWindowHandle)
{
if (videoPaths.Length != 4)
{
throw new ArgumentException("Requires exactly 4 video sources");
}
var filterGraph = (IFilterGraph2)new FilterGraph();
// Add all source filters
IBaseFilter[] sources = new IBaseFilter[4];
for (int i = 0; i < 4; i++)
{
filterGraph.AddSourceFilter(videoPaths[i], $"Source {i}", out sources[i]);
}
// Add Video Mixer
var mixerFilter = FilterGraphTools.AddFilterFromClsid(
filterGraph,
Consts.CLSID_VFVideoMixer,
"Video Mixer");
var mixer = mixerFilter as IVFVideoMixer;
if (mixer != null)
{
// Set output size
mixer.SetOutputParam(new VFPIPVideoOutputParam
{
Width = 1920,
Height = 1080,
FrameRateTime = 30
});
int halfWidth = 960; // 1920 / 2
int halfHeight = 540; // 1080 / 2
// Top-left (Input 0)
mixer.SetInputParam(0, new VFPIPVideoInputParam { X = 0, Y = 0, Width = halfWidth, Height = halfHeight, Alpha = 255 });
// Top-right (Input 1)
mixer.SetInputParam(1, new VFPIPVideoInputParam { X = halfWidth, Y = 0, Width = halfWidth, Height = halfHeight, Alpha = 255 });
// Bottom-left (Input 2)
mixer.SetInputParam(2, new VFPIPVideoInputParam { X = 0, Y = halfHeight, Width = halfWidth, Height = halfHeight, Alpha = 255 });
// Bottom-right (Input 3)
mixer.SetInputParam(3, new VFPIPVideoInputParam { X = halfWidth, Y = halfHeight, Width = halfWidth, Height = halfHeight, Alpha = 255 });
// Set Z-order (per-pin)
for (int i = 0; i < 4; i++)
{
mixer.SetInputOrder(i, i);
}
}
// Connect sources to mixer and render...
// (Similar to PIP example)
var mediaControl = (IMediaControl)filterGraph;
mediaControl.Run();
}
}
Example 9: Video Mixer with Chroma Key¶
Mix sources with transparent background.
C# Mixer with Chroma Key¶
public void CreateMixerWithChromaKey(string backgroundPath, string foregroundPath)
{
var filterGraph = (IFilterGraph2)new FilterGraph();
// Add sources
filterGraph.AddSourceFilter(backgroundPath, "Background", out IBaseFilter bgSource);
filterGraph.AddSourceFilter(foregroundPath, "Foreground", out IBaseFilter fgSource);
// Add mixer
var mixerFilter = FilterGraphTools.AddFilterFromClsid(
filterGraph,
Consts.CLSID_VFVideoMixer,
"Video Mixer");
var mixer = mixerFilter as IVFVideoMixer;
if (mixer != null)
{
// Configure output
mixer.SetOutputParam(new VFPIPVideoOutputParam
{
Width = 1920,
Height = 1080
});
// Background (fullscreen)
mixer.SetInputParam(0, new VFPIPVideoInputParam
{
X = 0, Y = 0, Width = 1920, Height = 1080
});
// Foreground (centered, smaller)
mixer.SetInputParam(1, new VFPIPVideoInputParam
{
X = 480, Y = 270, Width = 960, Height = 540
});
// Enable chroma key — mixer-wide, 4 args
mixer.SetChromaSettings(
enabled: true,
color: ColorTranslator.ToWin32(Color.FromArgb(0, 255, 0)), // Green
tolerance1: 50,
tolerance2: 10);
}
// Connect and run...
}
Chroma Key Examples¶
Example 10: Green Screen Effect¶
Standalone chroma key filter for green screen removal.
C# Chroma Key Filter¶
public class ChromaKeyExample
{
public void ApplyGreenScreen(string videoPath, string backgroundImagePath, IntPtr videoWindowHandle)
{
var filterGraph = (IFilterGraph2)new FilterGraph();
// Add video source (with green screen)
filterGraph.AddSourceFilter(videoPath, "Source", out IBaseFilter sourceFilter);
// Add Chroma Key filter
var chromaFilter = FilterGraphTools.AddFilterFromClsid(
filterGraph,
Consts.CLSID_VFChromaKey,
"Chroma Key");
// Configure chroma key — real IVFChromaKey API
var chromaKey = chromaFilter as IVFChromaKey;
if (chromaKey != null)
{
// Set key color (green) — single int using RGB macro
chromaKey.put_color(ColorTranslator.ToWin32(Color.FromArgb(0, 255, 0)));
// Set contrast range (low, high bounds)
chromaKey.put_contrast(50, 100);
// Set background image (optional)
if (!string.IsNullOrEmpty(backgroundImagePath))
{
chromaKey.put_image(backgroundImagePath);
}
}
// Connect filters: Source → Chroma Key → Renderer
ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
captureGraph.SetFiltergraph(filterGraph);
captureGraph.RenderStream(null, MediaType.Video, sourceFilter, chromaFilter, null);
captureGraph.RenderStream(null, MediaType.Audio, sourceFilter, null, null);
// Setup video window
var videoWindow = (IVideoWindow)filterGraph;
videoWindow.put_Owner(videoWindowHandle);
videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings);
// Run
var mediaControl = (IMediaControl)filterGraph;
mediaControl.Run();
Marshal.ReleaseComObject(captureGraph);
}
}
C++ Chroma Key¶
HRESULT ApplyChromaKey(IBaseFilter* pChromaFilter)
{
IVFChromaKey* pChromaKey = NULL;
HRESULT hr = pChromaFilter->QueryInterface(IID_IVFChromaKey, (void**)&pChromaKey);
if (FAILED(hr)) return hr;
// Set green color — single COLORREF argument: RGB(0, 255, 0)
hr = pChromaKey->put_color(RGB(0, 255, 0));
if (FAILED(hr)) goto cleanup;
// Set contrast range (low, high)
hr = pChromaKey->put_contrast(40, 90);
if (FAILED(hr)) goto cleanup;
// Optional: Set background image
hr = pChromaKey->put_image(L"C:\\backgrounds\\studio.jpg");
cleanup:
pChromaKey->Release();
return hr;
}
¶
HRESULT ApplyChromaKey(IBaseFilter* pChromaFilter)
{
IVFChromaKey* pChromaKey = NULL;
HRESULT hr = pChromaFilter->QueryInterface(IID_IVFChromaKey, (void**)&pChromaKey);
if (FAILED(hr)) return hr;
// Set green color — single COLORREF argument: RGB(0, 255, 0)
hr = pChromaKey->put_color(RGB(0, 255, 0));
if (FAILED(hr)) goto cleanup;
// Set contrast range (low, high)
hr = pChromaKey->put_contrast(40, 90);
if (FAILED(hr)) goto cleanup;
// Optional: Set background image
hr = pChromaKey->put_image(L"C:\\backgrounds\\studio.jpg");
cleanup:
pChromaKey->Release();
return hr;
}
Example 11: Blue Screen with Fine Tuning¶
Configure blue screen chroma key with optimal settings.
C# Blue Screen¶
public void ApplyBlueScreen(IBaseFilter chromaFilter)
{
var chromaKey = chromaFilter as IVFChromaKey;
if (chromaKey != null)
{
// Set blue color — single int via RGB
chromaKey.put_color(ColorTranslator.ToWin32(Color.FromArgb(0, 0, 255)));
// Fine-tuned contrast range for blue screen
// Lower low = more strict (less tolerance)
// Higher high = more loose (more tolerance)
chromaKey.put_contrast(30, 80);
}
}
Example 12: Custom Color Chroma Key¶
Use any custom color for keying.
C# Custom Color Key¶
public void ApplyCustomColorKey(IBaseFilter chromaFilter, Color keyColor)
{
var chromaKey = chromaFilter as IVFChromaKey;
if (chromaKey != null)
{
// Use any custom color — single int via RGB
chromaKey.put_color(ColorTranslator.ToWin32(keyColor));
// Standard contrast range
chromaKey.put_contrast(50, 100);
}
}
// Example usage:
// ApplyCustomColorKey(chromaFilter, Color.Magenta); // Magenta screen
// ApplyCustomColorKey(chromaFilter, Color.FromArgb(255, 180, 0, 220)); // Custom purple
¶
public void ApplyCustomColorKey(IBaseFilter chromaFilter, Color keyColor)
{
var chromaKey = chromaFilter as IVFChromaKey;
if (chromaKey != null)
{
// Use any custom color — single int via RGB
chromaKey.put_color(ColorTranslator.ToWin32(keyColor));
// Standard contrast range
chromaKey.put_contrast(50, 100);
}
}
// Example usage:
// ApplyCustomColorKey(chromaFilter, Color.Magenta); // Magenta screen
// ApplyCustomColorKey(chromaFilter, Color.FromArgb(255, 180, 0, 220)); // Custom purple
Complete Processing Pipeline¶
Example 13: Combined Effects, Mixing, and Chroma Key¶
Complete example combining all processing filters.
C# Complete Pipeline¶
public class CompleteProcessingPipeline
{
public void CreateCompleteSetup(
string mainVideoPath,
string greenScreenVideoPath,
string backgroundImagePath,
IntPtr videoWindowHandle)
{
var filterGraph = (IFilterGraph2)new FilterGraph();
// 1. Main video source
filterGraph.AddSourceFilter(mainVideoPath, "Main Video", out IBaseFilter mainSource);
// 2. Green screen video source
filterGraph.AddSourceFilter(greenScreenVideoPath, "Green Screen", out IBaseFilter gsSource);
// 3. Add Chroma Key filter for green screen
var chromaFilter = FilterGraphTools.AddFilterFromClsid(
filterGraph,
Consts.CLSID_VFChromaKey,
"Chroma Key");
var chromaKey = chromaFilter as IVFChromaKey;
if (chromaKey != null)
{
chromaKey.put_color(ColorTranslator.ToWin32(Color.FromArgb(0, 255, 0))); // Green
chromaKey.put_contrast(40, 90);
}
// 4. Add Video Effects filter
var effectsFilter = FilterGraphTools.AddFilterFromClsid(
filterGraph,
Consts.CLSID_VFVideoEffects,
"Video Effects");
var effects = effectsFilter as IVFEffects45;
if (effects != null)
{
// Apply effects via VideoEffectSimple structs
effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Darkness, Enabled = true, AmountI = 60 });
effects.add_effect(new VideoEffectSimple { Type = (int)VideoEffectType.Contrast, Enabled = true, AmountI = 80 });
// Add text overlay
effects.add_effect(new VideoEffectSimple
{
Type = (int)VideoEffectType.TextLogo,
Enabled = true,
TextLogo = new MFPTextLogo
{
Text = "LIVE",
FontSize = 48,
X = 50,
Y = 50,
FontColor = 0xFFFFFF,
FontBold = true
}
});
}
// 5. Add Video Mixer
var mixerFilter = FilterGraphTools.AddFilterFromClsid(
filterGraph,
Consts.CLSID_VFVideoMixer,
"Video Mixer");
var mixer = mixerFilter as IVFVideoMixer;
if (mixer != null)
{
mixer.SetOutputParam(new VFPIPVideoOutputParam { Width = 1920, Height = 1080, FrameRateTime = 30 });
// Main video (fullscreen background)
mixer.SetInputParam(0, new VFPIPVideoInputParam { X = 0, Y = 0, Width = 1920, Height = 1080 });
// Chroma-keyed video (PIP)
mixer.SetInputParam(1, new VFPIPVideoInputParam { X = 1200, Y = 700, Width = 640, Height = 360 });
// Set Z-order (per-pin)
mixer.SetInputOrder(0, 0);
mixer.SetInputOrder(1, 1);
}
// Connect the pipeline:
// Main Source → Effects → Mixer Input 0
// GS Source → Chroma Key → Mixer Input 1
// Mixer → Renderer
ICaptureGraphBuilder2 captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
captureGraph.SetFiltergraph(filterGraph);
// Connect main path
captureGraph.RenderStream(null, MediaType.Video, mainSource, effectsFilter, mixerFilter);
// Connect chroma key path
// (Requires pin-level connections to specific mixer input)
// Render mixer output
captureGraph.RenderStream(null, MediaType.Video, mixerFilter, null, null);
// Audio
captureGraph.RenderStream(null, MediaType.Audio, mainSource, null, null);
// Setup video window
var videoWindow = (IVideoWindow)filterGraph;
videoWindow.put_Owner(videoWindowHandle);
videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings);
// Run
var mediaControl = (IMediaControl)filterGraph;
mediaControl.Run();
Marshal.ReleaseComObject(captureGraph);
}
}
Troubleshooting¶
Issue: Effect Not Visible¶
Solution: Ensure effect is enabled and parameters are set on the VideoEffectSimple struct:
var eff = new VideoEffectSimple
{
Type = (int)VideoEffectType.Darkness,
Enabled = true,
AmountI = 75
};
effects.add_effect(eff);
Issue: Chroma Key Not Working Well¶
Solution: Adjust contrast thresholds:
// For difficult green screens:
chromaKey.put_contrast(30, 70); // Tighter range
// For well-lit green screens:
chromaKey.put_contrast(50, 110); // Wider range
Issue: Video Mixer Inputs Not Showing¶
Solution: Verify input parameters and Z-order:
// Ensure inputs are on-screen via VFPIPVideoInputParam struct
mixer.SetInputParam(0, new VFPIPVideoInputParam { X = 0, Y = 0, Width = 640, Height = 480 });
// Set Z-order per-pin
mixer.SetInputOrder(0, 0); // Input 0 at layer 0
mixer.SetInputOrder(1, 1); // Input 1 at layer 1
See Also¶
Documentation¶
- Effects Reference - Complete effects list
- Video Mixer Interface - Full API reference
- Chroma Key Interface - Complete interface docs