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.
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, andRawVideoFilter
BitmapVideoFilter
The BitmapVideoFilter provides a Bitmap of each frame for easy manipulation.
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)