Skip to content

Instantly share code, notes, and snippets.

@naveenrobo
Created February 11, 2022 14:54
Show Gist options
  • Save naveenrobo/be998edd51f02fa313b176d3f0d65ee7 to your computer and use it in GitHub Desktop.
Save naveenrobo/be998edd51f02fa313b176d3f0d65ee7 to your computer and use it in GitHub Desktop.
package dev.dotworld.mdm.ui.videocall
import android.annotation.TargetApi
import android.content.Context
import android.graphics.ImageFormat
import android.hardware.camera2.CameraCharacteristics
import android.hardware.camera2.CameraManager
import android.hardware.camera2.CameraMetadata
import android.os.Build
import android.util.Log
import com.twilio.video.Camera2Capturer
import com.twilio.video.CameraCapturer
import com.twilio.video.VideoCapturer
import dev.dotworld.mdm.utils.Utils
import tvi.webrtc.CapturerObserver
import tvi.webrtc.SurfaceTextureHelper
/*
* Simple wrapper class that uses Camera2Capturer with supported devices.
*/
class CameraCapturerCompat(context: Context, cameraId: String) : VideoCapturer {
private var camera1Capturer: CameraCapturer? = null
private var camera2Capturer: Camera2Capturer? = null
private var activeCapturer: VideoCapturer? = null
override fun initialize(
surfaceTextureHelper: SurfaceTextureHelper,
context: Context,
capturerObserver: CapturerObserver
) {
activeCapturer?.initialize(surfaceTextureHelper, context, capturerObserver)
}
override fun startCapture(width: Int, height: Int, framerate: Int) {
activeCapturer?.startCapture(width, height, framerate)
}
@Throws(InterruptedException::class)
override fun stopCapture() {
activeCapturer?.stopCapture()
}
override fun isScreencast(): Boolean {
return activeCapturer?.isScreencast ?: false
}
override fun dispose() {
activeCapturer?.dispose()
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private fun isCameraIdSupported(context: Context, cameraId: String): Boolean {
var isMonoChromeSupported = false
var isPrivateImageFormatSupported = false
val cameraManager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
val cameraCharacteristics: CameraCharacteristics = try {
cameraManager.getCameraCharacteristics(cameraId)
} catch (e: Exception) {
e.printStackTrace()
return false
}
/*
* This is a temporary work around for a RuntimeException that occurs on devices which contain cameras
* that do not support ImageFormat.PRIVATE output formats. A long term fix is currently in development.
* https://github.com/twilio/video-quickstart-android/issues/431
*/
val streamMap =
cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
if (streamMap != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
isPrivateImageFormatSupported = streamMap.isOutputSupportedFor(ImageFormat.PRIVATE)
}
/*
* Read the color filter arrangements of the camera to filter out the ones that support
* SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO or SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR.
* Visit this link for details on supported values - https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
*/
val colorFilterArrangement = cameraCharacteristics.get(
CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && colorFilterArrangement != null) {
isMonoChromeSupported = (colorFilterArrangement
== CameraMetadata.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO ||
colorFilterArrangement
== CameraMetadata.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR)
}
return isPrivateImageFormatSupported && !isMonoChromeSupported
}
init {
try {
if (Camera2Capturer.isSupported(context) && isCameraIdSupported(
context,
cameraId
) && Utils.isLollipopApiSupported
) {
Log.i(TAG, "Camera 2: $cameraId")
camera2Capturer = Camera2Capturer(context, cameraId)
activeCapturer = camera2Capturer
camera1Capturer = null
} else {
Log.i(TAG, "Camera 1: $cameraId")
camera1Capturer =
CameraCapturer(context, cameraId)
activeCapturer = camera1Capturer
camera2Capturer = null
}
} catch (e: Exception) {
e.printStackTrace()
}
}
companion object {
private const val TAG = "CameraCapturerCompat"
}
}
private fun enumerateCamera1(): List<FormatItem> {
val availableCameras: MutableList<FormatItem> = mutableListOf()
for (i in 0 until Camera.getNumberOfCameras()) {
val cameraInfo = CameraInfo()
Camera.getCameraInfo(i, cameraInfo)
val title = if (cameraInfo.facing == 1) "Front $i" else "Back $i"
val facing = if (cameraInfo.facing == 1) CameraFacing.FRONT else CameraFacing.BACK
val facing1 = if (cameraInfo.facing == 1) "front" else "back"
val data =
"Camera " + i + ", Facing " + facing1 + ", Orientation " + cameraInfo.orientation
availableCameras.add(
FormatItem(title, data, ImageFormat.JPEG, false, facing)
)
}
return availableCameras
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment