# 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](https://download.sinch.com/android/latest/reference/sinch-rtc/com.sinch.android.rtc.calling/-call-controller/index.html). Events are received using the [CallControllerListener](https://download.sinch.com/android/latest/reference/sinch-rtc/com.sinch.android.rtc.calling/-call-controller-listener/index.html) (for example, `onIncomingCall()`) and the [VideoCallListener](https://download.sinch.com/android/latest/reference/sinch-rtc/com.sinch.android.rtc.video/-video-call-listener/index.html), a subclass of [CallListener](https://download.sinch.com/android/latest/reference/sinch-rtc/com.sinch.android.rtc.calling/-call-listener/index.html) 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](https://download.sinch.com/android/latest/reference/sinch-rtc/com.sinch.android.rtc.video/-video-call-listener/index.html) and added it to a call using [`Call.addCallListener()`](https://download.sinch.com/android/latest/reference/sinch-rtc/com.sinch.android.rtc.calling/-call/add-call-listener.html), the following callback will be invoked:

```kotlin
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()](https://download.sinch.com/android/latest/reference/sinch-rtc/com.sinch.android.rtc.calling/-call/pause-video.html) or
[Call.resumeVideo()](https://download.sinch.com/android/latest/reference/sinch-rtc/com.sinch.android.rtc.calling/-call/resume-video.html)

Call listeners are notified of pause and resume events via [`VideoCallListener.onVideoTrackPaused()`](https://download.sinch.com/android/latest/reference/sinch-rtc/com.sinch.android.rtc.video/-video-call-listener/index.html) and related callbacks. Use these events to update the UI with a pause indicator and then remove it when resumed.

```kotlin
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)`](https://download.sinch.com/android/latest/reference/sinch-rtc/com.sinch.android.rtc.video/-video-controller/set-resize-behaviour.html) and [`VideoController.setLocalResizeBehaviour(VideoScalingType)`](https://download.sinch.com/android/latest/reference/sinch-rtc/com.sinch.android.rtc.video/-video-controller/set-local-video-resize-behaviour.html) 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()`](https://download.sinch.com/android/latest/reference/sinch-rtc/com.sinch.android.rtc.video/-video-controller/toggle-capture-device-position.html).

## 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`](https://download.sinch.com/android/latest/reference/sinch-rtc/com.sinch.android.rtc.video/-remote-video-frame-listener/index.html) with the `onFrame()` callback. Note: this method runs in the render path; in-place modification of the provided I420 frame will be rendered.

Example:

```kotlin
class YourVideoFrameHandler: RemoteVideoFrameListener {

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

Use [`VideoController.setRemoteVideoFrameListener()`](https://download.sinch.com/android/latest/reference/sinch-rtc/com.sinch.android.rtc.video/-video-controller/index.html) to register your handler to receive remote video frames.

Example:

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

## Accessing Video Frames of the Local Streams

Similar to the remote stream, use [`VideoController.setLocalVideoFrameListener()`](https://download.sinch.com/android/latest/reference/sinch-rtc/com.sinch.android.rtc.video/-video-controller/index.html) 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:

```kotlin
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())
```