Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added display-id option to mirror displays that are not displayId=0 #1223

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions app/src/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ scrcpy_print_usage(const char *arg0) {
" -h, --help\n"
" Print this help.\n"
"\n"
" --display-id value\n"
" Specifies the Android display to mirror\n"
" Default is 0\n"
"\n"
" --max-fps value\n"
" Limit the frame rate of screen capture (only supported on\n"
" devices with Android >= 10).\n"
Expand Down Expand Up @@ -259,6 +263,18 @@ parse_max_fps(const char *s, uint16_t *max_fps) {
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, 1000, "display id");
if (!ok) {
return false;
}

*display_id = (uint16_t) value;
return true;
}

static bool
parse_window_position(const char *s, int16_t *position) {
long value;
Expand Down Expand Up @@ -340,6 +356,7 @@ guess_record_format(const char *filename) {
#define OPT_WINDOW_HEIGHT 1010
#define OPT_WINDOW_BORDERLESS 1011
#define OPT_MAX_FPS 1012
#define OPT_DISPLAY_ID 1013

bool
scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
Expand All @@ -350,6 +367,7 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
{"fullscreen", no_argument, NULL, 'f'},
{"help", no_argument, NULL, 'h'},
{"max-fps", required_argument, NULL, OPT_MAX_FPS},
{"display-id", required_argument, NULL, OPT_DISPLAY_ID},
{"max-size", required_argument, NULL, 'm'},
{"no-control", no_argument, NULL, 'n'},
{"no-display", no_argument, NULL, 'N'},
Expand Down Expand Up @@ -412,6 +430,11 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
return false;
}
break;
case OPT_DISPLAY_ID:
if (!parse_display_id(optarg, &opts->display_id)) {
return false;
}
break;
case 'm':
if (!parse_max_size(optarg, &opts->max_size)) {
return false;
Expand Down
1 change: 1 addition & 0 deletions app/src/scrcpy.c
Original file line number Diff line number Diff line change
Expand Up @@ -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, &params)) {
return false;
Expand Down
2 changes: 2 additions & 0 deletions app/src/scrcpy.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ struct scrcpy_options {
bool render_expired_frames;
bool prefer_text;
bool window_borderless;
uint16_t display_id;
};

#define SCRCPY_OPTIONS_DEFAULT { \
Expand All @@ -58,6 +59,7 @@ struct scrcpy_options {
.render_expired_frames = false, \
.prefer_text = false, \
.window_borderless = false, \
.display_id = 0, \
}

bool
Expand Down
4 changes: 4 additions & 0 deletions app/src/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,12 @@ 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,
Expand All @@ -146,6 +149,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 "
Expand Down
1 change: 1 addition & 0 deletions app/src/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ struct server_params {
uint32_t bit_rate;
uint16_t max_fps;
bool control;
uint16_t display_id;
};

// init default values
Expand Down
8 changes: 4 additions & 4 deletions server/src/main/java/com/genymobile/scrcpy/Device.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public interface RotationListener {
private RotationListener rotationListener;

public Device(Options options) {
screenInfo = computeScreenInfo(options.getCrop(), options.getMaxSize());
screenInfo = computeScreenInfo(options.getDisplayId(), options.getCrop(), options.getMaxSize());
registerRotationWatcher(new IRotationWatcher.Stub() {
@Override
public void onRotationChanged(int rotation) throws RemoteException {
Expand All @@ -46,8 +46,8 @@ public synchronized ScreenInfo getScreenInfo() {
return screenInfo;
}

private ScreenInfo computeScreenInfo(Rect crop, int maxSize) {
DisplayInfo displayInfo = serviceManager.getDisplayManager().getDisplayInfo();
private ScreenInfo computeScreenInfo(int displayId, Rect crop, int maxSize) {
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());
Expand All @@ -64,7 +64,7 @@ private ScreenInfo computeScreenInfo(Rect crop, int maxSize) {
}

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) {
Expand Down
14 changes: 13 additions & 1 deletion server/src/main/java/com/genymobile/scrcpy/DisplayInfo.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
package com.genymobile.scrcpy;

public final class DisplayInfo {
private final int displayId;
private final Size size;
private final int rotation;
private final int layerStack;

public DisplayInfo(Size size, int rotation) {
public DisplayInfo(int displayId, Size size, int rotation, int layerStack) {
this.displayId = displayId;
this.size = size;
this.rotation = rotation;
this.layerStack = layerStack;
}

public int getDisplayId() {
return displayId;
}

public Size getSize() {
Expand All @@ -16,5 +24,9 @@ public Size getSize() {
public int getRotation() {
return rotation;
}

public int getLayerStack() {
return layerStack;
}
}

9 changes: 9 additions & 0 deletions server/src/main/java/com/genymobile/scrcpy/Options.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -66,4 +67,12 @@ public boolean getControl() {
public void setControl(boolean control) {
this.control = control;
}

public int getDisplayId() {
return displayId;
}

public void setDisplayId(int displayId) {
this.displayId = displayId;
}
}
7 changes: 4 additions & 3 deletions server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,11 @@ public void streamScreen(Device device, FileDescriptor fd) throws IOException {
IBinder display = createDisplay();
Rect contentRect = device.getScreenInfo().getContentRect();
Rect videoRect = device.getScreenInfo().getVideoSize().toRect();
int layerStack = device.getScreenInfo().getLayerStack();
setSize(format, videoRect.width(), videoRect.height());
configure(codec, format);
Surface surface = codec.createInputSurface();
setDisplaySurface(display, surface, contentRect, videoRect);
setDisplaySurface(display, surface, contentRect, videoRect, layerStack);
codec.start();
try {
alive = encode(codec, fd);
Expand Down Expand Up @@ -172,12 +173,12 @@ private static void setSize(MediaFormat format, int width, int height) {
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();
}
Expand Down
10 changes: 8 additions & 2 deletions server/src/main/java/com/genymobile/scrcpy/ScreenInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -21,11 +23,15 @@ public Size getVideoSize() {
return videoSize;
}

public int getLayerStack() {
return layerStack;
}

public ScreenInfo withRotation(int rotation) {
boolean newRotated = (rotation & 1) != 0;
if (rotated == newRotated) {
return this;
}
return new ScreenInfo(Device.flipRect(contentRect), videoSize.rotate(), newRotated);
return new ScreenInfo(Device.flipRect(contentRect), videoSize.rotate(), newRotated, layerStack);
}
}
7 changes: 5 additions & 2 deletions server/src/main/java/com/genymobile/scrcpy/Server.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ private static Options createOptions(String... args) {
"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();
Expand All @@ -107,6 +107,9 @@ private static Options createOptions(String... args) {
boolean control = Boolean.parseBoolean(args[7]);
options.setControl(control);

int displayId = Integer.parseInt(args[8]);
options.setDisplayId(displayId);

return options;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,19 @@ public DisplayManager(IInterface manager) {
}

public DisplayInfo getDisplayInfo() {
return getDisplayInfo(0);
}

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(displayId, new Size(width, height), rotation, layerStack);
} catch (Exception e) {
throw new AssertionError(e);
}
Expand Down