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