mirror of
https://github.com/Genymobile/scrcpy.git
synced 2025-08-03 14:49:29 +00:00
Merge pull request #1 from calebbrown/master
Replace layout stack option with better device id option.
This commit is contained in:
commit
e787615dd2
12 changed files with 58 additions and 34 deletions
|
@ -41,8 +41,8 @@ scrcpy_print_usage(const char *arg0) {
|
||||||
" -h, --help\n"
|
" -h, --help\n"
|
||||||
" Print this help.\n"
|
" Print this help.\n"
|
||||||
"\n"
|
"\n"
|
||||||
" --layer-stack value\n"
|
" --display-id value\n"
|
||||||
" Specifies the Android layer stack to mirror\n"
|
" Specifies the Android display to mirror\n"
|
||||||
" Default is 0\n"
|
" Default is 0\n"
|
||||||
"\n"
|
"\n"
|
||||||
" --max-fps value\n"
|
" --max-fps value\n"
|
||||||
|
@ -264,14 +264,14 @@ parse_max_fps(const char *s, uint16_t *max_fps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
parse_layer_stack(const char *s, uint16_t *layer_stack) {
|
parse_display_id(const char *s, uint16_t *display_id) {
|
||||||
long value;
|
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) {
|
if (!ok) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
*layer_stack = (uint16_t) value;
|
*display_id = (uint16_t) value;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,7 +356,7 @@ guess_record_format(const char *filename) {
|
||||||
#define OPT_WINDOW_HEIGHT 1010
|
#define OPT_WINDOW_HEIGHT 1010
|
||||||
#define OPT_WINDOW_BORDERLESS 1011
|
#define OPT_WINDOW_BORDERLESS 1011
|
||||||
#define OPT_MAX_FPS 1012
|
#define OPT_MAX_FPS 1012
|
||||||
#define OPT_LAYER_STACK 1013
|
#define OPT_DISPLAY_ID 1013
|
||||||
|
|
||||||
bool
|
bool
|
||||||
scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
|
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'},
|
{"fullscreen", no_argument, NULL, 'f'},
|
||||||
{"help", no_argument, NULL, 'h'},
|
{"help", no_argument, NULL, 'h'},
|
||||||
{"max-fps", required_argument, NULL, OPT_MAX_FPS},
|
{"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'},
|
{"max-size", required_argument, NULL, 'm'},
|
||||||
{"no-control", no_argument, NULL, 'n'},
|
{"no-control", no_argument, NULL, 'n'},
|
||||||
{"no-display", 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;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPT_LAYER_STACK:
|
case OPT_DISPLAY_ID:
|
||||||
if (!parse_layer_stack(optarg, &opts->layer_stack)) {
|
if (!parse_display_id(optarg, &opts->display_id)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -285,7 +285,7 @@ scrcpy(const struct scrcpy_options *options) {
|
||||||
.bit_rate = options->bit_rate,
|
.bit_rate = options->bit_rate,
|
||||||
.max_fps = options->max_fps,
|
.max_fps = options->max_fps,
|
||||||
.control = options->control,
|
.control = options->control,
|
||||||
.layer_stack = options->layer_stack,
|
.display_id = options->display_id,
|
||||||
};
|
};
|
||||||
if (!server_start(&server, options->serial, ¶ms)) {
|
if (!server_start(&server, options->serial, ¶ms)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -32,7 +32,7 @@ struct scrcpy_options {
|
||||||
bool render_expired_frames;
|
bool render_expired_frames;
|
||||||
bool prefer_text;
|
bool prefer_text;
|
||||||
bool window_borderless;
|
bool window_borderless;
|
||||||
uint16_t layer_stack;
|
uint16_t display_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SCRCPY_OPTIONS_DEFAULT { \
|
#define SCRCPY_OPTIONS_DEFAULT { \
|
||||||
|
@ -59,7 +59,7 @@ struct scrcpy_options {
|
||||||
.render_expired_frames = false, \
|
.render_expired_frames = false, \
|
||||||
.prefer_text = false, \
|
.prefer_text = false, \
|
||||||
.window_borderless = false, \
|
.window_borderless = false, \
|
||||||
.layer_stack = 0, \
|
.display_id = 0, \
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -124,12 +124,12 @@ execute_server(struct server *server, const struct server_params *params) {
|
||||||
char max_size_string[6];
|
char max_size_string[6];
|
||||||
char bit_rate_string[11];
|
char bit_rate_string[11];
|
||||||
char max_fps_string[6];
|
char max_fps_string[6];
|
||||||
char layer_stack_string[6];
|
char display_id_string[6];
|
||||||
|
|
||||||
sprintf(max_size_string, "%"PRIu16, params->max_size);
|
sprintf(max_size_string, "%"PRIu16, params->max_size);
|
||||||
sprintf(bit_rate_string, "%"PRIu32, params->bit_rate);
|
sprintf(bit_rate_string, "%"PRIu32, params->bit_rate);
|
||||||
sprintf(max_fps_string, "%"PRIu16, params->max_fps);
|
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[] = {
|
const char *const cmd[] = {
|
||||||
"shell",
|
"shell",
|
||||||
"CLASSPATH=" DEVICE_SERVER_PATH,
|
"CLASSPATH=" DEVICE_SERVER_PATH,
|
||||||
|
@ -149,7 +149,7 @@ execute_server(struct server *server, const struct server_params *params) {
|
||||||
params->crop ? params->crop : "-",
|
params->crop ? params->crop : "-",
|
||||||
"true", // always send frame meta (packet boundaries + timestamp)
|
"true", // always send frame meta (packet boundaries + timestamp)
|
||||||
params->control ? "true" : "false",
|
params->control ? "true" : "false",
|
||||||
layer_stack_string
|
display_id_string
|
||||||
};
|
};
|
||||||
#ifdef SERVER_DEBUGGER
|
#ifdef SERVER_DEBUGGER
|
||||||
LOGI("Server debugger waiting for a client on device port "
|
LOGI("Server debugger waiting for a client on device port "
|
||||||
|
|
|
@ -37,7 +37,7 @@ struct server_params {
|
||||||
uint32_t bit_rate;
|
uint32_t bit_rate;
|
||||||
uint16_t max_fps;
|
uint16_t max_fps;
|
||||||
bool control;
|
bool control;
|
||||||
uint16_t layer_stack;
|
uint16_t display_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
// init default values
|
// init default values
|
||||||
|
|
|
@ -26,7 +26,7 @@ public final class Device {
|
||||||
private RotationListener rotationListener;
|
private RotationListener rotationListener;
|
||||||
|
|
||||||
public Device(Options options) {
|
public Device(Options options) {
|
||||||
screenInfo = computeScreenInfo(options.getCrop(), options.getMaxSize());
|
screenInfo = computeScreenInfo(options.getDisplayId(), options.getCrop(), options.getMaxSize());
|
||||||
registerRotationWatcher(new IRotationWatcher.Stub() {
|
registerRotationWatcher(new IRotationWatcher.Stub() {
|
||||||
@Override
|
@Override
|
||||||
public void onRotationChanged(int rotation) throws RemoteException {
|
public void onRotationChanged(int rotation) throws RemoteException {
|
||||||
|
@ -46,8 +46,8 @@ public final class Device {
|
||||||
return screenInfo;
|
return screenInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScreenInfo computeScreenInfo(Rect crop, int maxSize) {
|
private ScreenInfo computeScreenInfo(int displayId, Rect crop, int maxSize) {
|
||||||
DisplayInfo displayInfo = serviceManager.getDisplayManager().getDisplayInfo();
|
DisplayInfo displayInfo = serviceManager.getDisplayManager().getDisplayInfo(displayId);
|
||||||
boolean rotated = (displayInfo.getRotation() & 1) != 0;
|
boolean rotated = (displayInfo.getRotation() & 1) != 0;
|
||||||
Size deviceSize = displayInfo.getSize();
|
Size deviceSize = displayInfo.getSize();
|
||||||
Rect contentRect = new Rect(0, 0, deviceSize.getWidth(), deviceSize.getHeight());
|
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);
|
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) {
|
private static String formatCrop(Rect rect) {
|
||||||
|
|
|
@ -1,12 +1,20 @@
|
||||||
package com.genymobile.scrcpy;
|
package com.genymobile.scrcpy;
|
||||||
|
|
||||||
public final class DisplayInfo {
|
public final class DisplayInfo {
|
||||||
|
private final int displayId;
|
||||||
private final Size size;
|
private final Size size;
|
||||||
private final int rotation;
|
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.size = size;
|
||||||
this.rotation = rotation;
|
this.rotation = rotation;
|
||||||
|
this.layerStack = layerStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDisplayId() {
|
||||||
|
return displayId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Size getSize() {
|
public Size getSize() {
|
||||||
|
@ -16,5 +24,9 @@ public final class DisplayInfo {
|
||||||
public int getRotation() {
|
public int getRotation() {
|
||||||
return rotation;
|
return rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getLayerStack() {
|
||||||
|
return layerStack;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ public class Options {
|
||||||
private Rect crop;
|
private Rect crop;
|
||||||
private boolean sendFrameMeta; // send PTS so that the client may record properly
|
private boolean sendFrameMeta; // send PTS so that the client may record properly
|
||||||
private boolean control;
|
private boolean control;
|
||||||
private int layerStack;
|
private int displayId;
|
||||||
|
|
||||||
public int getMaxSize() {
|
public int getMaxSize() {
|
||||||
return maxSize;
|
return maxSize;
|
||||||
|
@ -68,11 +68,11 @@ public class Options {
|
||||||
this.control = control;
|
this.control = control;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getLayerStack() {
|
public int getDisplayId() {
|
||||||
return layerStack;
|
return displayId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLayerStack(int layerStack) {
|
public void setDisplayId(int displayId) {
|
||||||
this.layerStack = layerStack;
|
this.displayId = displayId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ public class ScreenEncoder implements Device.RotationListener {
|
||||||
return rotationChanged.getAndSet(false);
|
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.prepareMainLooper();
|
||||||
Workarounds.fillAppInfo();
|
Workarounds.fillAppInfo();
|
||||||
|
|
||||||
|
@ -64,6 +64,7 @@ public class ScreenEncoder implements Device.RotationListener {
|
||||||
IBinder display = createDisplay();
|
IBinder display = createDisplay();
|
||||||
Rect contentRect = device.getScreenInfo().getContentRect();
|
Rect contentRect = device.getScreenInfo().getContentRect();
|
||||||
Rect videoRect = device.getScreenInfo().getVideoSize().toRect();
|
Rect videoRect = device.getScreenInfo().getVideoSize().toRect();
|
||||||
|
int layerStack = device.getScreenInfo().getLayerStack();
|
||||||
setSize(format, videoRect.width(), videoRect.height());
|
setSize(format, videoRect.width(), videoRect.height());
|
||||||
configure(codec, format);
|
configure(codec, format);
|
||||||
Surface surface = codec.createInputSurface();
|
Surface surface = codec.createInputSurface();
|
||||||
|
|
|
@ -6,11 +6,13 @@ public final class ScreenInfo {
|
||||||
private final Rect contentRect; // device size, possibly cropped
|
private final Rect contentRect; // device size, possibly cropped
|
||||||
private final Size videoSize;
|
private final Size videoSize;
|
||||||
private final boolean rotated;
|
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.contentRect = contentRect;
|
||||||
this.videoSize = videoSize;
|
this.videoSize = videoSize;
|
||||||
this.rotated = rotated;
|
this.rotated = rotated;
|
||||||
|
this.layerStack = layerStack;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Rect getContentRect() {
|
public Rect getContentRect() {
|
||||||
|
@ -21,11 +23,15 @@ public final class ScreenInfo {
|
||||||
return videoSize;
|
return videoSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getLayerStack() {
|
||||||
|
return layerStack;
|
||||||
|
}
|
||||||
|
|
||||||
public ScreenInfo withRotation(int rotation) {
|
public ScreenInfo withRotation(int rotation) {
|
||||||
boolean newRotated = (rotation & 1) != 0;
|
boolean newRotated = (rotation & 1) != 0;
|
||||||
if (rotated == newRotated) {
|
if (rotated == newRotated) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
return new ScreenInfo(Device.flipRect(contentRect), videoSize.rotate(), newRotated);
|
return new ScreenInfo(Device.flipRect(contentRect), videoSize.rotate(), newRotated, layerStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ public final class Server {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// synchronous
|
// synchronous
|
||||||
screenEncoder.streamScreen(device, connection.getVideoFd(), options.getLayerStack());
|
screenEncoder.streamScreen(device, connection.getVideoFd());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// this is expected on close
|
// this is expected on close
|
||||||
Ln.d("Screen streaming stopped");
|
Ln.d("Screen streaming stopped");
|
||||||
|
@ -107,8 +107,8 @@ public final class Server {
|
||||||
boolean control = Boolean.parseBoolean(args[7]);
|
boolean control = Boolean.parseBoolean(args[7]);
|
||||||
options.setControl(control);
|
options.setControl(control);
|
||||||
|
|
||||||
int layerStack = Integer.parseInt(args[8]);
|
int displayId = Integer.parseInt(args[8]);
|
||||||
options.setLayerStack(layerStack);
|
options.setDisplayId(displayId);
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,14 +13,19 @@ public final class DisplayManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public DisplayInfo getDisplayInfo() {
|
public DisplayInfo getDisplayInfo() {
|
||||||
|
return getDisplayInfo(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DisplayInfo getDisplayInfo(int displayId) {
|
||||||
try {
|
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();
|
Class<?> cls = displayInfo.getClass();
|
||||||
// width and height already take the rotation into account
|
// width and height already take the rotation into account
|
||||||
int width = cls.getDeclaredField("logicalWidth").getInt(displayInfo);
|
int width = cls.getDeclaredField("logicalWidth").getInt(displayInfo);
|
||||||
int height = cls.getDeclaredField("logicalHeight").getInt(displayInfo);
|
int height = cls.getDeclaredField("logicalHeight").getInt(displayInfo);
|
||||||
int rotation = cls.getDeclaredField("rotation").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) {
|
} catch (Exception e) {
|
||||||
throw new AssertionError(e);
|
throw new AssertionError(e);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue