Compare commits

..

21 Commits

Author SHA1 Message Date
Romain Vimont
26ee63d9e9 Build on Windows with libusb support 2022-02-07 13:24:10 +01:00
Romain Vimont
0d3ed2f669 Fix libusb callback for Windows
Add LIBUSB_CALL so that the callback has the correct signature on
Windows (including __attribute__((stdcall))).
2022-02-07 13:24:10 +01:00
Romain Vimont
0480581789 Avoid PRIx16 printf format on Windows
Convert uint16_t to unsigned to avoid using PRIx16, which may not exist
on Windows.
2022-02-07 13:24:09 +01:00
Romain Vimont
c0bc183157 Log device opening errors during listing
Without this log, the user would have no way to know that a USB device
is rejected because it could not be opened (typically due to
insufficient permissions).
2022-02-07 13:21:31 +01:00
Romain Vimont
dddd960a9e Mention --select-usb and --select-tcpip in README 2022-02-07 13:11:37 +01:00
Romain Vimont
5b05936093 Add option to select USB or TCP/IP devices
If several devices are connected (as listed by `adb devices`), it was
necessary to provide the explicit serial via -s/--serial.

If only one device is connected via USB (respectively, via TCP/IP), it
might be convenient to select it automatically. For this purpose, two
new options are introduced:
 - -U/--select-usb: select the single device connected over USB
 - -T/--select-tcpip: select the single device connected over TCP/IP
2022-02-07 13:11:37 +01:00
Romain Vimont
14b608dbcc Introduce adb device selector
Currently, a device is selected either from a specific serial, or if it
is the only one connected.

In order to support selecting the only device connected via USB or via
TCP/IP separately, introduce a new selection structure.
2022-02-07 13:11:37 +01:00
Romain Vimont
1718bfe00e Execute adb start-server
This does nothing if the adb daemon is already started, but allows to
print any output/errors in the console.

Otherwise, the daemon starting would occur during `adb devices`, which
does not output to the console because the result is parsed.
2022-02-07 13:11:37 +01:00
Romain Vimont
4ad12755da Remove sc_adb_get_serialno()
The device serial is now retrieved from `adb devices -l`, `adb
get-serialno` is not called anymore.
2022-02-07 13:11:37 +01:00
Romain Vimont
a6bedb4301 Allow selecting a device from IP without port
Since the previous commit, if a serial is given via -s/--serial (either
a real USB serial or an IP:port), a device is selected if its serial
matches exactly.

In addition, if the user pass an IP without a port, then select any
device with this IP, regardless of the port (so that "192.168.1.1"
matches any "192.168.1.1:port"). This is also the default behavior of
adb.
2022-02-07 13:11:37 +01:00
Romain Vimont
a432134685 Expose simple API to select a single adb device
Select an adb device from the output of `adb device -l`.
2022-02-07 13:11:37 +01:00
Romain Vimont
e78eb83cb9 Expose function to test if a serial is TCP/IP
In practice, it just tests if the serial contains a ':', which is
sufficient to distinguish ip:port from a real USB serial.
2022-02-07 13:11:37 +01:00
Romain Vimont
f5b737857f Add adb devices parser
Add a parser of `adb device -l` output, to extract a list of devices
with their serial, state and model.
2022-02-07 13:11:37 +01:00
Romain Vimont
4a759f9b55 Refactor device configuration
Depending on the parameters passed to scrcpy, either the initial device
serial is necessary or not. Reorganize to simplify the logic.
2022-02-07 13:11:37 +01:00
Romain Vimont
c28e616a44 List and select USB devices separately
List all USB devices in a first step, then select the matching one(s).

This allows to report a user-friendly log message containing the list of
devices, with the matching one(s) highlighted.
2022-02-07 13:11:37 +01:00
Romain Vimont
70a0d9cc37 Expose simple API to select a single USB device
The caller just wants a single device. Handle all cases and error
messages internally.
2022-02-07 13:11:37 +01:00
Romain Vimont
b11c6550c7 Add move-function for sc_usb_device
Add a function to "move" a sc_usb_device into another instance.

This will avoid unnecessary copies.
2022-02-07 13:11:37 +01:00
Romain Vimont
7d7953e278 Move SC_PRIsizet to compat.h
Define the printf format macro for size_t in compat.h so that it can be
used from anywhere.
2022-02-07 13:11:37 +01:00
Romain Vimont
54d48321fd Rename function to destroy a list of USB devices
Rename from "usb_device_" to "usb_devices_".
2022-02-07 13:11:37 +01:00
Romain Vimont
3456ca19c7 Add generic LOG() macro with level parameter
One log macro was provided for each log level (LOGV(), LOGD(), LOGI(),
LOGW(), LOGE()).

Add a generic macro LOG(LEVEL, ...) taking a log level as parameter, so
that it is possible to write logging wrappers.
2022-02-07 13:11:37 +01:00
Romain Vimont
79eb78a9e8 Remove LOGC()
It is not clear when to use LOGC() rather than LOGE(). Always use
LOGE().

Moreover, enum sc_log_level has no "critical" log level.
2022-02-07 13:11:37 +01:00
42 changed files with 277 additions and 338 deletions

View File

@@ -258,7 +258,7 @@ set ANDROID_SDK_ROOT=%LOCALAPPDATA%\Android\sdk
Then, build:
```bash
meson x --buildtype=release --strip -Db_lto=true
meson x --buildtype release --strip -Db_lto=true
ninja -Cx # DO NOT RUN AS ROOT
```
@@ -279,7 +279,7 @@ Download the prebuilt server somewhere, and specify its path during the Meson
configuration:
```bash
meson x --buildtype=release --strip -Db_lto=true \
meson x --buildtype release --strip -Db_lto=true \
-Dprebuilt_server=/path/to/scrcpy-server
ninja -Cx # DO NOT RUN AS ROOT
```

View File

@@ -441,12 +441,12 @@ select it automatically:
```bash
# Select the only device connected via USB
scrcpy -d # like adb -d
scrcpy --select-usb # long version
scrcpy --select-usb
scrcpy -U # short version
# Select the only device connected via TCP/IP
scrcpy -e # like adb -e
scrcpy --select-tcpip # long version
scrcpy --select-tcpip
scrcpy -T # short version
```
You can start several instances of _scrcpy_ for several devices.

View File

