Skip to main content

FilterVideoProcessor

The FilterVideoProcessor is a helper class that simplifies the process of applying visual effects to video streams. It extends the NoDropVideoProcessor class, providing a convenient way to apply VideoFilter implementations.

info

You will need to create a VideoFilter implementation to use this class and pass an EglBase instance to the constructor.

We provide two primary VideoFilter types:

  • BitmapVideoFilter, and
  • RawVideoFilter

BitmapVideoFilter

The BitmapVideoFilter provides a Bitmap of each frame for easy manipulation.

NOTE

This is less performant than using the RawVideoFilter because we do YUV to ARGB conversions internally.

Usage Example

This example shows how to create a custom BitmapVideoFilter that inverts the colors of the video.

class SampleVideoFilter : BitmapVideoFilter() {
override fun applyFilter(bitmap: Bitmap) {
val width = bitmap.width
val height = bitmap.height

for (y in 0 until height) {
for (x in 0 until width) {
val pixel = bitmap[x, y]

val r = 255 - Color.red(pixel)
val g = 255 - Color.green(pixel)
val b = 255 - Color.blue(pixel)

bitmap[x, y] = Color.rgb(r, g, b)
}
}
}
}

RawVideoFilter

The RawVideoFilter is quite similar to creating a custom VideoProcessor. It allows you to get frames directly from WebRTC and modify them.

Usage Example

Here's how to implement a RawVideoFilter that dims the brightness of the video.

class CustomFilter : RawVideoFilter() {
override fun applyFilter(
videoFrame: VideoFrame,
surfaceTextureHelper: SurfaceTextureHelper,
): VideoFrame {
val buffer = videoFrame.buffer
val i420 = buffer.toI420()

if (i420 == null) return videoFrame

val width = i420.width
val height = i420.height

val yPlane = i420.dataY
val yStride = i420.strideY

// Dim brightness: halve all Y (luma) values
for (y in 0 until height) {
for (x in 0 until width) {
val index = y * yStride + x
yPlane.put(index, (yPlane.get(index).toInt() / 2).toByte())
}
}

return VideoFrame(i420, videoFrame.rotation, videoFrame.timestampNs)
}
}

Using the Filter

After creating a VideoFilter, you can create an instance of FilterVideoProcessor and pass it down to the RealtimeKitMeetingBuilder object.

val eglBase = EglBase.create()

// Create the filter which will be used to process the video frames.
val bgFilter = CustomFilter()

// Create the processor that will execute the filter.
val filterProcessor = FilterVideoProcessor(eglBase = eglBase, filter = bgFilter)

val meeting = RealtimeKitMeetingBuilder()
.setVideoProcessor(filterProcessor)
.build(activity)