Replace layout stack option with better device id option.

This allows the correct geometry to be grabbed and the layout stack to be derived from the display info itself.
This commit is contained in:
Caleb Brown 2020-03-19 12:38:05 +11:00
parent 792fd0e07b
commit 4afca06635
12 changed files with 58 additions and 34 deletions

View file

@ -41,8 +41,8 @@ scrcpy_print_usage(const char *arg0) {
" -h, --help\n"
" Print this help.\n"
"\n"
" --layer-stack value\n"
" Specifies the Android layer stack to mirror\n"
" --display-id value\n"
" Specifies the Android display to mirror\n"
" Default is 0\n"
"\n"
" --max-fps value\n"
@ -264,14 +264,14 @@ parse_max_fps(const char *s, uint16_t *max_fps) {
}
static bool
parse_layer_stack(const char *s, uint16_t *layer_stack) {
parse_display_id(const char *s, uint16_t *display_id) {
long value;
bool ok = parse_integer_arg(s, &value, false, 0, 1000, "layer stack");
bool ok = parse_integer_arg(s, &value, false, 0, 1000, "display id");
if (!ok) {
return false;
}
*layer_stack = (uint16_t) value;
*display_id = (uint16_t) value;
return true;
}
@ -356,7 +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_LAYER_STACK 1013
#define OPT_DISPLAY_ID 1013
bool
scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
@ -367,7 +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},
{"layer-stack", required_argument, NULL, OPT_LAYER_STACK},
{"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'},
@ -430,8 +430,8 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
return false;
}
break;
case OPT_LAYER_STACK:
if (!parse_layer_stack(optarg, &opts->layer_stack)) {
case OPT_DISPLAY_ID:
if (!parse_display_id(optarg, &opts->display_id)) {
return false;
}
break;

View file

@ -285,7 +285,7 @@ scrcpy(const struct scrcpy_options *options) {
.bit_rate = options->bit_rate,
.max_fps = options->max_fps,
.control = options->control,
.layer_stack = options->layer_stack,
.display_id = options->display_id,
};
if (!server_start(&server, options->serial, &params)) {
return false;

View file

@ -32,7 +32,7 @@ struct scrcpy_options {
bool render_expired_frames;
bool prefer_text;
bool window_borderless;
uint16_t layer_stack;
uint16_t display_id;
};
#define SCRCPY_OPTIONS_DEFAULT { \
@ -59,7 +59,7 @@ struct scrcpy_options {
.render_expired_frames = false, \
.prefer_text = false, \
.window_borderless = false, \
.layer_stack = 0, \
.display_id = 0, \
}
bool

View file

@ -124,12 +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 layer_stack_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(layer_stack_string, "%"PRIu16, params->layer_stack);
sprintf(display_id_string, "%"PRIu16, params->display_id);
const char *const cmd[] = {
"shell",
"CLASSPATH=" DEVICE_SERVER_PATH,
@ -149,7 +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",
layer_stack_string
display_id_string
};
#ifdef SERVER_DEBUGGER
LOGI("Server debugger waiting for a client on device port "

View file

@ -37,7 +37,7 @@ struct server_params {
uint32_t bit_rate;
uint16_t max_fps;
bool control;
uint16_t layer_stack;
uint16_t display_id;
};
// init default values

View file

@ -26,7 +26,7 @@ public final class Device {
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 {
@ -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(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());
@ -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) {

View file

@ -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() {
@ -16,5 +24,9 @@ public final class DisplayInfo {
public int getRotation() {
return rotation;
}
public int getLayerStack() {
return layerStack;
}
}

View file

@ -10,7 +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 layerStack;
private int displayId;
public int getMaxSize() {
return maxSize;
@ -68,11 +68,11 @@ public class Options {
this.control = control;
}
public int getLayerStack() {
return layerStack;
public int getDisplayId() {
return displayId;
}
public void setLayerStack(int layerStack) {
this.layerStack = layerStack;
public void setDisplayId(int displayId) {
this.displayId = displayId;
}
}

View file

@ -51,7 +51,7 @@ public class ScreenEncoder implements Device.RotationListener {
return rotationChanged.getAndSet(false);
}
public void streamScreen(Device device, FileDescriptor fd, int layerStack) throws IOException {
public void streamScreen(Device device, FileDescriptor fd) throws IOException {
Workarounds.prepareMainLooper();
Workarounds.fillAppInfo();
@ -64,6 +64,7 @@ public class ScreenEncoder implements Device.RotationListener {
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();

View file

@ -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() {
@ -21,11 +23,15 @@ public final class ScreenInfo {
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);
}
}

View file

@ -31,7 +31,7 @@ public final class Server {
try {
// synchronous
screenEncoder.streamScreen(device, connection.getVideoFd(), options.getLayerStack());
screenEncoder.streamScreen(device, connection.getVideoFd());
} catch (IOException e) {
// this is expected on close
Ln.d("Screen streaming stopped");
@ -107,8 +107,8 @@ public final class Server {
boolean control = Boolean.parseBoolean(args[7]);
options.setControl(control);
int layerStack = Integer.parseInt(args[8]);
options.setLayerStack(layerStack);
int displayId = Integer.parseInt(args[8]);
options.setDisplayId(displayId);
return options;
}

View file

@ -13,14 +13,19 @@ public final class DisplayManager {
}
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);
}