Skip to content
Last updated

Video Calling

Set up video calls with the Sinch Android Voice with Video SDK.

Setting Up a Video Call

Just like audio calls, video calls are placed through the CallController. Events are received using the CallControllerListener (for example, onIncomingCall()) and the VideoCallListener, a subclass of CallListener that includes callbacks like onCallEstablished() and onCallEnded(). The call controller is owned by the SinchClient and accessed using sinchClient.callController.

Showing the Video Streams

Once you have created a VideoCallListener and added it to a call using Call.addCallListener(), the following callback will be invoked:

override fun onVideoTrackAdded(call: Call) {
    // Get a reference to your SinchClient, in the samples this is done through the service interface.
    val videoController = sinchServiceInterface.videoController
    val localPreviewView = videoController.localView
    val remoteView = videoController.remoteView

    // Add the views to your view hierarchy
    ...
}

After the call has ended, remove the views from your view hierarchy.

Pausing and Resuming a Video Stream

To pause or resume the local video stream, use the method Call.pauseVideo() or Call.resumeVideo()

Call listeners are notified of pause and resume events via VideoCallListener.onVideoTrackPaused() and related callbacks. Use these events to update the UI with a pause indicator and then remove it when resumed.

override fun onVideoTrackPaused(call: Call) {
     // Implement what to be done when remote user pause video stream.
}

override fun onVideoTrackResumed(call: Call) {
     // Implement what to be done when remote user resumes video stream.
}

Video Content Fitting and Aspect Ratio

Use VideoController.setResizeBehaviour(VideoScalingType) and VideoController.setLocalResizeBehaviour(VideoScalingType) to control local and remote video scaling. Possible arguments are ASPECT_FIT, ASPECT_FILL, and ASPECT_BALANCED. The local preview always uses ASPECT_FIT.

Switching Capturing Device

Toggle the capture device (front/back camera) using VideoController.toggleCaptureDevicePosition().

Accessing Video Frames of the Remote Streams

The Sinch SDK can provide access to raw video frames via a callback function. This callback can be used to achieve rich functionality such as applying filters, adding stickers to the video frames or saving the video frame as an image.

Implement a video frame handler by providing RemoteVideoFrameListener with the onFrame() callback. Note: this method runs in the render path; in-place modification of the provided I420 frame will be rendered.

Example:

class YourVideoFrameHandler: RemoteVideoFrameListener {

    @Synchronized 
    override fun onFrame(callId: String, videoFrame: VideoFrame) {
    // Process videoFrame
    }
}

Use VideoController.setRemoteVideoFrameListener() to register your handler to receive remote video frames.

Example:

val videoFrameHandler = YourVideoFrameHandler()
sinchClient.videoController.setRemoteVideoFrameListener(videoFrameHandler)

Accessing Video Frames of the Local Streams

Similar to the remote stream, use VideoController.setLocalVideoFrameListener() to access local video frames.

Convert video frame from I420 to NV21

The SDK provides a helper to convert the default I420 frame to an NV21 frame, which is handy when you need to save it as an image on Android. Use VideoUtils.I420toNV21Frame(VideoFrame) for the conversion. Note: this helper doesn't release the original I420 video frame.

Example:

val videoFrame = ... // Get the video frame from onFrame() callback
val nv21Frame = VideoUtils.I420toNV21Frame(videoFrame)

val image: YuvImage = YuvImage(nv21Frame.yuvPlanes()[0].array(),
                              ImageFormat.NV21,
                              nv21Frame.width(),
                              nv21Frame.height(),
                              nv21Frame.yuvStrides())