mirror of
https://github.com/Genymobile/scrcpy.git
synced 2025-04-20 19:45:00 +00:00
add display id param
This commit is contained in:
parent
f903cd376d
commit
dfef5a0cb5
12 changed files with 67 additions and 18 deletions
|
@ -297,6 +297,18 @@ parse_port(const char *s, uint16_t *port) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_display_id(const char *s, uint16_t *display_id) {
|
||||
long value;
|
||||
bool ok = parse_integer_arg(s, &value, false, 0, 0xFFFF, "display id");
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*display_id = (uint16_t) value;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_record_format(const char *optarg, enum recorder_format *format) {
|
||||
if (!strcmp(optarg, "mp4")) {
|
||||
|
@ -369,8 +381,8 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
|
|||
{"window-y", required_argument, NULL, OPT_WINDOW_Y},
|
||||
{"window-width", required_argument, NULL, OPT_WINDOW_WIDTH},
|
||||
{"window-height", required_argument, NULL, OPT_WINDOW_HEIGHT},
|
||||
{"window-borderless", no_argument, NULL,
|
||||
OPT_WINDOW_BORDERLESS},
|
||||
{"window-borderless", no_argument, NULL, OPT_WINDOW_BORDERLESS},
|
||||
{"display", required_argument, NULL, 'd'},
|
||||
{NULL, 0, NULL, 0 },
|
||||
};
|
||||
|
||||
|
@ -379,7 +391,7 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
|
|||
optind = 0; // reset to start from the first argument in tests
|
||||
|
||||
int c;
|
||||
while ((c = getopt_long(argc, argv, "b:c:fF:hm:nNp:r:s:StTv", long_options,
|
||||
while ((c = getopt_long(argc, argv, "b:c:fF:hm:nNpd:r:s:StTv", long_options,
|
||||
NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'b':
|
||||
|
@ -428,6 +440,11 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
|
|||
return false;
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
if (!parse_display_id(optarg, &opts->display_id)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
opts->record_filename = optarg;
|
||||
break;
|
||||
|
|
|
@ -285,6 +285,7 @@ scrcpy(const struct scrcpy_options *options) {
|
|||
.bit_rate = options->bit_rate,
|
||||
.max_fps = options->max_fps,
|
||||
.control = options->control,
|
||||
.display_id = options->display_id,
|
||||
};
|
||||
if (!server_start(&server, options->serial, ¶ms)) {
|
||||
return false;
|
||||
|
|
|
@ -23,6 +23,7 @@ struct scrcpy_options {
|
|||
int16_t window_y;
|
||||
uint16_t window_width;
|
||||
uint16_t window_height;
|
||||
uint16_t display_id;
|
||||
bool show_touches;
|
||||
bool fullscreen;
|
||||
bool always_on_top;
|
||||
|
@ -49,6 +50,7 @@ struct scrcpy_options {
|
|||
.window_y = -1, \
|
||||
.window_width = 0, \
|
||||
.window_height = 0, \
|
||||
.display_id = 0, \
|
||||
.show_touches = false, \
|
||||
.fullscreen = false, \
|
||||
.always_on_top = false, \
|
||||
|
|
|
@ -124,9 +124,11 @@ execute_server(struct server *server, const struct server_params *params) {
|
|||
char max_size_string[6];
|
||||
char bit_rate_string[11];
|
||||
char max_fps_string[6];
|
||||
char display_id_string[6];
|
||||
sprintf(max_size_string, "%"PRIu16, params->max_size);
|
||||
sprintf(bit_rate_string, "%"PRIu32, params->bit_rate);
|
||||
sprintf(max_fps_string, "%"PRIu16, params->max_fps);
|
||||
sprintf(display_id_string, "%"PRIu16, params->display_id);
|
||||
const char *const cmd[] = {
|
||||
"shell",
|
||||
"CLASSPATH=" DEVICE_SERVER_PATH,
|
||||
|
@ -146,6 +148,7 @@ execute_server(struct server *server, const struct server_params *params) {
|
|||
params->crop ? params->crop : "-",
|
||||
"true", // always send frame meta (packet boundaries + timestamp)
|
||||
params->control ? "true" : "false",
|
||||
display_id_string,
|
||||
};
|
||||
#ifdef SERVER_DEBUGGER
|
||||
LOGI("Server debugger waiting for a client on device port "
|
||||
|
|
|
@ -37,6 +37,7 @@ struct server_params {
|
|||
uint32_t bit_rate;
|
||||
uint16_t max_fps;
|
||||
bool control;
|
||||
uint16_t display_id;
|
||||
};
|
||||
|
||||
// init default values
|
||||
|
|
|
@ -26,7 +26,7 @@ public final class Device {
|
|||
private RotationListener rotationListener;
|
||||
|
||||
public Device(Options options) {
|
||||
screenInfo = computeScreenInfo(options.getCrop(), options.getMaxSize());
|
||||
screenInfo = computeScreenInfo(options.getCrop(), options.getMaxSize(), options.getDisplayId());
|
||||
registerRotationWatcher(new IRotationWatcher.Stub() {
|
||||
@Override
|
||||
public void onRotationChanged(int rotation) throws RemoteException {
|
||||
|
@ -46,8 +46,8 @@ public final class Device {
|
|||
return screenInfo;
|
||||
}
|
||||
|
||||
private ScreenInfo computeScreenInfo(Rect crop, int maxSize) {
|
||||
DisplayInfo displayInfo = serviceManager.getDisplayManager().getDisplayInfo();
|
||||
private ScreenInfo computeScreenInfo(Rect crop, int maxSize, int displayId) {
|
||||
DisplayInfo displayInfo = serviceManager.getDisplayManager().getDisplayInfo(displayId);
|
||||
boolean rotated = (displayInfo.getRotation() & 1) != 0;
|
||||
Size deviceSize = displayInfo.getSize();
|
||||
Rect contentRect = new Rect(0, 0, deviceSize.getWidth(), deviceSize.getHeight());
|
||||
|
@ -64,7 +64,7 @@ public final class Device {
|
|||
}
|
||||
|
||||
Size videoSize = computeVideoSize(contentRect.width(), contentRect.height(), maxSize);
|
||||
return new ScreenInfo(contentRect, videoSize, rotated);
|
||||
return new ScreenInfo(contentRect, videoSize, rotated, displayInfo.getLayerStack());
|
||||
}
|
||||
|
||||
private static String formatCrop(Rect rect) {
|
||||
|
|
|
@ -3,10 +3,12 @@ package com.genymobile.scrcpy;
|
|||
public final class DisplayInfo {
|
||||
private final Size size;
|
||||
private final int rotation;
|
||||
private final int layerStack;
|
||||
|
||||
public DisplayInfo(Size size, int rotation) {
|
||||
public DisplayInfo(Size size, int rotation, int layerStack) {
|
||||
this.size = size;
|
||||
this.rotation = rotation;
|
||||
this.layerStack = layerStack;
|
||||
}
|
||||
|
||||
public Size getSize() {
|
||||
|
@ -16,5 +18,9 @@ public final class DisplayInfo {
|
|||
public int getRotation() {
|
||||
return rotation;
|
||||
}
|
||||
|
||||
public int getLayerStack() {
|
||||
return layerStack;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ public class Options {
|
|||
private Rect crop;
|
||||
private boolean sendFrameMeta; // send PTS so that the client may record properly
|
||||
private boolean control;
|
||||
private int displayId;
|
||||
|
||||
public int getMaxSize() {
|
||||
return maxSize;
|
||||
|
@ -66,4 +67,12 @@ public class Options {
|
|||
public void setControl(boolean control) {
|
||||
this.control = control;
|
||||
}
|
||||
|
||||
public int getDisplayId() {
|
||||
return displayId;
|
||||
}
|
||||
|
||||
public void setDisplayId(int displayId) {
|
||||
this.displayId = displayId;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ public class ScreenEncoder implements Device.RotationListener {
|
|||
setSize(format, videoRect.width(), videoRect.height());
|
||||
configure(codec, format);
|
||||
Surface surface = codec.createInputSurface();
|
||||
setDisplaySurface(display, surface, contentRect, videoRect);
|
||||
setDisplaySurface(display, surface, contentRect, videoRect, device.getScreenInfo().getLayerStack());
|
||||
codec.start();
|
||||
try {
|
||||
alive = encode(codec, fd);
|
||||
|
@ -172,12 +172,12 @@ public class ScreenEncoder implements Device.RotationListener {
|
|||
format.setInteger(MediaFormat.KEY_HEIGHT, height);
|
||||
}
|
||||
|
||||
private static void setDisplaySurface(IBinder display, Surface surface, Rect deviceRect, Rect displayRect) {
|
||||
private static void setDisplaySurface(IBinder display, Surface surface, Rect deviceRect, Rect displayRect, int layerStack) {
|
||||
SurfaceControl.openTransaction();
|
||||
try {
|
||||
SurfaceControl.setDisplaySurface(display, surface);
|
||||
SurfaceControl.setDisplayProjection(display, 0, deviceRect, displayRect);
|
||||
SurfaceControl.setDisplayLayerStack(display, 0);
|
||||
SurfaceControl.setDisplayLayerStack(display, layerStack);
|
||||
} finally {
|
||||
SurfaceControl.closeTransaction();
|
||||
}
|
||||
|
|
|
@ -6,11 +6,13 @@ public final class ScreenInfo {
|
|||
private final Rect contentRect; // device size, possibly cropped
|
||||
private final Size videoSize;
|
||||
private final boolean rotated;
|
||||
private final int layerStack;
|
||||
|
||||
public ScreenInfo(Rect contentRect, Size videoSize, boolean rotated) {
|
||||
public ScreenInfo(Rect contentRect, Size videoSize, boolean rotated, int layerStack) {
|
||||
this.contentRect = contentRect;
|
||||
this.videoSize = videoSize;
|
||||
this.rotated = rotated;
|
||||
this.layerStack = layerStack;
|
||||
}
|
||||
|
||||
public Rect getContentRect() {
|
||||
|
@ -26,6 +28,10 @@ public final class ScreenInfo {
|
|||
if (rotated == newRotated) {
|
||||
return this;
|
||||
}
|
||||
return new ScreenInfo(Device.flipRect(contentRect), videoSize.rotate(), newRotated);
|
||||
return new ScreenInfo(Device.flipRect(contentRect), videoSize.rotate(), newRotated, layerStack);
|
||||
}
|
||||
|
||||
public int getLayerStack(){
|
||||
return layerStack;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,8 +79,8 @@ public final class Server {
|
|||
"The server version (" + clientVersion + ") does not match the client " + "(" + BuildConfig.VERSION_NAME + ")");
|
||||
}
|
||||
|
||||
if (args.length != 8) {
|
||||
throw new IllegalArgumentException("Expecting 8 parameters");
|
||||
if (args.length != 9) {
|
||||
throw new IllegalArgumentException("Expecting 9 parameters");
|
||||
}
|
||||
|
||||
Options options = new Options();
|
||||
|
@ -107,6 +107,9 @@ public final class Server {
|
|||
boolean control = Boolean.parseBoolean(args[7]);
|
||||
options.setControl(control);
|
||||
|
||||
int displayId = Integer.parseInt(args[8]);
|
||||
options.setDisplayId(displayId);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,15 +12,16 @@ public final class DisplayManager {
|
|||
this.manager = manager;
|
||||
}
|
||||
|
||||
public DisplayInfo getDisplayInfo() {
|
||||
public DisplayInfo getDisplayInfo(int displayId) {
|
||||
try {
|
||||
Object displayInfo = manager.getClass().getMethod("getDisplayInfo", int.class).invoke(manager, 0);
|
||||
Object displayInfo = manager.getClass().getMethod("getDisplayInfo", int.class).invoke(manager, displayId);
|
||||
Class<?> cls = displayInfo.getClass();
|
||||
// width and height already take the rotation into account
|
||||
int width = cls.getDeclaredField("logicalWidth").getInt(displayInfo);
|
||||
int height = cls.getDeclaredField("logicalHeight").getInt(displayInfo);
|
||||
int rotation = cls.getDeclaredField("rotation").getInt(displayInfo);
|
||||
return new DisplayInfo(new Size(width, height), rotation);
|
||||
int layerStack = cls.getDeclaredField("layerStack").getInt(displayInfo);
|
||||
return new DisplayInfo(new Size(width, height), rotation, layerStack);
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue