Skip to main content
Version: 3.x.x

What is SurfaceViewRenderer?

SurfaceViewRenderer displays a video track on a SurfaceView. VideoSDK's VideoView extends it and manages it for you.

caution

Render the video of a participant with VideoView, not with your own SurfaceViewRenderer. The track of a remote participant's RTCStream can be one whose addSink() does nothing, so a SurfaceViewRenderer attached with addSink() can stay black.

Here's the lifecycle of a SurfaceViewRenderer:

In order:

  1. Call init() after you create the renderer and before you use it. It starts the render thread.

  2. Call addSink() on the VideoTrack you want to show, passing the renderer.

  3. Call removeSink() on that track, passing the renderer, when you're done showing the video.

  4. Call release() last so the render thread stops. Call it before the activity is destroyed, and before you call init() again.

Common mistakes​

1. Not initializing the renderer​

The render thread never starts, so the view stays black.

2. Initializing it again without releasing it​

If you call init() again without calling release() first, you get this error:

java.lang.IllegalStateException: svrParticipant Already initialized
at videosdk.org.webrtc.EglRenderer.init(EglRenderer.java:194)
3. Two videos on the same renderer​

If you call addSink() with the same SurfaceViewRenderer for a second track without calling removeSink() for the first, both videos draw on it and flicker, like this:


VideoView does all of this for you. Use it instead of SurfaceViewRenderer.

VideoView​

VideoView renders live video and sets up and releases the renderer for you.

VideoView extends videosdk.org.webrtc.SurfaceViewRenderer. Import VideoTrack and the other WebRTC types you use with it from videosdk.org.webrtc, not from org.webrtc.

Methods​

  1. addTrack(videoTrack: VideoTrack?) - addTrack renders the video track you pass. Pass the track of a RTCStream whose kind is MediaType.VIDEO or MediaType.SHARE, or the track of a camera track from VideoSDK.createCameraVideoTrack() to preview the camera before you join. Cast either one to VideoTrack, for example stream.track as? VideoTrack. A null track is ignored. Adding the track of the participant that the view already shows does nothing, so you can call it again safely. Call removeTrack() before you add another participant's track. Your own camera is shown in one VideoView at a time. If you add your video track to a second VideoView, the first one stops updating.

  2. removeTrack() - removeTrack stops showing the current track. The view stays usable and can take another track, so call it when a recycled tile moves to another participant.

  3. releaseSurfaceViewRenderer() - Call releaseSurfaceViewRenderer once, before the activity is destroyed or in a Compose DisposableEffect. It also removes the track, so calling removeTrack() first is optional. The view can't render again afterwards. Don't call the release() method that VideoView inherits from SurfaceViewRenderer: it can deadlock while frames are still being drawn.

  4. setFrameSink(sink: FrameSink) - setFrameSink hands the frames this view would draw to your own FrameSink (from live.videosdk.rtc.android.render) instead. Call it before addTrack(). Today only the local screen-share preview reaches your sink. Your own camera and remote video are drawn directly and never reach it.

  5. attachLocalPreview() - attachLocalPreview draws the local camera preview, with video effects applied, into a view that has no track, such as on a pre-call screen. It has no effect unless video effects are on, which you set with VideoSDK.setVideoEffects(). See Video Effects. Only one view can show the local preview: attaching another view replaces the first.

  6. detachLocalPreview() - detachLocalPreview stops drawing the local camera preview into the view. removeTrack() and releaseSurfaceViewRenderer() also do this.

  7. setMirror(mirror: Boolean) - setMirror(true) flips the video horizontally, as a front-camera self view is usually shown.

  8. setScalingType(scalingType: RendererCommon.ScalingType) - setScalingType sets how the video fits the view: SCALE_ASPECT_FIT letterboxes it, SCALE_ASPECT_FILL crops it. Import RendererCommon from videosdk.org.webrtc.

On your own camera, setMirror() and setScalingType() apply only in a room without video effects. The pre-call preview and the effects preview ignore them.

How to use VideoView ?​

Layout​
<live.videosdk.rtc.android.VideoView
android:id="@+id/participantView"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
Initialising and adding video track​
import videosdk.org.webrtc.VideoTrack

val track = stream.track as? VideoTrack
participantView.addTrack(track)
removeTrack​
participantView.removeTrack()

release​

override fun onDestroy() {
participantView.releaseSurfaceViewRenderer()
super.onDestroy()
}

Got a Question? Ask us on discord