#
Creating Custom Real-time Video Effects in C# Applications
Video Capture SDK .Net Video Edit SDK .Net Media Player SDK .Net
#
Introduction to Video Frame Processing
When developing video applications, you often need to apply custom effects or overlays to video streams in real-time. The .NET SDK provides two powerful events for this purpose: OnVideoFrameBitmap
and OnVideoFrameBuffer
. These events give you direct access to each video frame, allowing you to modify pixels before they're rendered or encoded.
#
Implementation Methods
There are two primary approaches to implementing custom video effects:
- Using OnVideoFrameBitmap: Process frames as Bitmap objects with GDI+ - easier to use but with moderate performance
- Using OnVideoFrameBuffer: Manipulate raw RGB24 image buffer directly - offers better performance but requires more low-level code
#
Code Examples for Custom Video Effects
#
Text Overlay Implementation
Adding text overlays to video is useful for watermarking, displaying information, or creating captions. This example demonstrates how to add simple text to your video frames:
private void VideoCapture1_OnVideoFrameBitmap(object sender, VideoFrameBitmapEventArgs e)
{
Graphics grf = Graphics.FromImage(e.Frame);
grf.DrawString("Hello!", new Font(FontFamily.GenericSansSerif, 20), new SolidBrush(Color.White), 20, 20);
grf.Dispose();
e.UpdateData = true;
}
#
Grayscale Effect Implementation
Converting video to grayscale is a fundamental image processing technique. This example shows how to access and modify individual pixel values:
private void VideoCapture1_OnVideoFrameBitmap(object sender, VideoFrameBitmapEventArgs e)
{
Bitmap bmp = e.Frame;
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat);
IntPtr ptr = bmpData.Scan0;
int bytes = Math.Abs(bmpData.Stride) * bmp.Height;
byte[] rgbValues = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
// Apply standard luminance formula (0.3R + 0.59G + 0.11B) for accurate grayscale conversion
for (int i = 0; i < rgbValues.Length; i += 3)
{
int gray = (int)(rgbValues[i] * 0.3 + rgbValues[i + 1] * 0.59 + rgbValues[i + 2] * 0.11);
rgbValues[i] = (byte)gray;
rgbValues[i + 1] = (byte)gray;
rgbValues[i + 2] = (byte)gray;
}
System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
bmp.UnlockBits(bmpData);
e.UpdateData = true;
}
#
Brightness Adjustment Implementation
This example demonstrates how to adjust the brightness of video frames - a common requirement in video processing applications:
private void VideoCapture1_OnVideoFrameBitmap(object sender, VideoFrameBitmapEventArgs e)
{
float brightness = 1.2f; // Values > 1 increase brightness, < 1 decrease it
Bitmap bmp = e.Frame;
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat);
IntPtr ptr = bmpData.Scan0;
int bytes = Math.Abs(bmpData.Stride) * bmp.Height;
byte[] rgbValues = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
// Apply brightness adjustment to each color channel
for (int i = 0; i < rgbValues.Length; i++)
{
int newValue = (int)(rgbValues[i] * brightness);
rgbValues[i] = (byte)Math.Min(255, Math.Max(0, newValue));
}
System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
bmp.UnlockBits(bmpData);
e.UpdateData = true;
}
#
Timestamp Overlay Implementation
Adding timestamps to video frames is essential for surveillance and logging applications. This example shows how to create a professional-looking timestamp with a semi-transparent background:
private void VideoCapture1_OnVideoFrameBitmap(object sender, VideoFrameBitmapEventArgs e)
{
Graphics grf = Graphics.FromImage(e.Frame);
// Create a semi-transparent background for better readability
Rectangle textBackground = new Rectangle(10, e.Frame.Height - 50, 250, 40);
grf.FillRectangle(new SolidBrush(Color.FromArgb(128, 0, 0, 0)), textBackground);
// Display current date and time
string dateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
grf.DrawString(dateTime, new Font(FontFamily.GenericSansSerif, 16),
new SolidBrush(Color.White), 15, e.Frame.Height - 45);
grf.Dispose();
e.UpdateData = true;
}
#
Performance Optimization Tips
#
Working with Raw Buffer Data
For high-performance applications, processing raw buffer data offers significant speed advantages:
// OnVideoFrameBuffer event example (pseudo-code)
private void VideoCapture1_OnVideoFrameBuffer(object sender, VideoFrameBufferEventArgs e)
{
// e.Buffer contains raw RGB24 data
// Each pixel uses 3 bytes in RGB order
// Process directly for maximum performance
}
#
Best Practices for Frame Processing
- Memory Management: Always dispose Graphics objects and unlock bitmapped data
- Performance Considerations: For real-time processing, keep operations lightweight
- Buffer Processing: We strongly recommend processing RAW data in the OnVideoFrameBuffer event for optimal performance
- External Libraries: Consider using Intel IPP or other optimized image-processing libraries for complex operations
#
Additional Resources
Visit our GitHub page to access more code samples and complete project examples.