Skip to content

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:

  1. Using OnVideoFrameBitmap: Process frames as Bitmap objects with GDI+ - easier to use but with moderate performance
  2. 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.