Skip to content

Commit 23360ad

Browse files
authored
Merge pull request #2173 from pedroSG94/camera2-features
Camera2 features
2 parents 508c3d1 + daaeae0 commit 23360ad

3 files changed

Lines changed: 145 additions & 8 deletions

File tree

encoder/src/main/java/com/pedro/encoder/input/sources/video/Camera2Source.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,14 @@ class Camera2Source(context: Context): VideoSource() {
154154
return camera.tapToFocus(view, event)
155155
}
156156

157+
fun tapToMeterExposure(view: View, event: MotionEvent): Boolean {
158+
return if (isRunning()) camera.tapToMeterExposure(view, event) else false
159+
}
160+
161+
fun tapToMeterWhiteBalance(view: View, event: MotionEvent): Boolean {
162+
return if (isRunning()) camera.tapToMeterWhiteBalance(view, event) else false
163+
}
164+
157165
@JvmOverloads
158166
fun setZoom(event: MotionEvent, delta: Float = 0.1f) {
159167
if (isRunning()) camera.setZoom(event, delta)
@@ -234,6 +242,16 @@ class Camera2Source(context: Context): VideoSource() {
234242

235243
fun isExposureLockEnabled() = camera.isExposureLockEnabled
236244

245+
fun enableWhiteBalanceLock(): Boolean {
246+
return if (isRunning()) camera.enableWhiteBalanceLock() else false
247+
}
248+
249+
fun disableWhiteBalanceLock() {
250+
if (isRunning()) camera.disableWhiteBalanceLock()
251+
}
252+
253+
fun isWhiteBalanceLockEnabled() = camera.isWhiteBalanceLockEnabled
254+
237255
@JvmOverloads
238256
fun addImageListener(
239257
format: Int,

encoder/src/main/java/com/pedro/encoder/input/video/Camera2ApiManager.kt

Lines changed: 102 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ class Camera2ApiManager(context: Context) {
9999
private set
100100
var isAutoWhiteBalanceEnabled: Boolean = true
101101
private set
102+
var isWhiteBalanceLockEnabled: Boolean = false
103+
private set
102104
var isRunning: Boolean = false
103105
private set
104106
private var fps = 30
@@ -409,6 +411,11 @@ class Camera2ApiManager(context: Context) {
409411
val builderInputSurface = this.builderInputSurface ?: return false
410412
val modes = characteristics.secureGet(CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES) ?: return false
411413
if (!modes.contains(mode)) return false
414+
val maxRegionsAwb = characteristics.secureGet(CameraCharacteristics.CONTROL_MAX_REGIONS_AWB) ?: 0
415+
if (maxRegionsAwb > 0) {
416+
val clearRect = MeteringRectangle(0, 0, 0, 0, MeteringRectangle.METERING_WEIGHT_DONT_CARE)
417+
builderInputSurface.set(CaptureRequest.CONTROL_AWB_REGIONS, arrayOf(clearRect))
418+
}
412419
builderInputSurface.set(CaptureRequest.CONTROL_AWB_MODE, mode)
413420
isAutoWhiteBalanceEnabled = applyRequest(builderInputSurface)
414421
return isAutoWhiteBalanceEnabled
@@ -453,6 +460,11 @@ class Camera2ApiManager(context: Context) {
453460
val builderInputSurface = this.builderInputSurface ?: return false
454461
val modes = characteristics.secureGet(CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES) ?: return false
455462
if (!modes.contains(CaptureRequest.CONTROL_AE_MODE_ON)) return false
463+
val maxRegionsAe = characteristics.secureGet(CameraCharacteristics.CONTROL_MAX_REGIONS_AE) ?: 0
464+
if (maxRegionsAe > 0) {
465+
val clearRect = MeteringRectangle(0, 0, 0, 0, MeteringRectangle.METERING_WEIGHT_DONT_CARE)
466+
builderInputSurface.set(CaptureRequest.CONTROL_AE_REGIONS, arrayOf(clearRect))
467+
}
456468
builderInputSurface.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON)
457469
isAutoExposureEnabled = applyRequest(builderInputSurface)
458470
return isAutoExposureEnabled
@@ -492,6 +504,30 @@ class Camera2ApiManager(context: Context) {
492504
isExposureLockEnabled = false
493505
}
494506

507+
/**
508+
* Lock auto white balance to the current value. The camera will stop adjusting white balance
509+
* automatically (useful to avoid color shifts from lighting changes).
510+
* @return true if success, false if fail (not supported or called before start camera)
511+
*/
512+
fun enableWhiteBalanceLock(): Boolean {
513+
val characteristics = cameraCharacteristics ?: return false
514+
val builderInputSurface = this.builderInputSurface ?: return false
515+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
516+
val available = characteristics.secureGet(CameraCharacteristics.CONTROL_AWB_LOCK_AVAILABLE) ?: return false
517+
if (!available) return false
518+
}
519+
builderInputSurface.set(CaptureRequest.CONTROL_AWB_LOCK, true)
520+
isWhiteBalanceLockEnabled = applyRequest(builderInputSurface)
521+
return isWhiteBalanceLockEnabled
522+
}
523+
524+
fun disableWhiteBalanceLock() {
525+
val builderInputSurface = this.builderInputSurface ?: return
526+
builderInputSurface.set(CaptureRequest.CONTROL_AWB_LOCK, false)
527+
applyRequest(builderInputSurface)
528+
isWhiteBalanceLockEnabled = false
529+
}
530+
495531
fun enableVideoStabilization(): Boolean {
496532
val characteristics = cameraCharacteristics ?: return false
497533
val builderInputSurface = this.builderInputSurface ?: return false
@@ -569,24 +605,30 @@ class Camera2ApiManager(context: Context) {
569605
return supportedExposure
570606
}
571607

572-
fun tapToFocus(view: View, event: MotionEvent): Boolean {
573-
val builderInputSurface = this.builderInputSurface ?: return false
574-
val characteristics = cameraCharacteristics ?: return false
575-
val session = cameraCaptureSession ?: return false
576-
if (characteristics.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AF) == 0) return false
577-
val focusTag = "focus"
578-
val sensorArraySize = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE) ?: return false
608+
private fun getTapRect(view: View, event: MotionEvent): MeteringRectangle? {
609+
val characteristics = cameraCharacteristics ?: return null
610+
val sensorArraySize = characteristics.secureGet(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE) ?: return null
611+
579612
val x = event.x
580613
val y = event.y
581614
val focusX = (x / view.width.toFloat()) * sensorArraySize.width()
582615
val focusY = (y / view.height.toFloat()) * sensorArraySize.height()
583-
val focusRect = MeteringRectangle(
616+
return MeteringRectangle(
584617
(focusX - 100).toInt().coerceIn(0, sensorArraySize.width()),
585618
(focusY - 100).toInt().coerceIn(0, sensorArraySize.height()),
586619
(100 * 2).coerceIn(0, sensorArraySize.width()),
587620
(100 * 2).coerceIn(0, sensorArraySize.height()),
588621
MeteringRectangle.METERING_WEIGHT_MAX
589622
)
623+
}
624+
625+
fun tapToFocus(view: View, event: MotionEvent): Boolean {
626+
val builderInputSurface = this.builderInputSurface ?: return false
627+
val session = cameraCaptureSession ?: return false
628+
val characteristics = cameraCharacteristics ?: return false
629+
if ((characteristics.secureGet(CameraCharacteristics.CONTROL_MAX_REGIONS_AF) ?: 0) == 0) return false
630+
val focusRect = getTapRect(view, event) ?: return false
631+
val focusTag = "focus"
590632

591633
val captureCallbackHandler: CameraCaptureSession.CaptureCallback =
592634
object : CameraCaptureSession.CaptureCallback() {
@@ -621,6 +663,56 @@ class Camera2ApiManager(context: Context) {
621663
}
622664
}
623665

666+
/**
667+
* Tap to meter exposure at a specific point.
668+
*
669+
* @param view The view where the touch event occurred
670+
* @param event The touch event containing coordinates
671+
* @return true if successful, false otherwise
672+
*/
673+
fun tapToMeterExposure(view: View, event: MotionEvent): Boolean {
674+
if (isExposureLockEnabled) return false
675+
val builderInputSurface = this.builderInputSurface ?: return false
676+
val characteristics = cameraCharacteristics ?: return false
677+
if ((characteristics.secureGet(CameraCharacteristics.CONTROL_MAX_REGIONS_AE) ?: 0) == 0) return false
678+
val aeRect = getTapRect(view, event) ?: return false
679+
680+
return try {
681+
builderInputSurface.set(CaptureRequest.CONTROL_AE_REGIONS, arrayOf(aeRect))
682+
builderInputSurface.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON)
683+
isAutoExposureEnabled = applyRequest(builderInputSurface)
684+
isAutoExposureEnabled
685+
} catch (e: Exception) {
686+
Log.e(TAG, "Error setting AE region", e)
687+
false
688+
}
689+
}
690+
691+
/**
692+
* Tap to meter white balance at a specific point.
693+
*
694+
* @param view The view where the touch event occurred
695+
* @param event The touch event containing coordinates
696+
* @return true if successful, false otherwise
697+
*/
698+
fun tapToMeterWhiteBalance(view: View, event: MotionEvent): Boolean {
699+
if (isWhiteBalanceLockEnabled) return false
700+
val builderInputSurface = this.builderInputSurface ?: return false
701+
val characteristics = cameraCharacteristics ?: return false
702+
if ((characteristics.secureGet(CameraCharacteristics.CONTROL_MAX_REGIONS_AWB) ?: 0) == 0) return false
703+
val awbRect = getTapRect(view, event) ?: return false
704+
705+
return try {
706+
builderInputSurface.set(CaptureRequest.CONTROL_AWB_REGIONS, arrayOf(awbRect))
707+
builderInputSurface.set(CaptureRequest.CONTROL_AWB_MODE, CameraMetadata.CONTROL_AWB_MODE_AUTO)
708+
isAutoWhiteBalanceEnabled = applyRequest(builderInputSurface)
709+
isAutoWhiteBalanceEnabled
710+
} catch (e: Exception) {
711+
Log.e(TAG, "Error setting AWB region", e)
712+
false
713+
}
714+
}
715+
624716
/**
625717
* Select camera facing
626718
*
@@ -961,6 +1053,8 @@ class Camera2ApiManager(context: Context) {
9611053

9621054
@JvmOverloads
9631055
fun closeCamera(resetSurface: Boolean = true) {
1056+
isExposureLockEnabled = false
1057+
isWhiteBalanceLockEnabled = false
9641058
isLanternEnabled = false
9651059
zoomLevel = 1.0f
9661060
cameraCaptureSession?.close()

library/src/main/java/com/pedro/library/base/Camera2Base.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,23 @@ public boolean isExposureLockEnabled() {
206206
return cameraManager.isExposureLockEnabled();
207207
}
208208

209+
/**
210+
* Lock auto white balance to the current value. The camera will stop adjusting white balance
211+
* automatically (useful to avoid color shifts from lighting changes).
212+
* @return true if success, false if fail (not supported or called before start camera)
213+
*/
214+
public boolean enableWhiteBalanceLock() {
215+
return cameraManager.enableWhiteBalanceLock();
216+
}
217+
218+
public void disableWhiteBalanceLock() {
219+
cameraManager.disableWhiteBalanceLock();
220+
}
221+
222+
public boolean isWhiteBalanceLockEnabled() {
223+
return cameraManager.isWhiteBalanceLockEnabled();
224+
}
225+
209226
public void setDynamicFps(boolean enabled) {
210227
cameraManager.setDynamicFps(enabled);
211228
}
@@ -981,6 +998,14 @@ public boolean tapToFocus(View view, MotionEvent event) {
981998
return cameraManager.tapToFocus(view, event);
982999
}
9831000

1001+
public boolean tapToMeterExposure(View view, MotionEvent event) {
1002+
return cameraManager.tapToMeterExposure(view, event);
1003+
}
1004+
1005+
public boolean tapToMeterWhiteBalance(View view, MotionEvent event) {
1006+
return cameraManager.tapToMeterWhiteBalance(view, event);
1007+
}
1008+
9841009
public GlInterface getGlInterface() {
9851010
return glInterface;
9861011
}

0 commit comments

Comments
 (0)