@@ -26,7 +26,6 @@ src = [
'src/scrcpy.c',
'src/screen.c',
'src/server.c',
'src/version.c',
'src/video_buffer.c',
'src/util/acksync.c',
'src/util/file.c',
@@ -69,12 +68,12 @@ else
endif
endif
v4l2_support = get_option('v4l2') and host_machine.system() == 'linux'
v4l2_support = host_machine.system() == 'linux'
if v4l2_support
src += [ 'src/v4l2_sink.c' ]
endif
usb_support = get_option('usb') and host_machine.system() == 'linux'
usb_support = host_machine.system() == 'linux' or host_machine.system() == 'windows'
if usb_support
src += [
'src/usb/aoa_hid.c',
@@ -111,9 +110,9 @@ if not crossbuild_windows
else
# cross-compile mingw32 build (from Linux to Windows)
prebuilt_sdl2 = meson.get_cross_property('prebuilt_sdl2')
sdl2_bin_dir = meson.current_source_dir() + '/prebuilt-deps/data/' + prebuilt_sdl2 + '/bin'
sdl2_lib_dir = meson.current_source_dir() + '/prebuilt-deps/data/' + prebuilt_sdl2 + '/lib'
sdl2_include_dir = 'prebuilt-deps/data/' + prebuilt_sdl2 + '/include'
sdl2_bin_dir = meson.current_source_dir() + '/../prebuilt-deps/data/' + prebuilt_sdl2 + '/bin'
sdl2_lib_dir = meson.current_source_dir() + '/../prebuilt-deps/data/' + prebuilt_sdl2 + '/lib'
sdl2_include_dir = '../prebuilt-deps/data/' + prebuilt_sdl2 + '/include'
sdl2 = declare_dependency(
dependencies: [
@@ -124,8 +123,8 @@ else
)
prebuilt_ffmpeg = meson.get_cross_property('prebuilt_ffmpeg')
ffmpeg_bin_dir = meson.current_source_dir() + '/prebuilt-deps/data/' + prebuilt_ffmpeg + '/bin'
ffmpeg_include_dir = 'prebuilt-deps/data/' + prebuilt_ffmpeg + '/include'
ffmpeg_bin_dir = meson.current_source_dir() + '/../prebuilt-deps/data/' + prebuilt_ffmpeg + '/bin'
ffmpeg_include_dir = '../prebuilt-deps/data/' + prebuilt_ffmpeg + '/include'
# ffmpeg versions are different for win32 and win64 builds
ffmpeg_avcodec = meson.get_cross_property('ffmpeg_avcodec')
@@ -141,9 +140,22 @@ else
include_directories: include_directories(ffmpeg_include_dir)
)
prebuilt_libusb = meson.get_cross_property('prebuilt_libusb')
prebuilt_libusb_root = meson.get_cross_property('prebuilt_libusb_root')
libusb_bin_dir = meson.current_source_dir() + '/../prebuilt-deps/data/' + prebuilt_libusb + '/dll'
libusb_include_dir = '../prebuilt-deps/data/' + prebuilt_libusb_root + '/include'
libusb = declare_dependency(
dependencies: [
cc.find_library('libusb-1.0', dirs: libusb_bin_dir),
],
include_directories: include_directories(libusb_include_dir)
)
dependencies = [
ffmpeg,
sdl2,
libusb,
cc.find_library('mingw32')
]

View File

@@ -43,12 +43,6 @@ The values are expressed in the device natural orientation (typically, portrait
.B \-\-max\-size
value is computed on the cropped size.
.TP
.B \-d, \-\-select\-usb
Use USB device (if there is exactly one, like adb -d).
Also see \fB\-e\fR (\fB\-\-select\-tcpip\fR).
.TP
.BI "\-\-disable-screensaver"
Disable screensaver while scrcpy is running.
@@ -68,12 +62,6 @@ Add a buffering delay (in milliseconds) before displaying. This increases latenc
Default is 0 (no buffering).
.TP
.B \-e, \-\-select\-tcpip
Use TCP/IP device (if there is exactly one, like adb -e).
Also see \fB\-d\fR (\fB\-\-select\-usb\fR).
.TP
.BI "\-\-encoder " name
Use a specific MediaCodec encoder (must be a H.264 encoder).
@@ -146,12 +134,6 @@ It may only work over USB, and is currently only supported on Linux.
Also see \fB\-\-hid\-keyboard\fR.
.TP
.B \-\-no\-cleanup
By default, scrcpy removes the server binary from the device and restores the device state (show touches, stay awake and power mode) on exit.
This option disables this cleanup.
.TP
.B \-\-no\-clipboard\-autosync
By default, scrcpy automatically synchronizes the computer clipboard to the device clipboard before injecting Ctrl+v, and the device clipboard to the computer clipboard whenever it changes.
@@ -291,6 +273,14 @@ Set the TCP port of the adb tunnel to reach the scrcpy server. This option autom
Default is 0 (not forced): the local port used for establishing the tunnel will be used.
.TP
.B \-T, \-\-select\-tcpip
Use TCP/IP device (if there is exactly one).
.TP
.B \-U, \-\-select\-usb
Use USB device (if there is exactly one).
.TP
.BI "\-\-v4l2-sink " /dev/videoN
Output to v4l2loopback device.

View File

@@ -585,8 +585,9 @@ sc_adb_select_device(struct sc_intr *intr,
break;
}
sc_adb_devices_log(SC_LOG_LEVEL_ERROR, devices, count);
LOGE("Select a device via -s (--serial), -d (--select-usb) or -e "
"(--select-tcpip)");
if (selector->type != SC_ADB_DEVICE_SELECT_ALL) {
LOGE("Specify the device via -s or --serial");
}
sc_adb_devices_destroy_all(devices, count);
return false;
}

View File

@@ -17,7 +17,7 @@ void
sc_adb_device_destroy(struct sc_adb_device *device);
/**
* Move src to dst
* Move src to dest
*
* After this call, the content of src is undefined, except that
* sc_adb_device_destroy() can be called.

View File

@@ -54,7 +54,6 @@
#define OPT_RAW_KEY_EVENTS 1034
#define OPT_NO_DOWNSIZE_ON_ERROR 1035
#define OPT_OTG 1036
#define OPT_NO_CLEANUP 1037
struct sc_option {
char shortopt;
@@ -119,12 +118,6 @@ static const struct sc_option options[] = {
"(typically, portrait for a phone, landscape for a tablet). "
"Any --max-size value is cmoputed on the cropped size.",
},
{
.shortopt = 'd',
.longopt = "select-usb",
.text = "Use USB device (if there is exactly one, like adb -d).\n"
"Also see -e (--select-tcpip).",
},
{
.longopt_id = OPT_DISABLE_SCREENSAVER,
.longopt = "disable-screensaver",
@@ -148,12 +141,6 @@ static const struct sc_option options[] = {
"This increases latency to compensate for jitter.\n"
"Default is 0 (no buffering).",
},
{
.shortopt = 'e',
.longopt = "select-tcpip",
.text = "Use TCP/IP device (if there is exactly one, like adb -e).\n"
"Also see -d (--select-usb).",
},
{
.longopt_id = OPT_ENCODER_NAME,
.longopt = "encoder",
@@ -252,12 +239,11 @@ static const struct sc_option options[] = {
"Default is 0 (unlimited).",
},
{
.longopt_id = OPT_NO_CLEANUP,
.longopt = "no-cleanup",
.text = "By default, scrcpy removes the server binary from the device "
"and restores the device state (show touches, stay awake and "
"power mode) on exit.\n"
"This option disables this cleanup."
.longopt_id = OPT_NO_DOWNSIZE_ON_ERROR,
.longopt = "no-downsize-on-error",
.text = "By default, on MediaCodec error, scrcpy automatically tries "
"again with a lower definition.\n"
"This option disables this behavior.",
},
{
.longopt_id = OPT_NO_CLIPBOARD_AUTOSYNC,
@@ -268,13 +254,6 @@ static const struct sc_option options[] = {
"it changes.\n"
"This option disables this automatic synchronization."
},
{
.longopt_id = OPT_NO_DOWNSIZE_ON_ERROR,
.longopt = "no-downsize-on-error",
.text = "By default, on MediaCodec error, scrcpy automatically tries "
"again with a lower definition.\n"
"This option disables this behavior.",
},
{
.shortopt = 'n',
.longopt = "no-control",
@@ -437,6 +416,16 @@ static const struct sc_option options[] = {
"Default is 0 (not forced): the local port used for "
"establishing the tunnel will be used.",
},
{
.shortopt = 'T',
.longopt = "select-tcpip",
.text = "Use TCP/IP device (if there is exactly one).",
},
{
.shortopt = 'U',
.longopt = "select-usb",
.text = "Use USB device (if there is exactly one).",
},
{
.longopt_id = OPT_V4L2_SINK,
.longopt = "v4l2-sink",
@@ -1341,12 +1330,6 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
return false;
}
break;
case 'd':
opts->select_usb = true;
break;
case 'e':
opts->select_tcpip = true;
break;
case 'f':
opts->fullscreen = true;
break;
@@ -1366,8 +1349,8 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
opts->keyboard_input_mode = SC_KEYBOARD_INPUT_MODE_HID;
break;
#else
LOGE("HID over AOA (-K/--hid-keyboard) is disabled (or "
"unsupported on this platform).");
LOGE("HID over AOA (-K/--hid-keyboard) is not supported on "
"this platform. It is only available on Linux.");
return false;
#endif
case OPT_MAX_FPS:
@@ -1385,8 +1368,8 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
opts->mouse_input_mode = SC_MOUSE_INPUT_MODE_HID;
break;
#else
LOGE("HID over AOA (-M/--hid-mouse) is disabled (or "
"unsupported on this platform).");
LOGE("HID over AOA (-M/--hid-mouse) is not supported on this"
"platform. It is only available on Linux.");
return false;
#endif
case OPT_LOCK_VIDEO_ORIENTATION:
@@ -1428,6 +1411,12 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
case 't':
opts->show_touches = true;
break;
case 'T':
opts->select_tcpip = true;
break;
case 'U':
opts->select_usb = true;
break;
case OPT_ALWAYS_ON_TOP:
opts->always_on_top = true;
break;
@@ -1544,16 +1533,13 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
case OPT_NO_DOWNSIZE_ON_ERROR:
opts->downsize_on_error = false;
break;
case OPT_NO_CLEANUP:
opts->cleanup = false;
break;
case OPT_OTG:
#ifdef HAVE_USB
opts->otg = true;
break;
#else
LOGE("OTG mode (--otg) is disabled (or unsupported on this "
"platform).");
LOGE("OTG mode (--otg) is not supported on this platform. It "
"is only available on Linux.");
return false;
#endif
case OPT_V4L2_SINK:
@@ -1561,8 +1547,7 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
opts->v4l2_device = optarg;
break;
#else
LOGE("V4L2 (--v4l2-sink) is disabled (or unsupported on this "
"platform).");
LOGE("V4L2 (--v4l2-sink) is only available on Linux.");
return false;
#endif
case OPT_V4L2_BUFFER:
@@ -1597,8 +1582,8 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
if (selectors > 1) {
LOGE("At most one device selector option may be passed, among:\n"
" --serial (-s)\n"
" --select-usb (-d)\n"
" --select-tcpip (-e)\n"
" --select-usb (-U)\n"
" --select-tcpip (-T)\n"
" --tcpip=<addr> (with an argument)");
return false;
}
@@ -1703,12 +1688,12 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
LOGE("OTG mode: could not select display");
return false;
}
# ifdef HAVE_V4L2
#ifdef HAVE_V4L2
if (opts->v4l2_device) {
LOGE("OTG mode: could not sink to V4L2 device");
return false;
}
# endif
#endif
}
#endif

View File

@@ -63,17 +63,17 @@ static const char *const copy_key_labels[] = {
static void
write_position(uint8_t *buf, const struct sc_position *position) {
sc_write32be(&buf[0], position->point.x);
sc_write32be(&buf[4], position->point.y);
sc_write16be(&buf[8], position->screen_size.width);
sc_write16be(&buf[10], position->screen_size.height);
buffer_write32be(&buf[0], position->point.x);
buffer_write32be(&buf[4], position->point.y);
buffer_write16be(&buf[8], position->screen_size.width);
buffer_write16be(&buf[10], position->screen_size.height);
}
// write length (4 bytes) + string (non null-terminated)
static size_t
write_string(const char *utf8, size_t max_len, unsigned char *buf) {
size_t len = sc_str_utf8_truncation_index(utf8, max_len);
sc_write32be(buf, len);
buffer_write32be(buf, len);
memcpy(&buf[4], utf8, len);
return 4 + len;
}
@@ -94,9 +94,9 @@ sc_control_msg_serialize(const struct sc_control_msg *msg, unsigned char *buf) {
switch (msg->type) {
case SC_CONTROL_MSG_TYPE_INJECT_KEYCODE:
buf[1] = msg->inject_keycode.action;
sc_write32be(&buf[2], msg->inject_keycode.keycode);
sc_write32be(&buf[6], msg->inject_keycode.repeat);
sc_write32be(&buf[10], msg->inject_keycode.metastate);
buffer_write32be(&buf[2], msg->inject_keycode.keycode);
buffer_write32be(&buf[6], msg->inject_keycode.repeat);
buffer_write32be(&buf[10], msg->inject_keycode.metastate);
return 14;
case SC_CONTROL_MSG_TYPE_INJECT_TEXT: {
size_t len =
@@ -106,20 +106,20 @@ sc_control_msg_serialize(const struct sc_control_msg *msg, unsigned char *buf) {
}
case SC_CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT:
buf[1] = msg->inject_touch_event.action;
sc_write64be(&buf[2], msg->inject_touch_event.pointer_id);
buffer_write64be(&buf[2], msg->inject_touch_event.pointer_id);
write_position(&buf[10], &msg->inject_touch_event.position);
uint16_t pressure =
to_fixed_point_16(msg->inject_touch_event.pressure);
sc_write16be(&buf[22], pressure);
sc_write32be(&buf[24], msg->inject_touch_event.buttons);
buffer_write16be(&buf[22], pressure);
buffer_write32be(&buf[24], msg->inject_touch_event.buttons);
return 28;
case SC_CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT:
write_position(&buf[1], &msg->inject_scroll_event.position);
sc_write32be(&buf[13],
buffer_write32be(&buf[13],
(uint32_t) msg->inject_scroll_event.hscroll);
sc_write32be(&buf[17],
buffer_write32be(&buf[17],
(uint32_t) msg->inject_scroll_event.vscroll);
sc_write32be(&buf[21], msg->inject_scroll_event.buttons);
buffer_write32be(&buf[21], msg->inject_scroll_event.buttons);
return 25;
case SC_CONTROL_MSG_TYPE_BACK_OR_SCREEN_ON:
buf[1] = msg->inject_keycode.action;
@@ -128,7 +128,7 @@ sc_control_msg_serialize(const struct sc_control_msg *msg, unsigned char *buf) {
buf[1] = msg->get_clipboard.copy_key;
return 2;
case SC_CONTROL_MSG_TYPE_SET_CLIPBOARD:
sc_write64be(&buf[1], msg->set_clipboard.sequence);
buffer_write64be(&buf[1], msg->set_clipboard.sequence);
buf[9] = !!msg->set_clipboard.paste;
size_t len = write_string(msg->set_clipboard.text,
SC_CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH,

View File

@@ -10,12 +10,10 @@
#include "util/buffer_util.h"
#include "util/log.h"
#define SC_PACKET_HEADER_SIZE 12
#define BUFSIZE 0x10000
#define SC_PACKET_FLAG_CONFIG (UINT64_C(1) << 63)
#define SC_PACKET_FLAG_KEY_FRAME (UINT64_C(1) << 62)
#define SC_PACKET_PTS_MASK (SC_PACKET_FLAG_KEY_FRAME - 1)
#define HEADER_SIZE 12
#define NO_PTS UINT64_C(-1)
static bool
sc_demuxer_recv_packet(struct sc_demuxer *demuxer, AVPacket *packet) {
@@ -30,24 +28,16 @@ sc_demuxer_recv_packet(struct sc_demuxer *demuxer, AVPacket *packet) {
// size
//
// It is followed by <packet_size> bytes containing the packet/frame.
//
// The most significant bits of the PTS are used for packet flags:
//
// byte 7 byte 6 byte 5 byte 4 byte 3 byte 2 byte 1 byte 0
// CK...... ........ ........ ........ ........ ........ ........ ........
// ^^<------------------------------------------------------------------->
// || PTS
// | `- config packet
// `-- key frame
uint8_t header[SC_PACKET_HEADER_SIZE];
ssize_t r = net_recv_all(demuxer->socket, header, SC_PACKET_HEADER_SIZE);
if (r < SC_PACKET_HEADER_SIZE) {
uint8_t header[HEADER_SIZE];
ssize_t r = net_recv_all(demuxer->socket, header, HEADER_SIZE);
if (r < HEADER_SIZE) {
return false;
}
uint64_t pts_flags = sc_read64be(header);
uint32_t len = sc_read32be(&header[8]);
uint64_t pts = buffer_read64be(header);
uint32_t len = buffer_read32be(&header[8]);
assert(pts == NO_PTS || (pts & 0x8000000000000000) == 0);
assert(len);
if (av_new_packet(packet, len)) {
@@ -61,17 +51,8 @@ sc_demuxer_recv_packet(struct sc_demuxer *demuxer, AVPacket *packet) {
return false;
}
if (pts_flags & SC_PACKET_FLAG_CONFIG) {
packet->pts = AV_NOPTS_VALUE;
} else {
packet->pts = pts_flags & SC_PACKET_PTS_MASK;
}
packet->pts = pts != NO_PTS ? (int64_t) pts : AV_NOPTS_VALUE;
if (pts_flags & SC_PACKET_FLAG_KEY_FRAME) {
packet->flags |= AV_PKT_FLAG_KEY;
}
packet->dts = packet->pts;
return true;
}
@@ -88,6 +69,28 @@ push_packet_to_sinks(struct sc_demuxer *demuxer, const AVPacket *packet) {
return true;
}
static void
sc_demuxer_parse(struct sc_demuxer *demuxer, AVPacket *packet) {
uint8_t *in_data = packet->data;
int in_len = packet->size;
uint8_t *out_data = NULL;
int out_len = 0;
int r = av_parser_parse2(demuxer->parser, demuxer->codec_ctx,
&out_data, &out_len, in_data, in_len,
AV_NOPTS_VALUE, AV_NOPTS_VALUE, -1);
// PARSER_FLAG_COMPLETE_FRAMES is set
assert(r == in_len);
(void) r;
assert(out_len == in_len);
if (demuxer->parser->key_frame == 1) {
packet->flags |= AV_PKT_FLAG_KEY;
}
packet->dts = packet->pts;
}
static bool
sc_demuxer_push_packet(struct sc_demuxer *demuxer, AVPacket *packet) {
bool is_config = packet->pts == AV_NOPTS_VALUE;
@@ -127,6 +130,11 @@ sc_demuxer_push_packet(struct sc_demuxer *demuxer, AVPacket *packet) {
}
}
if (!is_config) {
// data packet
sc_demuxer_parse(demuxer, packet);
}
bool ok = push_packet_to_sinks(demuxer, packet);
if (!is_config && demuxer->pending) {

View File

@@ -18,7 +18,7 @@ device_msg_deserialize(const unsigned char *buf, size_t len,
msg->type = buf[0];
switch (msg->type) {
case DEVICE_MSG_TYPE_CLIPBOARD: {
size_t clipboard_len = sc_read32be(&buf[1]);
size_t clipboard_len = buffer_read32be(&buf[1]);
if (clipboard_len > len - 5) {
return 0; // not available
}
@@ -36,7 +36,7 @@ device_msg_deserialize(const unsigned char *buf, size_t len,
return 5 + clipboard_len;
}
case DEVICE_MSG_TYPE_ACK_CLIPBOARD: {
uint64_t sequence = sc_read64be(&buf[1]);
uint64_t sequence = buffer_read64be(&buf[1]);
msg->ack_clipboard.sequence = sequence;
return 9;
}

View File

@@ -15,7 +15,27 @@
#include "scrcpy.h"
#include "usb/scrcpy_otg.h"
#include "util/log.h"
#include "version.h"
static void
print_version(void) {
printf("\ndependencies:\n");
printf(" - SDL %d.%d.%d\n", SDL_MAJOR_VERSION, SDL_MINOR_VERSION,
SDL_PATCHLEVEL);
printf(" - libavcodec %d.%d.%d\n", LIBAVCODEC_VERSION_MAJOR,
LIBAVCODEC_VERSION_MINOR,
LIBAVCODEC_VERSION_MICRO);
printf(" - libavformat %d.%d.%d\n", LIBAVFORMAT_VERSION_MAJOR,
LIBAVFORMAT_VERSION_MINOR,
LIBAVFORMAT_VERSION_MICRO);
printf(" - libavutil %d.%d.%d\n", LIBAVUTIL_VERSION_MAJOR,
LIBAVUTIL_VERSION_MINOR,
LIBAVUTIL_VERSION_MICRO);
#ifdef HAVE_V4L2
printf(" - libavdevice %d.%d.%d\n", LIBAVDEVICE_VERSION_MAJOR,
LIBAVDEVICE_VERSION_MINOR,
LIBAVDEVICE_VERSION_MICRO);
#endif
}
int
main(int argc, char *argv[]) {
@@ -51,7 +71,7 @@ main(int argc, char *argv[]) {
}
if (args.version) {
scrcpy_print_version();
print_version();
return 0;
}

View File

@@ -62,5 +62,4 @@ const struct scrcpy_options scrcpy_options_default = {
.tcpip_dst = NULL,
.select_tcpip = false,
.select_usb = false,
.cleanup = true,
};

View File

@@ -137,7 +137,6 @@ struct scrcpy_options {
const char *tcpip_dst;
bool select_usb;
bool select_tcpip;
bool cleanup;
};
extern const struct scrcpy_options scrcpy_options_default;

View File

@@ -320,7 +320,6 @@ scrcpy(struct scrcpy_options *options) {
.downsize_on_error = options->downsize_on_error,
.tcpip = options->tcpip,
.tcpip_dst = options->tcpip_dst,
.cleanup = options->cleanup,
};
static const struct sc_server_callbacks cbs = {

View File

@@ -163,21 +163,14 @@ sc_screen_is_relative_mode(struct sc_screen *screen) {
}
static void
sc_screen_set_mouse_capture(bool capture) {
sc_screen_capture_mouse(struct sc_screen *screen, bool capture) {
if (SDL_SetRelativeMouseMode(capture)) {
LOGE("Could not set relative mouse mode to %s: %s",
capture ? "true" : "false", SDL_GetError());
return;
}
}
static inline bool
sc_screen_get_mouse_capture(void) {
return SDL_GetRelativeMouseMode();
}
static inline void
sc_screen_toggle_mouse_capture(void) {
sc_screen_set_mouse_capture(!sc_screen_get_mouse_capture());
screen->mouse_captured = capture;
}
static void
@@ -379,6 +372,7 @@ sc_screen_init(struct sc_screen *screen,
screen->fullscreen = false;
screen->maximized = false;
screen->event_failed = false;
screen->mouse_captured = false;
screen->mouse_capture_key_pressed = 0;
screen->req.x = params->window_x;
@@ -716,7 +710,7 @@ sc_screen_update_frame(struct sc_screen *screen) {
if (sc_screen_is_relative_mode(screen)) {
// Capture mouse on start
sc_screen_set_mouse_capture(true);
sc_screen_capture_mouse(screen, true);
}
}
@@ -829,7 +823,7 @@ sc_screen_handle_event(struct sc_screen *screen, SDL_Event *event) {
break;
case SDL_WINDOWEVENT_FOCUS_LOST:
if (relative_mode) {
sc_screen_set_mouse_capture(false);
sc_screen_capture_mouse(screen, false);
}
break;
}
@@ -859,7 +853,8 @@ sc_screen_handle_event(struct sc_screen *screen, SDL_Event *event) {
if (key == cap) {
// A mouse capture key has been pressed then released:
// toggle the capture mouse mode
sc_screen_toggle_mouse_capture();
sc_screen_capture_mouse(screen,
!screen->mouse_captured);
}
// Mouse capture keys are never forwarded to the device
return;
@@ -869,7 +864,7 @@ sc_screen_handle_event(struct sc_screen *screen, SDL_Event *event) {
case SDL_MOUSEWHEEL:
case SDL_MOUSEMOTION:
case SDL_MOUSEBUTTONDOWN:
if (relative_mode && !sc_screen_get_mouse_capture()) {
if (relative_mode && !screen->mouse_captured) {
// Do not forward to input manager, the mouse will be captured
// on SDL_MOUSEBUTTONUP
return;
@@ -885,8 +880,8 @@ sc_screen_handle_event(struct sc_screen *screen, SDL_Event *event) {
}
break;
case SDL_MOUSEBUTTONUP:
if (relative_mode && !sc_screen_get_mouse_capture()) {
sc_screen_set_mouse_capture(true);
if (relative_mode && !screen->mouse_captured) {
sc_screen_capture_mouse(screen, true);
return;
}
break;

View File

@@ -60,6 +60,7 @@ struct sc_screen {
bool event_failed; // in case SDL_PushEvent() returned an error
bool mouse_captured; // only relevant in relative mouse mode
// To enable/disable mouse capture, a mouse capture key (LALT, LGUI or
// RGUI) must be pressed. This variable tracks the pressed capture key.
SDL_Keycode mouse_capture_key_pressed;

View File

@@ -244,10 +244,6 @@ execute_server(struct sc_server *server,
// By default, downsize_on_error is true
ADD_PARAM("downsize_on_error=false");
}
if (!params->cleanup) {
// By default, cleanup is true
ADD_PARAM("cleanup=false");
}
#undef ADD_PARAM
@@ -486,10 +482,8 @@ fail:
}
}
if (tunnel->enabled) {
// Always leave this function with tunnel disabled
sc_adb_tunnel_close(tunnel, &server->intr, serial);
}
// Always leave this function with tunnel disabled
sc_adb_tunnel_close(tunnel, &server->intr, serial);
return false;
}

View File

@@ -46,7 +46,6 @@ struct sc_server_params {
const char *tcpip_dst;
bool select_usb;
bool select_tcpip;
bool cleanup;
};
struct sc_server {

View File

@@ -89,10 +89,8 @@ scrcpy_otg(struct scrcpy_options *options) {
goto end;
}
usb_device_initialized = true;
LOGI("USB device: %s (%04" PRIx16 ":%04" PRIx16 ") %s %s",
usb_device.serial, usb_device.vid, usb_device.pid,
LOGI("USB device: %s (%04x:%04x) %s %s", usb_device.serial,
(unsigned) usb_device.vid, (unsigned) usb_device.pid,
usb_device.manufacturer, usb_device.product);
ok = sc_usb_connect(&s->usb, usb_device.device, &cbs, NULL);

View File

@@ -5,21 +5,15 @@
#include "util/log.h"
static void
sc_screen_otg_set_mouse_capture(bool capture) {
sc_screen_otg_capture_mouse(struct sc_screen_otg *screen, bool capture) {
assert(screen->mouse);
if (SDL_SetRelativeMouseMode(capture)) {
LOGE("Could not set relative mouse mode to %s: %s",
capture ? "true" : "false", SDL_GetError());
return;
}
}
static inline bool
sc_screen_otg_get_mouse_capture(void) {
return SDL_GetRelativeMouseMode();
}
static inline void
sc_screen_otg_toggle_mouse_capture(void) {
sc_screen_otg_set_mouse_capture(!sc_screen_otg_get_mouse_capture());
screen->mouse_captured = capture;
}
static void
@@ -37,6 +31,7 @@ sc_screen_otg_init(struct sc_screen_otg *screen,
screen->keyboard = params->keyboard;
screen->mouse = params->mouse;
screen->mouse_captured = false;
screen->mouse_capture_key_pressed = 0;
const char *title = params->window_title;
@@ -86,7 +81,7 @@ sc_screen_otg_init(struct sc_screen_otg *screen,
if (screen->mouse) {
// Capture mouse on start
sc_screen_otg_set_mouse_capture(true);
sc_screen_otg_capture_mouse(screen, true);
}
return true;
@@ -198,7 +193,7 @@ sc_screen_otg_handle_event(struct sc_screen_otg *screen, SDL_Event *event) {
break;
case SDL_WINDOWEVENT_FOCUS_LOST:
if (screen->mouse) {
sc_screen_otg_set_mouse_capture(false);
sc_screen_otg_capture_mouse(screen, false);
}
break;
}
@@ -232,7 +227,8 @@ sc_screen_otg_handle_event(struct sc_screen_otg *screen, SDL_Event *event) {
if (key == cap) {
// A mouse capture key has been pressed then released:
// toggle the capture mouse mode
sc_screen_otg_toggle_mouse_capture();
sc_screen_otg_capture_mouse(screen,
!screen->mouse_captured);
}
// Mouse capture keys are never forwarded to the device
return;
@@ -244,26 +240,26 @@ sc_screen_otg_handle_event(struct sc_screen_otg *screen, SDL_Event *event) {
}
break;
case SDL_MOUSEMOTION:
if (screen->mouse && sc_screen_otg_get_mouse_capture()) {
if (screen->mouse && screen->mouse_captured) {
sc_screen_otg_process_mouse_motion(screen, &event->motion);
}
break;
case SDL_MOUSEBUTTONDOWN:
if (screen->mouse && sc_screen_otg_get_mouse_capture()) {
if (screen->mouse && screen->mouse_captured) {
sc_screen_otg_process_mouse_button(screen, &event->button);
}
break;
case SDL_MOUSEBUTTONUP:
if (screen->mouse) {
if (sc_screen_otg_get_mouse_capture()) {
if (screen->mouse_captured) {
sc_screen_otg_process_mouse_button(screen, &event->button);
} else {
sc_screen_otg_set_mouse_capture(true);
sc_screen_otg_capture_mouse(screen, true);
}
}
break;
case SDL_MOUSEWHEEL:
if (screen->mouse && sc_screen_otg_get_mouse_capture()) {
if (screen->mouse && screen->mouse_captured) {
sc_screen_otg_process_mouse_wheel(screen, &event->wheel);
}
break;

View File

@@ -18,6 +18,7 @@ struct sc_screen_otg {
SDL_Texture *texture;
// See equivalent mechanism in screen.h
bool mouse_captured;
SDL_Keycode mouse_capture_key_pressed;
};

View File

@@ -40,8 +40,9 @@ sc_usb_read_device(libusb_device *device, struct sc_usb_device *out) {
if (result < 0) {
// Log at debug level because it is expected that some non-Android USB
// devices present on the computer require special permissions
LOGD("Open USB device %04" PRIx16 ":%04" PRIx16 ": libusb error: %s",
desc.idVendor, desc.idProduct, libusb_strerror(result));
LOGD("Open USB device %04x:%04x: libusb error: %s",
(unsigned) desc.idVendor, (unsigned) desc.idProduct,
libusb_strerror(result));
return false;
}
@@ -146,8 +147,10 @@ sc_usb_devices_log(enum sc_log_level level, struct sc_usb_device *devices,
for (size_t i = 0; i < count; ++i) {
struct sc_usb_device *d = &devices[i];
const char *selection = d->selected ? "-->" : " ";
LOG(level, " %s %-18s (%04" PRIx16 ":%04" PRIx16 ") %s %s",
selection, d->serial, d->vid, d->pid, d->manufacturer, d->product);
// Convert uint16_t to unsigned because PRIx16 may not exist on Windows
LOG(level, " %s %-18s (%04x:%04x) %s %s",
selection, d->serial, (unsigned) d->vid, (unsigned) d->pid,
d->manufacturer, d->product);
}
}
@@ -188,7 +191,9 @@ sc_usb_select_device(struct sc_usb *usb, const char *serial,
LOGE("Multiple (%" SC_PRIsizet ") USB devices:", sel_count);
}
sc_usb_devices_log(SC_LOG_LEVEL_ERROR, usb_devices, count);
LOGE("Select a device via -s (--serial)");
if (!serial) {
LOGE("Specify the device via -s or --serial");
}
sc_usb_devices_destroy_all(usb_devices, count);
return false;
}
@@ -216,7 +221,7 @@ sc_usb_destroy(struct sc_usb *usb) {
libusb_exit(usb->context);
}
static int
static LIBUSB_CALL int
sc_usb_libusb_callback(libusb_context *ctx, libusb_device *device,
libusb_hotplug_event event, void *userdata) {
(void) ctx;
@@ -254,8 +259,7 @@ run_libusb_event_handler(void *data) {
static bool
sc_usb_register_callback(struct sc_usb *usb) {
if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
LOGW("On this platform, libusb does not have hotplug capability; "
"device disconnection will not be detected properly");
LOGW("libusb does not have hotplug capability");
return false;
}

View File

@@ -42,7 +42,7 @@ void
sc_usb_device_destroy(struct sc_usb_device *usb_device);
/**
* Move src to dst
* Move src to dest
*
* After this call, the content of src is undefined, except that
* sc_usb_device_destroy() can be called.

View File

@@ -1,5 +1,5 @@
#ifndef SC_BUFFER_UTIL_H
#define SC_BUFFER_UTIL_H
#ifndef BUFFER_UTIL_H
#define BUFFER_UTIL_H
#include "common.h"
@@ -7,13 +7,13 @@
#include <stdint.h>
static inline void
sc_write16be(uint8_t *buf, uint16_t value) {
buffer_write16be(uint8_t *buf, uint16_t value) {
buf[0] = value >> 8;
buf[1] = value;
}
static inline void
sc_write32be(uint8_t *buf, uint32_t value) {
buffer_write32be(uint8_t *buf, uint32_t value) {
buf[0] = value >> 24;
buf[1] = value >> 16;
buf[2] = value >> 8;
@@ -21,25 +21,25 @@ sc_write32be(uint8_t *buf, uint32_t value) {
}
static inline void
sc_write64be(uint8_t *buf, uint64_t value) {
sc_write32be(buf, value >> 32);
sc_write32be(&buf[4], (uint32_t) value);
buffer_write64be(uint8_t *buf, uint64_t value) {
buffer_write32be(buf, value >> 32);
buffer_write32be(&buf[4], (uint32_t) value);
}
static inline uint16_t
sc_read16be(const uint8_t *buf) {
buffer_read16be(const uint8_t *buf) {
return (buf[0] << 8) | buf[1];
}
static inline uint32_t
sc_read32be(const uint8_t *buf) {
buffer_read32be(const uint8_t *buf) {
return ((uint32_t) buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
}
static inline uint64_t
sc_read64be(const uint8_t *buf) {
uint32_t msb = sc_read32be(buf);
uint32_t lsb = sc_read32be(&buf[4]);
buffer_read64be(const uint8_t *buf) {
uint32_t msb = buffer_read32be(buf);
uint32_t lsb = buffer_read32be(&buf[4]);
return ((uint64_t) msb << 32) | lsb;
}

View File

@@ -1,67 +0,0 @@
#include "version.h"
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
#ifdef HAVE_V4L2
# include <libavdevice/avdevice.h>
#endif
#ifdef HAVE_USB
# include <libusb-1.0/libusb.h>
#endif
void
scrcpy_print_version(void) {
printf("\nDependencies (compiled / linked):\n");
SDL_version sdl;
SDL_GetVersion(&sdl);
printf(" - SDL: %u.%u.%u / %u.%u.%u\n",
SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL,
(unsigned) sdl.major, (unsigned) sdl.minor, (unsigned) sdl.patch);
unsigned avcodec = avcodec_version();
printf(" - libavcodec: %u.%u.%u / %u.%u.%u\n",
LIBAVCODEC_VERSION_MAJOR,
LIBAVCODEC_VERSION_MINOR,
LIBAVCODEC_VERSION_MICRO,
AV_VERSION_MAJOR(avcodec),
AV_VERSION_MINOR(avcodec),
AV_VERSION_MICRO(avcodec));
unsigned avformat = avformat_version();
printf(" - libavformat: %u.%u.%u / %u.%u.%u\n",
LIBAVFORMAT_VERSION_MAJOR,
LIBAVFORMAT_VERSION_MINOR,
LIBAVFORMAT_VERSION_MICRO,
AV_VERSION_MAJOR(avformat),
AV_VERSION_MINOR(avformat),
AV_VERSION_MICRO(avformat));
unsigned avutil = avutil_version();
printf(" - libavutil: %u.%u.%u / %u.%u.%u\n",
LIBAVUTIL_VERSION_MAJOR,
LIBAVUTIL_VERSION_MINOR,
LIBAVUTIL_VERSION_MICRO,
AV_VERSION_MAJOR(avutil),
AV_VERSION_MINOR(avutil),
AV_VERSION_MICRO(avutil));
#ifdef HAVE_V4L2
unsigned avdevice = avdevice_version();
printf(" - libavdevice: %u.%u.%u / %u.%u.%u\n",
LIBAVDEVICE_VERSION_MAJOR,
LIBAVDEVICE_VERSION_MINOR,
LIBAVDEVICE_VERSION_MICRO,
AV_VERSION_MAJOR(avdevice),
AV_VERSION_MINOR(avdevice),
AV_VERSION_MICRO(avdevice));
#endif
#ifdef HAVE_USB
const struct libusb_version *usb = libusb_get_version();
// The compiled version may not be known
printf(" - libusb: - / %u.%u.%u\n",
(unsigned) usb->major, (unsigned) usb->minor, (unsigned) usb->micro);
#endif
}

View File

@@ -1,9 +0,0 @@
#ifndef SC_VERSION_H
#define SC_VERSION_H
#include "common.h"
void
scrcpy_print_version(void);
#endif

View File

@@ -8,7 +8,7 @@ static void test_buffer_write16be(void) {
uint16_t val = 0xABCD;
uint8_t buf[2];
sc_write16be(buf, val);
buffer_write16be(buf, val);
assert(buf[0] == 0xAB);
assert(buf[1] == 0xCD);
@@ -18,7 +18,7 @@ static void test_buffer_write32be(void) {
uint32_t val = 0xABCD1234;
uint8_t buf[4];
sc_write32be(buf, val);
buffer_write32be(buf, val);
assert(buf[0] == 0xAB);
assert(buf[1] == 0xCD);
@@ -30,7 +30,7 @@ static void test_buffer_write64be(void) {
uint64_t val = 0xABCD1234567890EF;
uint8_t buf[8];
sc_write64be(buf, val);
buffer_write64be(buf, val);
assert(buf[0] == 0xAB);
assert(buf[1] == 0xCD);
@@ -45,7 +45,7 @@ static void test_buffer_write64be(void) {
static void test_buffer_read16be(void) {
uint8_t buf[2] = {0xAB, 0xCD};
uint16_t val = sc_read16be(buf);
uint16_t val = buffer_read16be(buf);
assert(val == 0xABCD);
}
@@ -53,7 +53,7 @@ static void test_buffer_read16be(void) {
static void test_buffer_read32be(void) {
uint8_t buf[4] = {0xAB, 0xCD, 0x12, 0x34};
uint32_t val = sc_read32be(buf);
uint32_t val = buffer_read32be(buf);
assert(val == 0xABCD1234);
}
@@ -62,7 +62,7 @@ static void test_buffer_read64be(void) {
uint8_t buf[8] = {0xAB, 0xCD, 0x12, 0x34,
0x56, 0x78, 0x90, 0xEF};
uint64_t val = sc_read64be(buf);
uint64_t val = buffer_read64be(buf);
assert(val == 0xABCD1234567890EF);
}

View File

@@ -21,3 +21,5 @@ ffmpeg_avformat = 'avformat-58'
ffmpeg_avutil = 'avutil-56'
prebuilt_ffmpeg = 'ffmpeg-win32-4.3.1'
prebuilt_sdl2 = 'SDL2-2.0.20/i686-w64-mingw32'
prebuilt_libusb_root = 'libusb-1.0.25'
prebuilt_libusb = prebuilt_libusb_root + '/MinGW32'

View File

@@ -21,3 +21,5 @@ ffmpeg_avformat = 'avformat-59'
ffmpeg_avutil = 'avutil-57'
prebuilt_ffmpeg = 'ffmpeg-win64-5.0'
prebuilt_sdl2 = 'SDL2-2.0.20/x86_64-w64-mingw32'
prebuilt_libusb_root = 'libusb-1.0.25'
prebuilt_libusb = prebuilt_libusb_root + '/MinGW64'

View File

@@ -12,7 +12,7 @@ echo "$PREBUILT_SERVER_SHA256 scrcpy-server" | sha256sum --check
echo "[scrcpy] Building client..."
rm -rf "$BUILDDIR"
meson "$BUILDDIR" --buildtype=release --strip -Db_lto=true \
meson "$BUILDDIR" --buildtype release --strip -Db_lto=true \
-Dprebuilt_server=scrcpy-server
cd "$BUILDDIR"
ninja

View File

@@ -4,5 +4,3 @@ option('prebuilt_server', type: 'string', description: 'Path of the prebuilt ser
option('portable', type: 'boolean', value: false, description: 'Use scrcpy-server from the same directory as the scrcpy executable')
option('server_debugger', type: 'boolean', value: false, description: 'Run a server debugger and wait for a client to be attached')
option('server_debugger_method', type: 'combo', choices: ['old', 'new'], value: 'new', description: 'Select the debugger method (Android < 9: "old", Android >= 9: "new")')
option('v4l2', type: 'boolean', value: true, description: 'Enable V4L2 feature when supported')
option('usb', type: 'boolean', value: true, description: 'Enable HID/OTG features when supported')

28
prebuilt-deps/prepare-libusb.sh Executable file
View File

@@ -0,0 +1,28 @@
#!/usr/bin/env bash
set -e
DIR=$(dirname ${BASH_SOURCE[0]})
cd "$DIR"
. common
mkdir -p "$PREBUILT_DATA_DIR"
cd "$PREBUILT_DATA_DIR"
DEP_DIR=libusb-1.0.25
FILENAME=libusb-1.0.25.7z
SHA256SUM=3d1c98416f454026034b2b5d67f8a294053898cb70a8b489874e75b136c6674d
if [[ -d "$DEP_DIR" ]]
then
echo "$DEP_DIR" found
exit 0
fi
get_file "https://github.com/libusb/libusb/releases/download/v1.0.25/$FILENAME" "$FILENAME" "$SHA256SUM"
mkdir "$DEP_DIR"
cd "$DEP_DIR"
7z x "../$FILENAME" \
MinGW32/dll/libusb-1.0.dll \
MinGW64/dll/libusb-1.0.dll \
include /

View File

@@ -63,14 +63,10 @@ build-server:
ninja -C "$(SERVER_BUILD_DIR)"
prepare-deps-win32:
@app/prebuilt-deps/prepare-adb.sh
@app/prebuilt-deps/prepare-sdl.sh
@app/prebuilt-deps/prepare-ffmpeg-win32.sh
prepare-deps-win64:
@app/prebuilt-deps/prepare-adb.sh
@app/prebuilt-deps/prepare-sdl.sh
@app/prebuilt-deps/prepare-ffmpeg-win64.sh
@prebuilt-deps/prepare-adb.sh
@prebuilt-deps/prepare-sdl.sh
@prebuilt-deps/prepare-ffmpeg-win32.sh
@prebuilt-deps/prepare-libusb.sh
build-win32: prepare-deps-win32
[ -d "$(WIN32_BUILD_DIR)" ] || ( mkdir "$(WIN32_BUILD_DIR)" && \
@@ -81,6 +77,11 @@ build-win32: prepare-deps-win32
-Dportable=true )
ninja -C "$(WIN32_BUILD_DIR)"
prepare-deps-win64:
@prebuilt-deps/prepare-adb.sh
@prebuilt-deps/prepare-sdl.sh
@prebuilt-deps/prepare-ffmpeg-win64.sh
build-win64: prepare-deps-win64
[ -d "$(WIN64_BUILD_DIR)" ] || ( mkdir "$(WIN64_BUILD_DIR)" && \
meson "$(WIN64_BUILD_DIR)" \
@@ -98,15 +99,16 @@ dist-win32: build-server build-win32
cp data/scrcpy-noconsole.vbs "$(DIST)/$(WIN32_TARGET_DIR)"
cp data/icon.png "$(DIST)/$(WIN32_TARGET_DIR)"
cp data/open_a_terminal_here.bat "$(DIST)/$(WIN32_TARGET_DIR)"
cp app/prebuilt-deps/data/ffmpeg-win32-4.3.1/bin/avutil-56.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp app/prebuilt-deps/data/ffmpeg-win32-4.3.1/bin/avcodec-58.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp app/prebuilt-deps/data/ffmpeg-win32-4.3.1/bin/avformat-58.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp app/prebuilt-deps/data/ffmpeg-win32-4.3.1/bin/swresample-3.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp app/prebuilt-deps/data/ffmpeg-win32-4.3.1/bin/swscale-5.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp app/prebuilt-deps/data/platform-tools-31.0.3/adb.exe "$(DIST)/$(WIN32_TARGET_DIR)/"
cp app/prebuilt-deps/data/platform-tools-31.0.3/AdbWinApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp app/prebuilt-deps/data/platform-tools-31.0.3/AdbWinUsbApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp app/prebuilt-deps/data/SDL2-2.0.20/i686-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/data/ffmpeg-win32-4.3.1/bin/avutil-56.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/data/ffmpeg-win32-4.3.1/bin/avcodec-58.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/data/ffmpeg-win32-4.3.1/bin/avformat-58.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/data/ffmpeg-win32-4.3.1/bin/swresample-3.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/data/ffmpeg-win32-4.3.1/bin/swscale-5.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/data/platform-tools-31.0.3/adb.exe "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/data/platform-tools-31.0.3/AdbWinApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/data/platform-tools-31.0.3/AdbWinUsbApi.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/data/SDL2-2.0.20/i686-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
cp prebuilt-deps/data/libusb-1.0.25/MinGW32/dll/libusb-1.0.dll "$(DIST)/$(WIN32_TARGET_DIR)/"
dist-win64: build-server build-win64
mkdir -p "$(DIST)/$(WIN64_TARGET_DIR)"
@@ -116,15 +118,16 @@ dist-win64: build-server build-win64
cp data/scrcpy-noconsole.vbs "$(DIST)/$(WIN64_TARGET_DIR)"
cp data/icon.png "$(DIST)/$(WIN64_TARGET_DIR)"
cp data/open_a_terminal_here.bat "$(DIST)/$(WIN64_TARGET_DIR)"
cp app/prebuilt-deps/data/ffmpeg-win64-5.0/bin/avutil-57.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp app/prebuilt-deps/data/ffmpeg-win64-5.0/bin/avcodec-59.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp app/prebuilt-deps/data/ffmpeg-win64-5.0/bin/avformat-59.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp app/prebuilt-deps/data/ffmpeg-win64-5.0/bin/swresample-4.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp app/prebuilt-deps/data/ffmpeg-win64-5.0/bin/swscale-6.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp app/prebuilt-deps/data/platform-tools-31.0.3/adb.exe "$(DIST)/$(WIN64_TARGET_DIR)/"
cp app/prebuilt-deps/data/platform-tools-31.0.3/AdbWinApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp app/prebuilt-deps/data/platform-tools-31.0.3/AdbWinUsbApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp app/prebuilt-deps/data/SDL2-2.0.20/x86_64-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/data/ffmpeg-win64-5.0/bin/avutil-57.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/data/ffmpeg-win64-5.0/bin/avcodec-59.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/data/ffmpeg-win64-5.0/bin/avformat-59.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/data/ffmpeg-win64-5.0/bin/swresample-4.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/data/ffmpeg-win64-5.0/bin/swscale-6.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/data/platform-tools-31.0.3/adb.exe "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/data/platform-tools-31.0.3/AdbWinApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/data/platform-tools-31.0.3/AdbWinUsbApi.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/data/SDL2-2.0.20/x86_64-w64-mingw32/bin/SDL2.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
cp prebuilt-deps/data/libusb-1.0.25/MinGW64/dll/libusb-1.0.dll "$(DIST)/$(WIN64_TARGET_DIR)/"
zip-win32: dist-win32
cd "$(DIST)/$(WIN32_TARGET_DIR)"; \

View File

@@ -21,7 +21,6 @@ public class Options {
private boolean powerOffScreenOnClose;
private boolean clipboardAutosync = true;
private boolean downsizeOnError = true;
private boolean cleanup = true;
// Options not used by the scrcpy client, but useful to use scrcpy-server directly
private boolean sendDeviceMeta = true; // send device name and size
@@ -156,14 +155,6 @@ public class Options {
this.downsizeOnError = downsizeOnError;
}
public boolean getCleanup() {
return cleanup;
}
public void setCleanup(boolean cleanup) {
this.cleanup = cleanup;
}
public boolean getSendDeviceMeta() {
return sendDeviceMeta;
}

View File

@@ -28,8 +28,7 @@ public class ScreenEncoder implements Device.RotationListener {
// Keep the values in descending order
private static final int[] MAX_SIZE_FALLBACK = {2560, 1920, 1600, 1280, 1024, 800};
private static final long PACKET_FLAG_CONFIG = 1L << 63;
private static final long PACKET_FLAG_KEY_FRAME = 1L << 62;
private static final int NO_PTS = -1;
private final AtomicBoolean rotationChanged = new AtomicBoolean();
private final ByteBuffer headerBuffer = ByteBuffer.allocate(12);
@@ -184,15 +183,12 @@ public class ScreenEncoder implements Device.RotationListener {
long pts;
if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
pts = PACKET_FLAG_CONFIG; // non-media data packet
pts = NO_PTS; // non-media data packet
} else {
if (ptsOrigin == 0) {
ptsOrigin = bufferInfo.presentationTimeUs;
}
pts = bufferInfo.presentationTimeUs - ptsOrigin;
if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_KEY_FRAME) != 0) {
pts |= PACKET_FLAG_KEY_FRAME;
}
}
headerBuffer.putLong(pts);

View File

@@ -51,13 +51,11 @@ public final class Server {
}
}
if (options.getCleanup()) {
try {
CleanUp.configure(options.getDisplayId(), restoreStayOn, mustDisableShowTouchesOnCleanUp, restoreNormalPowerMode,
options.getPowerOffScreenOnClose());
} catch (IOException e) {
Ln.e("Could not configure cleanup", e);
}
try {
CleanUp.configure(options.getDisplayId(), restoreStayOn, mustDisableShowTouchesOnCleanUp, restoreNormalPowerMode,
options.getPowerOffScreenOnClose());
} catch (IOException e) {
Ln.e("Could not configure cleanup", e);
}
}
@@ -245,10 +243,6 @@ public final class Server {
boolean downsizeOnError = Boolean.parseBoolean(value);
options.setDownsizeOnError(downsizeOnError);
break;
case "cleanup":
boolean cleanup = Boolean.parseBoolean(value);
options.setCleanup(cleanup);
break;
case "send_device_meta":
boolean sendDeviceMeta = Boolean.parseBoolean(value);
options.setSendDeviceMeta(sendDeviceMeta);