mirror of
https://github.com/Genymobile/scrcpy.git
synced 2025-12-17 05:24:19 +01:00
Add option to specify the camera zoom
Add --camera-zoom to specify the camera zoom. TODO ref 6243. Signed-off-by: Romain Vimont <rom@rom1v.com>
This commit is contained in:
@@ -19,6 +19,7 @@ _scrcpy() {
|
|||||||
--camera-high-speed
|
--camera-high-speed
|
||||||
--camera-size=
|
--camera-size=
|
||||||
--camera-torch
|
--camera-torch
|
||||||
|
--camera-zoom=
|
||||||
--capture-orientation=
|
--capture-orientation=
|
||||||
--crop=
|
--crop=
|
||||||
-d --select-usb
|
-d --select-usb
|
||||||
@@ -199,6 +200,7 @@ _scrcpy() {
|
|||||||
|--camera-fps \
|
|--camera-fps \
|
||||||
|--camera-size \
|
|--camera-size \
|
||||||
|--camera-torch \
|
|--camera-torch \
|
||||||
|
|--camera-zoom \
|
||||||
|--crop \
|
|--crop \
|
||||||
|--display-id \
|
|--display-id \
|
||||||
|--max-fps \
|
|--max-fps \
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ arguments=(
|
|||||||
'--camera-fps=[Specify the camera capture frame rate]'
|
'--camera-fps=[Specify the camera capture frame rate]'
|
||||||
'--camera-size=[Specify an explicit camera capture size]'
|
'--camera-size=[Specify an explicit camera capture size]'
|
||||||
'--camera-torch[Turn on the camera torch when the camera starts]'
|
'--camera-torch[Turn on the camera torch when the camera starts]'
|
||||||
|
'--camera-zoom[Specify the camera zoom initial value]'
|
||||||
'--capture-orientation=[Set the capture video orientation]:orientation:(0 90 180 270 flip0 flip90 flip180 flip270 @0 @90 @180 @270 @flip0 @flip90 @flip180 @flip270)'
|
'--capture-orientation=[Set the capture video orientation]:orientation:(0 90 180 270 flip0 flip90 flip180 flip270 @0 @90 @180 @270 @flip0 @flip90 @flip180 @flip270)'
|
||||||
'--crop=[\[width\:height\:x\:y\] Crop the device screen on the server]'
|
'--crop=[\[width\:height\:x\:y\] Crop the device screen on the server]'
|
||||||
{-d,--select-usb}'[Use USB device]'
|
{-d,--select-usb}'[Use USB device]'
|
||||||
|
|||||||
@@ -135,6 +135,10 @@ Specify an explicit camera capture size.
|
|||||||
.BI \-\-camera\-torch
|
.BI \-\-camera\-torch
|
||||||
Turn on the camera torch when the camera starts.
|
Turn on the camera torch when the camera starts.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "\-\-camera-zoom " zoom
|
||||||
|
Specify the camera zoom initial value.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI "\-\-capture\-orientation " value
|
.BI "\-\-capture\-orientation " value
|
||||||
Possible values are 0, 90, 180, 270, flip0, flip90, flip180 and flip270, possibly prefixed by '@'.
|
Possible values are 0, 90, 180, 270, flip0, flip90, flip180 and flip270, possibly prefixed by '@'.
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ enum {
|
|||||||
OPT_NO_VD_DESTROY_CONTENT,
|
OPT_NO_VD_DESTROY_CONTENT,
|
||||||
OPT_DISPLAY_IME_POLICY,
|
OPT_DISPLAY_IME_POLICY,
|
||||||
OPT_CAMERA_TORCH,
|
OPT_CAMERA_TORCH,
|
||||||
|
OPT_CAMERA_ZOOM,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sc_option {
|
struct sc_option {
|
||||||
@@ -319,6 +320,12 @@ static const struct sc_option options[] = {
|
|||||||
.longopt = "camera-torch",
|
.longopt = "camera-torch",
|
||||||
.text = "Turn on the camera torch when the camera starts.",
|
.text = "Turn on the camera torch when the camera starts.",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.longopt_id = OPT_CAMERA_ZOOM,
|
||||||
|
.longopt = "camera-zoom",
|
||||||
|
.argdesc = "zoom",
|
||||||
|
.text = "Specify the camera zoom initial value.",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.longopt_id = OPT_CAPTURE_ORIENTATION,
|
.longopt_id = OPT_CAPTURE_ORIENTATION,
|
||||||
.longopt = "capture-orientation",
|
.longopt = "capture-orientation",
|
||||||
@@ -2797,6 +2804,9 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
|||||||
case OPT_CAMERA_TORCH:
|
case OPT_CAMERA_TORCH:
|
||||||
opts->camera_torch = true;
|
opts->camera_torch = true;
|
||||||
break;
|
break;
|
||||||
|
case OPT_CAMERA_ZOOM:
|
||||||
|
opts->camera_zoom = optarg;
|
||||||
|
break;
|
||||||
case OPT_NO_WINDOW:
|
case OPT_NO_WINDOW:
|
||||||
opts->window = false;
|
opts->window = false;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ const struct scrcpy_options scrcpy_options_default = {
|
|||||||
.camera_id = NULL,
|
.camera_id = NULL,
|
||||||
.camera_size = NULL,
|
.camera_size = NULL,
|
||||||
.camera_ar = NULL,
|
.camera_ar = NULL,
|
||||||
|
.camera_zoom = NULL,
|
||||||
.camera_fps = 0,
|
.camera_fps = 0,
|
||||||
.log_level = SC_LOG_LEVEL_INFO,
|
.log_level = SC_LOG_LEVEL_INFO,
|
||||||
.video_codec = SC_CODEC_H264,
|
.video_codec = SC_CODEC_H264,
|
||||||
|
|||||||
@@ -241,6 +241,7 @@ struct scrcpy_options {
|
|||||||
const char *camera_id;
|
const char *camera_id;
|
||||||
const char *camera_size;
|
const char *camera_size;
|
||||||
const char *camera_ar;
|
const char *camera_ar;
|
||||||
|
const char *camera_zoom;
|
||||||
uint16_t camera_fps;
|
uint16_t camera_fps;
|
||||||
enum sc_log_level log_level;
|
enum sc_log_level log_level;
|
||||||
enum sc_codec video_codec;
|
enum sc_codec video_codec;
|
||||||
|
|||||||
@@ -470,6 +470,7 @@ scrcpy(struct scrcpy_options *options) {
|
|||||||
.kill_adb_on_close = options->kill_adb_on_close,
|
.kill_adb_on_close = options->kill_adb_on_close,
|
||||||
.camera_high_speed = options->camera_high_speed,
|
.camera_high_speed = options->camera_high_speed,
|
||||||
.camera_torch = options->camera_torch,
|
.camera_torch = options->camera_torch,
|
||||||
|
.camera_zoom = options->camera_zoom,
|
||||||
.vd_destroy_content = options->vd_destroy_content,
|
.vd_destroy_content = options->vd_destroy_content,
|
||||||
.vd_system_decorations = options->vd_system_decorations,
|
.vd_system_decorations = options->vd_system_decorations,
|
||||||
.list = options->list,
|
.list = options->list,
|
||||||
|
|||||||
@@ -360,6 +360,10 @@ execute_server(struct sc_server *server,
|
|||||||
if (params->camera_torch) {
|
if (params->camera_torch) {
|
||||||
ADD_PARAM("camera_torch=true");
|
ADD_PARAM("camera_torch=true");
|
||||||
}
|
}
|
||||||
|
if (params->camera_zoom) {
|
||||||
|
VALIDATE_STRING(params->camera_zoom);
|
||||||
|
ADD_PARAM("camera_zoom=%s", params->camera_zoom);
|
||||||
|
}
|
||||||
if (params->show_touches) {
|
if (params->show_touches) {
|
||||||
ADD_PARAM("show_touches=true");
|
ADD_PARAM("show_touches=true");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ struct sc_server_params {
|
|||||||
const char *camera_id;
|
const char *camera_id;
|
||||||
const char *camera_size;
|
const char *camera_size;
|
||||||
const char *camera_ar;
|
const char *camera_ar;
|
||||||
|
const char *camera_zoom;
|
||||||
uint16_t camera_fps;
|
uint16_t camera_fps;
|
||||||
struct sc_port_range port_range;
|
struct sc_port_range port_range;
|
||||||
uint32_t tunnel_host;
|
uint32_t tunnel_host;
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ public class Options {
|
|||||||
private Size cameraSize;
|
private Size cameraSize;
|
||||||
private CameraFacing cameraFacing;
|
private CameraFacing cameraFacing;
|
||||||
private CameraAspectRatio cameraAspectRatio;
|
private CameraAspectRatio cameraAspectRatio;
|
||||||
|
private float cameraZoom = 1;
|
||||||
private int cameraFps;
|
private int cameraFps;
|
||||||
private boolean cameraHighSpeed;
|
private boolean cameraHighSpeed;
|
||||||
private boolean cameraTorch;
|
private boolean cameraTorch;
|
||||||
@@ -169,6 +170,10 @@ public class Options {
|
|||||||
return cameraAspectRatio;
|
return cameraAspectRatio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float getCameraZoom() {
|
||||||
|
return cameraZoom;
|
||||||
|
}
|
||||||
|
|
||||||
public int getCameraFps() {
|
public int getCameraFps() {
|
||||||
return cameraFps;
|
return cameraFps;
|
||||||
}
|
}
|
||||||
@@ -473,6 +478,11 @@ public class Options {
|
|||||||
options.cameraAspectRatio = parseCameraAspectRatio(value);
|
options.cameraAspectRatio = parseCameraAspectRatio(value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "camera_zoom":
|
||||||
|
if (!value.isEmpty()) {
|
||||||
|
options.cameraZoom = Float.parseFloat(value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case "camera_fps":
|
case "camera_fps":
|
||||||
options.cameraFps = Integer.parseInt(value);
|
options.cameraFps = Integer.parseInt(value);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import android.media.MediaCodecList;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.util.Range;
|
import android.util.Range;
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@@ -172,6 +173,18 @@ public final class LogUtils {
|
|||||||
Ln.w("Could not get available frame rates for camera " + id, e);
|
Ln.w("Could not get available frame rates for camera " + id, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= AndroidVersions.API_30_ANDROID_11) {
|
||||||
|
try {
|
||||||
|
Range<Float> zoomRange = characteristics.get(CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE);
|
||||||
|
if (zoomRange != null) {
|
||||||
|
String zoom = getFormattedZoomRange(zoomRange);
|
||||||
|
builder.append(", zoom-range=").append(zoom);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Ln.w("Could not get available zoom ranges for camera " + id, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
builder.append(')');
|
builder.append(')');
|
||||||
|
|
||||||
if (includeSizes) {
|
if (includeSizes) {
|
||||||
@@ -226,6 +239,11 @@ public final class LogUtils {
|
|||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String getFormattedZoomRange(Range<Float> range) {
|
||||||
|
DecimalFormat format = new DecimalFormat("#.##");
|
||||||
|
return "[" + format.format(range.getLower()) + ", " + format.format(range.getUpper()) + "]";
|
||||||
|
}
|
||||||
|
|
||||||
public static String buildAppListMessage() {
|
public static String buildAppListMessage() {
|
||||||
List<DeviceApp> apps = Device.listApps();
|
List<DeviceApp> apps = Device.listApps();
|
||||||
return buildAppListMessage("List of apps:", apps);
|
return buildAppListMessage("List of apps:", apps);
|
||||||
|
|||||||
@@ -65,10 +65,12 @@ public class CameraCapture extends SurfaceCapture {
|
|||||||
private final Orientation captureOrientation;
|
private final Orientation captureOrientation;
|
||||||
private final float angle;
|
private final float angle;
|
||||||
private final boolean initialTorch;
|
private final boolean initialTorch;
|
||||||
|
private float zoom;
|
||||||
|
|
||||||
private String cameraId;
|
private String cameraId;
|
||||||
private Size captureSize;
|
private Size captureSize;
|
||||||
private Size videoSize; // after OpenGL transforms
|
private Size videoSize; // after OpenGL transforms
|
||||||
|
private Range<Float> zoomRange;
|
||||||
|
|
||||||
private AffineMatrix transform;
|
private AffineMatrix transform;
|
||||||
private OpenGLRunner glRunner;
|
private OpenGLRunner glRunner;
|
||||||
@@ -98,6 +100,7 @@ public class CameraCapture extends SurfaceCapture {
|
|||||||
assert captureOrientation != null;
|
assert captureOrientation != null;
|
||||||
this.angle = options.getAngle();
|
this.angle = options.getAngle();
|
||||||
this.initialTorch = options.getCameraTorch();
|
this.initialTorch = options.getCameraTorch();
|
||||||
|
this.zoom = options.getCameraZoom();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -288,6 +291,14 @@ public class CameraCapture extends SurfaceCapture {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CameraManager cameraManager = ServiceManager.getCameraManager();
|
||||||
|
try {
|
||||||
|
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
|
||||||
|
zoomRange = characteristics.get(CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE);
|
||||||
|
} catch (CameraAccessException e) {
|
||||||
|
Ln.w("Could not get camera characteristics");
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
requestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
|
requestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
|
||||||
requestBuilder.addTarget(captureSurface);
|
requestBuilder.addTarget(captureSurface);
|
||||||
@@ -299,6 +310,11 @@ public class CameraCapture extends SurfaceCapture {
|
|||||||
Ln.i("Turn camera torch on");
|
Ln.i("Turn camera torch on");
|
||||||
requestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
|
requestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
|
||||||
}
|
}
|
||||||
|
if (zoom != 1) {
|
||||||
|
zoom = clampZoom(zoom);
|
||||||
|
Ln.i("Set camera zoom: " + zoom);
|
||||||
|
requestBuilder.set(CaptureRequest.CONTROL_ZOOM_RATIO, zoom);
|
||||||
|
}
|
||||||
|
|
||||||
CaptureRequest request = requestBuilder.build();
|
CaptureRequest request = requestBuilder.build();
|
||||||
setRepeatingRequest(session, request);
|
setRepeatingRequest(session, request);
|
||||||
@@ -456,6 +472,15 @@ public class CameraCapture extends SurfaceCapture {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private float clampZoom(float value) {
|
||||||
|
assertCameraThread();
|
||||||
|
if (zoomRange == null) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return zoomRange.clamp(value);
|
||||||
|
}
|
||||||
|
|
||||||
private void assertCameraThread() {
|
private void assertCameraThread() {
|
||||||
assert Thread.currentThread() == cameraThread;
|
assert Thread.currentThread() == cameraThread;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user