Add --list-cameras

Add an option to list the device cameras.

Co-authored-by: Romain Vimont <rom@rom1v.com>
This commit is contained in:
Simon Chan
2023-07-16 17:07:19 +08:00
committed by Romain Vimont
parent 8c96ab130e
commit 5406c93283
11 changed files with 103 additions and 4 deletions

View File

@@ -3,6 +3,13 @@ package com.genymobile.scrcpy;
import com.genymobile.scrcpy.wrappers.DisplayManager;
import com.genymobile.scrcpy.wrappers.ServiceManager;
import android.graphics.Rect;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.MediaCodec;
import java.util.List;
public final class LogUtils {
@@ -60,4 +67,42 @@ public final class LogUtils {
}
return builder.toString();
}
private static String getCameraFacingName(int facing) {
switch (facing) {
case CameraCharacteristics.LENS_FACING_FRONT:
return "front";
case CameraCharacteristics.LENS_FACING_BACK:
return "back";
case CameraCharacteristics.LENS_FACING_EXTERNAL:
return "external";
default:
return "unknown";
}
}
public static String buildCameraListMessage() {
StringBuilder builder = new StringBuilder("List of cameras:");
CameraManager cameraManager = ServiceManager.getCameraManager();
try {
String[] cameraIds = cameraManager.getCameraIdList();
if (cameraIds == null || cameraIds.length == 0) {
builder.append("\n (none)");
} else {
for (String id : cameraIds) {
builder.append("\n --video-source=camera --camera-id=").append(id);
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(id);
int facing = characteristics.get(CameraCharacteristics.LENS_FACING);
builder.append(" (").append(getCameraFacingName(facing)).append(", ");
Rect activeSize = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
builder.append(activeSize.width()).append("x").append(activeSize.height());
builder.append(')');
}
}
} catch (CameraAccessException e) {
builder.append("\n (access denied)");
}
return builder.toString();
}
}

View File

@@ -38,6 +38,7 @@ public class Options {
private boolean listEncoders;
private boolean listDisplays;
private boolean listCameras;
// Options not used by the scrcpy client, but useful to use scrcpy-server directly
private boolean sendDeviceMeta = true; // send device name and size
@@ -154,7 +155,7 @@ public class Options {
}
public boolean getList() {
return listEncoders || listDisplays;
return listEncoders || listDisplays || listCameras;
}
public boolean getListEncoders() {
@@ -165,6 +166,10 @@ public class Options {
return listDisplays;
}
public boolean getListCameras() {
return listCameras;
}
public boolean getSendDeviceMeta() {
return sendDeviceMeta;
}
@@ -312,6 +317,9 @@ public class Options {
case "list_displays":
options.listDisplays = Boolean.parseBoolean(value);
break;
case "list_cameras":
options.listCameras = Boolean.parseBoolean(value);
break;
case "send_device_meta":
options.sendDeviceMeta = Boolean.parseBoolean(value);
break;

View File

@@ -2,6 +2,7 @@ package com.genymobile.scrcpy;
import android.os.BatteryManager;
import android.os.Build;
import android.os.Looper;
import java.io.IOException;
import java.util.ArrayList;
@@ -99,7 +100,8 @@ public final class Server {
boolean audio = options.getAudio();
boolean sendDummyByte = options.getSendDummyByte();
Workarounds.apply(audio);
boolean camera = true;
Workarounds.apply(audio, camera);
List<AsyncProcessor> asyncProcessors = new ArrayList<>();
@@ -192,6 +194,10 @@ public final class Server {
if (options.getListDisplays()) {
Ln.i(LogUtils.buildDisplayListMessage());
}
if (options.getListCameras()) {
Workarounds.apply(false, true);
Ln.i(LogUtils.buildCameraListMessage());
}
// Just print the requested data, do not mirror
return;
}

View File

@@ -28,14 +28,13 @@ public final class Workarounds {
// not instantiable
}
public static void apply(boolean audio) {
public static void apply(boolean audio, boolean camera) {
Workarounds.prepareMainLooper();
boolean mustFillAppInfo = false;
boolean mustFillBaseContext = false;
boolean mustFillAppContext = false;
if (Build.BRAND.equalsIgnoreCase("meizu")) {
// Workarounds must be applied for Meizu phones:
// - <https://github.com/Genymobile/scrcpy/issues/240>
@@ -65,6 +64,10 @@ public final class Workarounds {
mustFillAppContext = true;
}
if (camera) {
mustFillAppInfo = true;
}
if (mustFillAppInfo) {
Workarounds.fillAppInfo();
}

View File

@@ -1,9 +1,15 @@
package com.genymobile.scrcpy.wrappers;
import com.genymobile.scrcpy.FakeContext;
import com.genymobile.scrcpy.Workarounds;
import android.annotation.SuppressLint;
import android.content.Context;
import android.hardware.camera2.CameraManager;
import android.os.IBinder;
import android.os.IInterface;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -26,6 +32,7 @@ public final class ServiceManager {
private static StatusBarManager statusBarManager;
private static ClipboardManager clipboardManager;
private static ActivityManager activityManager;
private static CameraManager cameraManager;
private ServiceManager() {
/* not instantiable */
@@ -129,4 +136,16 @@ public final class ServiceManager {
return activityManager;
}
public static CameraManager getCameraManager() {
if (cameraManager == null) {
try {
Constructor<CameraManager> ctor = CameraManager.class.getDeclaredConstructor(Context.class);
cameraManager = ctor.newInstance(FakeContext.get());
} catch (Exception e) {
throw new AssertionError(e);
}
}
return cameraManager;
}
}