Add --camera-fps
Add a new option for specifying the camera frame rate. By default, Android's default frame rate (30 fps) is used. Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
This commit is contained in:
parent
04ef1c1e9d
commit
8db995aaee
@ -13,6 +13,7 @@ _scrcpy() {
|
||||
--camera-ar=
|
||||
--camera-id=
|
||||
--camera-facing=
|
||||
--camera-fps=
|
||||
--camera-size=
|
||||
--crop=
|
||||
-d --select-usb
|
||||
@ -156,6 +157,7 @@ _scrcpy() {
|
||||
|--audio-output-buffer \
|
||||
|--camera-ar \
|
||||
|--camera-id \
|
||||
|--camera-fps \
|
||||
|--camera-size \
|
||||
|--crop \
|
||||
|--display-id \
|
||||
|
@ -20,6 +20,7 @@ arguments=(
|
||||
'--camera-ar=[Select the camera size by its aspect ratio]'
|
||||
'--camera-id=[Specify the camera id to mirror]'
|
||||
'--camera-facing=[Select the device camera by its facing direction]:facing:(front back external)'
|
||||
'--camera-fps=[Specify the camera capture frame rate]'
|
||||
'--camera-size=[Specify an explicit camera capture size]'
|
||||
'--crop=[\[width\:height\:x\:y\] Crop the device screen on the server]'
|
||||
{-d,--select-usb}'[Use USB device]'
|
||||
|
@ -93,6 +93,12 @@ Select the device camera by its facing direction.
|
||||
|
||||
Possible values are "front", "back" and "external".
|
||||
|
||||
.TP
|
||||
.BI "\-\-camera\-fps " fps
|
||||
Specify the camera capture frame rate.
|
||||
|
||||
If not specified, Android's default frame rate (30 fps) is used.
|
||||
|
||||
.TP
|
||||
.BI "\-\-camera\-size " width\fRx\fIheight
|
||||
Specify an explicit camera capture size.
|
||||
|
@ -88,6 +88,7 @@ enum {
|
||||
OPT_CAMERA_SIZE,
|
||||
OPT_CAMERA_FACING,
|
||||
OPT_CAMERA_AR,
|
||||
OPT_CAMERA_FPS,
|
||||
};
|
||||
|
||||
struct sc_option {
|
||||
@ -234,6 +235,14 @@ static const struct sc_option options[] = {
|
||||
.argdesc = "<width>x<height>",
|
||||
.text = "Specify an explicit camera capture size.",
|
||||
},
|
||||
{
|
||||
.longopt_id = OPT_CAMERA_FPS,
|
||||
.longopt = "camera-fps",
|
||||
.argdesc = "value",
|
||||
.text = "Specify the camera capture frame rate.\n"
|
||||
"If not specified, Android's default frame rate (30 fps) is "
|
||||
"used.",
|
||||
},
|
||||
{
|
||||
// Not really deprecated (--codec has never been released), but without
|
||||
// declaring an explicit --codec option, getopt_long() partial matching
|
||||
@ -1746,6 +1755,18 @@ parse_camera_facing(const char *optarg, enum sc_camera_facing *facing) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_camera_fps(const char *s, uint16_t *camera_fps) {
|
||||
long value;
|
||||
bool ok = parse_integer_arg(s, &value, false, 0, 0xFFFF, "camera fps");
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*camera_fps = (uint16_t) value;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_time_limit(const char *s, sc_tick *tick) {
|
||||
long value;
|
||||
@ -2154,6 +2175,11 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case OPT_CAMERA_FPS:
|
||||
if (!parse_camera_fps(optarg, &opts->camera_fps)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// getopt prints the error message on stderr
|
||||
return false;
|
||||
|
@ -14,6 +14,7 @@ const struct scrcpy_options scrcpy_options_default = {
|
||||
.camera_id = NULL,
|
||||
.camera_size = NULL,
|
||||
.camera_ar = NULL,
|
||||
.camera_fps = 0,
|
||||
.log_level = SC_LOG_LEVEL_INFO,
|
||||
.video_codec = SC_CODEC_H264,
|
||||
.audio_codec = SC_CODEC_OPUS,
|
||||
|
@ -133,6 +133,7 @@ struct scrcpy_options {
|
||||
const char *camera_id;
|
||||
const char *camera_size;
|
||||
const char *camera_ar;
|
||||
uint16_t camera_fps;
|
||||
enum sc_log_level log_level;
|
||||
enum sc_codec video_codec;
|
||||
enum sc_codec audio_codec;
|
||||
|
@ -376,6 +376,7 @@ scrcpy(struct scrcpy_options *options) {
|
||||
.camera_id = options->camera_id,
|
||||
.camera_size = options->camera_size,
|
||||
.camera_ar = options->camera_ar,
|
||||
.camera_fps = options->camera_fps,
|
||||
.force_adb_forward = options->force_adb_forward,
|
||||
.power_off_on_close = options->power_off_on_close,
|
||||
.clipboard_autosync = options->clipboard_autosync,
|
||||
|
@ -308,6 +308,9 @@ execute_server(struct sc_server *server,
|
||||
if (params->camera_ar) {
|
||||
ADD_PARAM("camera_ar=%s", params->camera_ar);
|
||||
}
|
||||
if (params->camera_fps) {
|
||||
ADD_PARAM("camera_fps=%" PRIu16, params->camera_fps);
|
||||
}
|
||||
if (params->show_touches) {
|
||||
ADD_PARAM("show_touches=true");
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ struct sc_server_params {
|
||||
const char *camera_id;
|
||||
const char *camera_size;
|
||||
const char *camera_ar;
|
||||
uint16_t camera_fps;
|
||||
struct sc_port_range port_range;
|
||||
uint32_t tunnel_host;
|
||||
uint16_t tunnel_port;
|
||||
|
@ -19,6 +19,7 @@ import android.media.MediaCodec;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.util.Range;
|
||||
import android.view.Surface;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -38,6 +39,7 @@ public class CameraCapture extends SurfaceCapture {
|
||||
private final Size explicitSize;
|
||||
private int maxSize;
|
||||
private final CameraAspectRatio aspectRatio;
|
||||
private final int fps;
|
||||
|
||||
private String cameraId;
|
||||
private Size size;
|
||||
@ -49,12 +51,13 @@ public class CameraCapture extends SurfaceCapture {
|
||||
|
||||
private final AtomicBoolean disconnected = new AtomicBoolean();
|
||||
|
||||
public CameraCapture(String explicitCameraId, CameraFacing cameraFacing, Size explicitSize, int maxSize, CameraAspectRatio aspectRatio) {
|
||||
public CameraCapture(String explicitCameraId, CameraFacing cameraFacing, Size explicitSize, int maxSize, CameraAspectRatio aspectRatio, int fps) {
|
||||
this.explicitCameraId = explicitCameraId;
|
||||
this.cameraFacing = cameraFacing;
|
||||
this.explicitSize = explicitSize;
|
||||
this.maxSize = maxSize;
|
||||
this.aspectRatio = aspectRatio;
|
||||
this.fps = fps;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -301,6 +304,11 @@ public class CameraCapture extends SurfaceCapture {
|
||||
private CaptureRequest createCaptureRequest(Surface surface) throws CameraAccessException {
|
||||
CaptureRequest.Builder requestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
|
||||
requestBuilder.addTarget(surface);
|
||||
|
||||
if (fps > 0) {
|
||||
requestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, new Range<>(fps, fps));
|
||||
}
|
||||
|
||||
return requestBuilder.build();
|
||||
}
|
||||
|
||||
|
@ -9,8 +9,10 @@ import android.hardware.camera2.CameraCharacteristics;
|
||||
import android.hardware.camera2.CameraManager;
|
||||
import android.hardware.camera2.params.StreamConfigurationMap;
|
||||
import android.media.MediaCodec;
|
||||
import android.util.Range;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
|
||||
public final class LogUtils {
|
||||
|
||||
@ -97,7 +99,15 @@ public final class LogUtils {
|
||||
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()).append(')');
|
||||
builder.append(activeSize.width()).append("x").append(activeSize.height()).append(", ");
|
||||
|
||||
// Capture frame rates for low-FPS mode are the same for every resolution
|
||||
Range<Integer>[] lowFpsRanges = characteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
|
||||
TreeSet<Integer> uniqueLowFps = new TreeSet<>();
|
||||
for (Range<Integer> range : lowFpsRanges) {
|
||||
uniqueLowFps.add(range.getUpper());
|
||||
}
|
||||
builder.append("fps=").append(uniqueLowFps).append(')');
|
||||
|
||||
if (includeSizes) {
|
||||
StreamConfigurationMap configs = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
|
||||
|
@ -28,6 +28,7 @@ public class Options {
|
||||
private Size cameraSize;
|
||||
private CameraFacing cameraFacing;
|
||||
private CameraAspectRatio cameraAspectRatio;
|
||||
private int cameraFps;
|
||||
private boolean showTouches;
|
||||
private boolean stayAwake;
|
||||
private List<CodecOption> videoCodecOptions;
|
||||
@ -136,6 +137,10 @@ public class Options {
|
||||
return cameraAspectRatio;
|
||||
}
|
||||
|
||||
public int getCameraFps() {
|
||||
return cameraFps;
|
||||
}
|
||||
|
||||
public boolean getShowTouches() {
|
||||
return showTouches;
|
||||
}
|
||||
@ -384,6 +389,9 @@ public class Options {
|
||||
options.cameraAspectRatio = parseCameraAspectRatio(value);
|
||||
}
|
||||
break;
|
||||
case "camera_fps":
|
||||
options.cameraFps = Integer.parseInt(value);
|
||||
break;
|
||||
case "send_device_meta":
|
||||
options.sendDeviceMeta = Boolean.parseBoolean(value);
|
||||
break;
|
||||
|
@ -144,7 +144,7 @@ public final class Server {
|
||||
surfaceCapture = new ScreenCapture(device);
|
||||
} else {
|
||||
surfaceCapture = new CameraCapture(options.getCameraId(), options.getCameraFacing(), options.getCameraSize(),
|
||||
options.getMaxSize(), options.getCameraAspectRatio());
|
||||
options.getMaxSize(), options.getCameraAspectRatio(), options.getCameraFps());
|
||||
}
|
||||
SurfaceEncoder surfaceEncoder = new SurfaceEncoder(surfaceCapture, videoStreamer, options.getVideoBitRate(), options.getMaxFps(),
|
||||
options.getVideoCodecOptions(), options.getVideoEncoder(), options.getDownsizeOnError());
|
||||
|
Loading…
x
Reference in New Issue
Block a user