Add --camera-facing

Add an option to select the camera by its lens facing (front, back or
external).

PR #4213 <https://github.com/Genymobile/scrcpy/pull/4213>

Co-authored-by: Romain Vimont <rom@rom1v.com>
Signed-off-by: Romain Vimont <rom@rom1v.com>
This commit is contained in:
Simon Chan
2023-07-22 17:17:05 +08:00
committed by Romain Vimont
parent 7f8d079c8c
commit faebb7d70a
13 changed files with 160 additions and 7 deletions

View File

@@ -6,6 +6,7 @@ import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureFailure;
@@ -28,6 +29,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
public class CameraCapture extends SurfaceCapture {
private final String explicitCameraId;
private final CameraFacing cameraFacing;
private final Size explicitSize;
private HandlerThread cameraThread;
@@ -37,8 +39,9 @@ public class CameraCapture extends SurfaceCapture {
private final AtomicBoolean disconnected = new AtomicBoolean();
public CameraCapture(String explicitCameraId, Size explicitSize) {
public CameraCapture(String explicitCameraId, CameraFacing cameraFacing, Size explicitSize) {
this.explicitCameraId = explicitCameraId;
this.cameraFacing = cameraFacing;
this.explicitSize = explicitSize;
}
@@ -50,7 +53,7 @@ public class CameraCapture extends SurfaceCapture {
cameraExecutor = new HandlerExecutor(cameraHandler);
try {
String cameraId = selectCamera(explicitCameraId);
String cameraId = selectCamera(explicitCameraId, cameraFacing);
if (cameraId == null) {
throw new IOException("No matching camera found");
}
@@ -62,7 +65,7 @@ public class CameraCapture extends SurfaceCapture {
}
}
private static String selectCamera(String explicitCameraId) throws CameraAccessException {
private static String selectCamera(String explicitCameraId, CameraFacing cameraFacing) throws CameraAccessException {
if (explicitCameraId != null) {
return explicitCameraId;
}
@@ -70,8 +73,22 @@ public class CameraCapture extends SurfaceCapture {
CameraManager cameraManager = ServiceManager.getCameraManager();
String[] cameraIds = cameraManager.getCameraIdList();
// Use the first one
return cameraIds.length > 0 ? cameraIds[0] : null;
if (cameraFacing == null) {
// Use the first one
return cameraIds.length > 0 ? cameraIds[0] : null;
}
for (String cameraId : cameraIds) {
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
int facing = characteristics.get(CameraCharacteristics.LENS_FACING);
if (cameraFacing.value() == facing) {
return cameraId;
}
}
// Not found
return null;
}
@Override

View File

@@ -0,0 +1,33 @@
package com.genymobile.scrcpy;
import android.annotation.SuppressLint;
import android.hardware.camera2.CameraCharacteristics;
public enum CameraFacing {
FRONT("front", CameraCharacteristics.LENS_FACING_FRONT),
BACK("back", CameraCharacteristics.LENS_FACING_BACK),
@SuppressLint("InlinedApi") // introduced in API 23
EXTERNAL("external", CameraCharacteristics.LENS_FACING_EXTERNAL);
private final String name;
private final int value;
CameraFacing(String name, int value) {
this.name = name;
this.value = value;
}
int value() {
return value;
}
static CameraFacing findByName(String name) {
for (CameraFacing facing : CameraFacing.values()) {
if (name.equals(facing.name)) {
return facing;
}
}
return null;
}
}

View File

@@ -26,6 +26,7 @@ public class Options {
private int displayId;
private String cameraId;
private Size cameraSize;
private CameraFacing cameraFacing;
private boolean showTouches;
private boolean stayAwake;
private List<CodecOption> videoCodecOptions;
@@ -126,6 +127,10 @@ public class Options {
return cameraSize;
}
public CameraFacing getCameraFacing() {
return cameraFacing;
}
public boolean getShowTouches() {
return showTouches;
}
@@ -360,6 +365,15 @@ public class Options {
options.cameraSize = parseSize(value);
}
break;
case "camera_facing":
if (!value.isEmpty()) {
CameraFacing facing = CameraFacing.findByName(value);
if (facing == null) {
throw new IllegalArgumentException("Camera facing " + value + " not supported");
}
options.cameraFacing = facing;
}
break;
case "send_device_meta":
options.sendDeviceMeta = Boolean.parseBoolean(value);
break;

View File

@@ -137,7 +137,7 @@ public final class Server {
if (options.getVideoSource() == VideoSource.DISPLAY) {
surfaceCapture = new ScreenCapture(device);
} else {
surfaceCapture = new CameraCapture(options.getCameraId(), options.getCameraSize());
surfaceCapture = new CameraCapture(options.getCameraId(), options.getCameraFacing(), options.getCameraSize());
}
SurfaceEncoder surfaceEncoder = new SurfaceEncoder(surfaceCapture, videoStreamer, options.getVideoBitRate(), options.getMaxFps(),
options.getVideoCodecOptions(), options.getVideoEncoder(), options.getDownsizeOnError());