On the scrcpy-deps repo, I built FFmpeg 5.1.2 binaries for Windows with
only the features used by scrcpy.
For comparison, here are the sizes of the dll for FFmpeg 5.1.2:
- before: 89M
- after: 4.7M
It also allows to upgrade the old FFmpeg version (4.3.1) used for win32.
Refs <https://github.com/rom1v/scrcpy-deps>
Refs <https://github.com/Genymobile/scrcpy/issues/1753>
On Android 11, it is possible to start the capture only when the running
app is in foreground. But scrcpy is not an app, it's a Java application
started from shell.
As a workaround, start an existing Android shell existing activity just
to start the capture, then close it immediately.
Co-authored-by: Romain Vimont <rom@rom1v.com>
Signed-off-by: Romain Vimont <rom@rom1v.com>
Play the decoded audio using SDL.
The audio player frame sink receives the audio frames, resample them
and write them to a byte buffer (introduced by this commit).
On SDL audio callback (from an internal SDL thread), copy samples from
this byte buffer to the SDL audio buffer.
The byte buffer is protected by the SDL_AudioDeviceLock(), but it has
been designed so that the producer and the consumer may write and read
in parallel, provided that they don't access the same slices of the
ring-buffer buffer.
Co-authored-by: Simon Chan <1330321+yume-chan@users.noreply.github.com>
If there is exactly one producer, then it can assume that the remaining
space in the buffer will only increase until it write something.
This assumption may allow the producer to write to the buffer (up to a
known safe size) without any synchronization mechanism, thus allowing
to read and write different parts of the buffer in parallel.
The producer can then commit the write with lock held, and update its
knowledge of the safe empty remaining space.
When audio capture fails on the device, scrcpy continue mirroring the
video stream. This allows to enable audio by default only when
supported.
However, if an audio configuration occurs (for example the user
explicitly selected an unknown audio encoder), this must be treated as
an error and scrcpy must exit.
If no bit-rate is passed, let the server use the default value (8Mbps).
This avoids to define a default value on both sides, and to pass the
default bit-rate as an argument when starting the server.
The permission "android.permission.RECORD_AUDIO" has been added for
shell in Android 11.
Moreover, on lower versions, it may make the server segfault on the
device (happened on a Nexus 5 with Android 6.0.1).
Refs <4feeee8891%5E%21/>
By default, audio is enabled (--no-audio must be explicitly passed to
disable it).
However, some devices may not support audio capture (typically devices
below Android 11, or Android 11 when the shell application is not
foreground on start).
In that case, make the server notify the client to dynamically disable
audio forwarding so that it does not wait indefinitely for an audio
stream.
Also disable audio on unknown codec or missing decoder on the
client-side, for the same reasons.
For video streams (at least H.264 and H.265), the config packet
containing SPS/PPS must be prepended to the next packet (the following
keyframe).
For audio streams (at least OPUS), they must not be merged.
Create an AudioRecorder to capture the audio source REMOTE_SUBMIX.
For now, the captured packets are just logged into the console.
Co-authored-by: Romain Vimont <rom@rom1v.com>
Signed-off-by: Romain Vimont <rom@rom1v.com>
When audio is enabled, open a new socket to send the audio stream from
the device to the client.
Co-authored-by: Romain Vimont <rom@rom1v.com>
Signed-off-by: Romain Vimont <rom@rom1v.com>
Audio will be enabled by default (when supported). Add an option to
disable it.
Co-authored-by: Romain Vimont <rom@rom1v.com>
Signed-off-by: Romain Vimont <rom@rom1v.com>
Remove USER_ID from ServiceManager, and replace it by a constant in
FakeContext.
This is the same as android.os.Process.ROOT_UID, but this constant has
been introduced in API 29.
Since scrcpy-server is not an Android application (it's a java
executable), it has no Context.
Some features will require a Context instance to get the package name
and the UID. Add a FakeContext for this purpose.
Co-authored-by: Romain Vimont <rom@rom1v.com>
Signed-off-by: Romain Vimont <rom@rom1v.com>
The Callbacks interface notifies new packets. But in addition, the
screen encoder will need to write headers on start.
We could add a function onStart(), but for simplicity, just remove the
interface, which brings no value, and call the streamer directly.
Refs 87972e2022
On any error, all previously opened sockets must be closed.
Handle these errors in a single catch-block. Currently, there are only 2
sockets, but this will simplify even more with more sockets.
Note: this commit is better displayed with --ignore-space-change (-b).
The recorder opened the target file from the packet sink open()
callback, called by the demuxer. Only then the recorder thread was
started.
One golden rule for the recorder is to never block the demuxer for I/O,
because it would impact mirroring. This rule is respected on recording
packets, but not for the initial recorder opening.
Therefore, start the recorder thread from sc_recorder_init(), open the
file immediately from the recorder thread, then make it wait for the
stream to start (on packet sink open()).
Now that the recorder can report errors directly (rather than making the
demuxer call fail), it is possible to report file opening error even
before the packet sink is open.
The recorder has two initialization phases: one to initialize the
concrete recorder object, and one to open its packet_sink trait.
Initialize mutex and condvar as part of the object initialization.
If there were several packet_sink traits, the mutex and condvar would
still be initialized only once.
Stop scrcpy on recorder errors.
It was previously indirectly stopped by the demuxer, which failed to
push packets to a recorder in error. Report it directly instead:
- it avoids to wait for the next demuxer call;
- it will allow to open the target file from a separate thread and stop
immediately on any I/O error.
User-friendly error messages are printed on specific configuration
exceptions. In that case, do not print the stacktrace.
Also handle the user-friendly error message directly where the error
occurs, and print multiline messages in a single log call, to avoid
confusing interleaving.
As reported by gradle:
> Setting the namespace via a source AndroidManifest.xml's package
> attribute is deprecated.
>
> Please instead set the namespace (or testNamespace) in the module's
> build.gradle file, as described here:
> https://developer.android.com/studio/build/configure-app-module#set-namespace
Running scrcpy --tcpip on a device already connected via TCP/IP did not
initialize server->serial.
As a consequence, in debug mode, an assertion failed:
scrcpy: ../app/src/server.c:770: run_server: Assertion
`server->serial' failed.
In release mode, scrcpy failed with this error:
adb: -s requires an argument
Scrcpy does not use FFmpeg network features. Initialize network locally
instead (useful only for Windows).
The include block has been moved to fix the following warning:
Please include winsock2.h before windows.h
DesktopConnection implements Closeable, so it is implicitly closed after
its try-with-resources block. Closing the DesktopConnection shutdowns
the sockets, so it is necessary in particular to wake up blocking read()
calls from the controller.
But the controller thread was joined before the DesktopConnection was
closed, causing a deadlock. To fix the problem, join the controller
thread only after the DesktopConnection is closed.
Refs 400a1c69b1
When a call to a packet or frame sink fails, do not log the error on the
caller side: either the "failure" is expected (explicitly stopped) or it
must be logged by the packet or frame sink implementation.
On close, the client closes the socket. This wakes up socket blocking
calls on the server-side, by throwing an exception. Since this exception
is expected, it was not logged.
However, other IOExceptions might occur, which must not be ignored. For
that purpose, log only IOException when they are not caused by an EPIPE
error.
The PTS received from MediaCodec are expressed relative to an arbitrary
clock origin. We consider the PTS of the first frame to be 0, and the
PTS of every other frame is relative to this first PTS (note that the
PTS is only used for recording, it is ignored for mirroring).
For simplicity, this relative PTS was computed on the server-side.
To prepare support for multiple stream (video and audio), send the
packet with its original PTS, and handle the PTS offset on the
client-side (by the recorder).
Since we can't know in advance which stream will produce the first
packet with the lowest PTS (a packet received later on one stream may
have a PTS lower than a packet received earlier on another stream),
computing the PTS on the server-side would require unnecessary waiting.
On mouse click events:
- the first button pressed must first generate ACTION_DOWN;
- all button pressed (including the first one) must generate
ACTION_BUTTON_PRESS;
- all button released (including the last one) must generate
ACTION_BUTTON_RELEASE;
- the last button released must in addition generate ACTION_UP.
Otherwise, Chrome does not work properly.
Fixes#3635 <https://github.com/Genymobile/scrcpy/issues/3635>
Signed-off-by: Romain Vimont <rom@rom1v.com>
If the pointer is a mouse, the pointer is UP only when no buttons are
pressed (not when a button is released, because there might be other
buttons still pressed).
Refs #3635 <https://github.com/Genymobile/scrcpy/issues/3635>
Signed-off-by: Romain Vimont <rom@rom1v.com>
MediaCodec may fail spuriously, typically when stopping an encoding and
starting a new one immediately (for example on device rotation).
In that case, retry a few times, in many cases it should work.
Refs #3693 <https://github.com/Genymobile/scrcpy/issues/3693>
For the initial connection between the device and the computer, an adb
tunnel is established (with "adb reverse" or "adb forward").
The device-side of the tunnel is a local socket having the hard-coded
name "scrcpy". This may cause issues when several scrcpy instances are
started in a few seconds for the same device, since they will try to
bind the same name.
To avoid conflicts, make the client generate a random UID, and append
this UID to the local socket name ("scrcpy_01234567").
Use av_packet_ref() to reference the packet without copy.
This also simplifies the logic, by making the "offset" variable and the
memcpy() call local to the if-block.
Right click and middle click require the source device to be a mouse,
not a touchscreen. Therefore, the source device was changed only when a
button other than the primary button was pressed (see
adc547fa6e).
However, this led to inconsistencies between the ACTION_DOWN when a
secondary button is pressed (with a mouse as source device) and the
matching ACTION_UP when the secondary button is released (with a
touchscreen as source device, because then there is no button pressed).
To avoid the problem in all cases, force a mouse as source device when
--forward-all-clicks is set.
Concretely, for mouse events in --forward-all-clicks mode:
- device source is set to InputDevice.SOURCE_MOUSE;
- motion event toolType is set to MotionEvent.TOOL_TYPE_MOUSE;
Otherwise (when --forward-all-clicks is unset, or for real touch
events), finger events are injected:
- device source is set to InputDevice.SOURCE_TOUCHSCREEN;
- motion event toolType is set to MotionEvent.TOOL_TYPE_FINGER.
Fixes#3568 <https://github.com/Genymobile/scrcpy/issues/3568>
PR #3579 <https://github.com/Genymobile/scrcpy/pull/3579>
Co-authored-by: Romain Vimont <rom@rom1v.com>
Signed-off-by: Romain Vimont <rom@rom1v.com>
This fixes the following warning:
> WARNING: Running the setup command as `meson [options]` instead of
> `meson setup [options]` is ambiguous and deprecated.
If the current adb port is not 5555 (typically 0 because it is not in
TCP/IP mode), --tcpip automatically executes (among other commands):
adb tcpip 5555
In case adb was already listening on another port, this command forced
to listen on 5555, and the connection should still succeed.
But this reconfiguration might be inconvenient for the user. If adb is
already in TCP/IP mode, use the current enabled port without
reconfiguration.
Fixes#3591 <https://github.com/Genymobile/scrcpy/issues/3591>
Mandatory arguments may be passed in either of these two forms:
1. --key value
2. --key=value
Optional argument may only be passed in the second form.
For consistency, always document using --key=value.
Refs f76fe2c0d4
There were exactly one instance of ServiceManager and Settings, stored
in Device.
Since a Device instance is not created by the CleanUp executable, it was
not straightforward to call wrapper methods on cleanup.
Remove this artificial restriction and expose them publicly via static
methods (this is equivalent to expose a singleton, but less verbose).
Add a launcher which opens a terminal, and keep it open in case of
errors (so that the user has time to read error messages).
The behavior is the same as scrcpy-console.bat on Windows.
PR #3351 <https://github.com/Genymobile/scrcpy/pull/3351>
This lowers the barrier to contribute to translations, and frees up my
maintenance time used to review and merge translations and their updates
in many languages.
On Windows and macOS, resizing blocks the event loop. Handling it
properly would require the same workaround as done in screen.c.
This reverts commit 436b368f9d.
The previous commit replaced the IInterface instance (the "input"
service) by the InputManager instance (retrieved by
InputManager.getInstance()).
Both define an "injectInputEvent" method, but the alternate version
(probably) does not concern the InputManager.
This reverts commit b7a06278fe.
PR #3190 <https://github.com/Genymobile/scrcpy/pull/3190>
We must distinguish 3 cases for await_for_server():
- an error occurred
- no error occurred, the device is connected
- no error occurred, the device is not connected (user requested to
quit)
For this purpose, use an additional output parameter to indicate if the
device is connected (only set when no error occurs).
Refs #3085 <https://github.com/Genymobile/scrcpy/pull/3085>
Mention that the device must be plugged via USB before configuring
TCP/IP connections.
It wasn't obvious that the device should be first plugged before running
scrcpy wirelessly, especially to those who aren't very familiar with
adb.
Note from committer: add this new step with index 0 to make the diff
readable, the next commit will renumber all the steps.
PR #1303 <https://github.com/Genymobile/scrcpy/pull/1303>
Signed-off-by: Romain Vimont <rom@rom1v.com>
For simplicity, the parsing of `adb devices -l` output is performed in a
single pass on the whole output.
This output was limited to 4096 bytes. Since there are about 100 chars
per device line, this limited the number of connected devices to ~40.
Increase to 65536 bytes to avoid a limitation in practice.
PR #3035 <https://github.com/Genymobile/scrcpy/pull/3035>
The files in data/ are specific to the client app (not the server).
This also avoids to reference the parent directory (../) from
app/meson.build.
Refs 8d583d36e2
All adb commands are executed with an "interruptor", so that they can be
interrupted on Ctrl+C.
Make this interruptor optional, so that we could call "adb kill-server"
in OTG mode. This command always returns almost immediately anyway.
Ideally, we should make all blocking calls interruptible (including
libusb calls, by using the asynchronous API), but it's a lot of work,
and in practice it works well enough.
PR #3011 <https://github.com/Genymobile/scrcpy/pull/3011>
USB device disconnection is detected via a hotplug callback when it is
supported.
In addition, report disconnection on libusb calls returning
LIBUSB_ERROR_NO_DEVICE or LIBUSB_ERROR_NOT_FOUND. This allows to detect
disconnection after a libusb call when hotplug is not available.
PR #3011 <https://github.com/Genymobile/scrcpy/pull/3011>
There were three links that weren't displayed correctly due to incorrect
references:
- the Windows release link to `README.md#windows`
- 2 links that expected a German reference but got an English reference
PR #3026 <https://github.com/Genymobile/scrcpy/pull/3026>
Signed-off-by: Romain Vimont <rom@rom1v.com>
The value of sc_tick_now() has microsecond precision, but
sc_cond_timedwait() has only millisecond precision.
To guarantee that sc_tick_now() >= deadline when sc_cond_timedwait()
returns due to timeout, round up to the next millisecond.
This avoids to call a non-blocking sc_cond_timedwait() in a loop for no
reason until a target deadline during up to 1 millisecond.
Refs 682a691173
The type uint32_t is not sufficient to store the result of
sc_tick_now().
As a consequence, the FPS counter entered a live loop and caused a lock
starvation (deadlock in practice).
Refs ec871dd3f5
Refs 682a691173
A special PTS value was used to encode a config packet.
To prepare for adding more flags, use the most significant bits of the
PTS field to store flags.
The relative mouse mode is tracked by SDL, and accessible via
SDL_GetRelativeMouseMode().
This is more robust in case SDL changes the relative mouse mode on its
own.
The prebuilt dependencies are specific to the client app (not the
server).
This also avoids to reference the parent directory (../) from
app/meson.build.
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).
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:
- -d/--select-usb: select the single device connected over USB
- -e/--select-tcpip: select the single device connected over TCP/IP
PR #3005 <https://github.com/Genymobile/scrcpy/pull/3005>
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.
PR #3005 <https://github.com/Genymobile/scrcpy/pull/3005>
This does nothing if the adb daemon is already started, but allows to
print any output/errors to the console.
Otherwise, the daemon starting would occur during `adb devices`, which
does not output to the console because the result is parsed.
PR #3005 <https://github.com/Genymobile/scrcpy/pull/3005>
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.
PR #3005 <https://github.com/Genymobile/scrcpy/pull/3005>
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.
PR #3005 <https://github.com/Genymobile/scrcpy/pull/3005>
One log macro was provided for each log level (LOGV(), LOGD(), LOGI(),
LOGW(), LOGE()).
Add a generic macro LOG(LEVEL, ...) accepting a log level as parameter,
so that it is possible to write logging wrappers.
PR #3005 <https://github.com/Genymobile/scrcpy/pull/3005>
This util function was error-prone:
- it accepted a buffer as parameter (not necessarily a NUL-terminated
string) and its length (including the NUL char, if any);
- it wrote '\0' over the last character of the buffer, so the last
character was lost if the buffer was not a NUL-terminated string, and
even worse, it caused undefined behavior if the length was empty;
- it returned the length of the resulting NUL-terminated string,
which was inconsistent with the input buffer length.
In addition, it was not necessarily optimal:
- it wrote '\0' twice;
- it required to know the buffer length, that is the input string
length + 1, in advance.
Remove this function, and let the client use strcspn() manually.
The function assumed that the raw output of "adb connect" was a
NUL-terminated string, but it is not the case.
It this output did not end with a space or a new line character, then
sc_str_truncate() would write '\0' over the last character. Even worse,
if the output was empty, then sc_str_truncate() would write
out-of-bounds.
Avoid the error-prone sc_str_truncate() util function.
The function assumed that the raw output of "adb get-serialno" was a
NUL-terminated string, but it is not the case.
It this output did not end with a space or a new line character, then
sc_str_truncate() would write '\0' over the last character. Even worse,
if the output was empty, then sc_str_truncate() would write
out-of-bounds.
Avoid the error-prone sc_str_truncate() util function.
The function assumed that the raw output of "adb getprop" was a
NUL-terminated string, but it is not the case.
It this output did not end with a space or a new line character, then
sc_str_truncate() would write '\0' over the last character. Even worse,
if the output was empty, then sc_str_truncate() would write
out-of-bounds.
Avoid the error-prone sc_str_truncate() util function.
The parser assumed that its input was a NUL-terminated string, but it
was not the case: it is just the raw output of "adb devices ip route".
In practice, it was harmless, since the output always ended with '\n'
(which was replaced by '\0' on truncation), but it was incorrect
nonetheless.
Always write a '\0' at the end of the buffer, and explicitly parse as a
NUL-terminated string. For that purpose, avoid the error-prone
sc_str_truncate() util function.
Before starting the server, the actual device serial (possibly its
ip:port if it's over TCP/IP) must be known.
A serial might be requested via -s/--serial (stored in the
sc_server_params), but the actual serial may change afterwards:
- if none is provided, then it is retrieved with "adb get-serialno";
- if --tcpip is requested, then the final serial will be the target
ip:port.
The requested serial was overwritten by the actual serial in the
sc_server_params struct, which was a bit hacky.
Instead, store a separate serial field in sc_server (and rename the one
from sc_server_params to "req_serial" to avoid confusion).
Now that providing a serial is mandatory for adb commands where it is
relevant, the whole argv array may be built statically, without
allocations at runtime.
If no serial is passed, then the command would work if there is exactly
one device connected, but will fail with multiple devices.
To avoid such cases, ensure that a serial is always provided.
On Windows, adb is provided in the release archive. Most missing adb
issues come from users setting the ADB environment variable to an
incorrect value (on all platforms).
Suggesting to install platform-tools to solve the problem will just make
things worse (there will be one more adb in yet another location).
The new retry mechanism with a lower definition only worked if the error
occurred during encode(). For example:
java.lang.IllegalStateException
at android.media.MediaCodec.native_dequeueOutputBuffer(Native Method)
at android.media.MediaCodec.dequeueOutputBuffer(MediaCodec.java:3452)
at com.genymobile.scrcpy.ScreenEncoder.encode(ScreenEncoder.java:114)
at com.genymobile.scrcpy.ScreenEncoder.internalStreamScreen(ScreenEncoder.java:95)
at com.genymobile.scrcpy.ScreenEncoder.streamScreen(ScreenEncoder.java:61)
at com.genymobile.scrcpy.Server.scrcpy(Server.java:80)
at com.genymobile.scrcpy.Server.main(Server.java:255)
However, MediaCodec may also fail before encoding, during configure() or
start(). For example:
android.media.MediaCodec$CodecException: Error 0xfffffc0e
at android.media.MediaCodec.native_configure(Native Method)
at android.media.MediaCodec.configure(MediaCodec.java:1956)
at android.media.MediaCodec.configure(MediaCodec.java:1885)
at com.genymobile.scrcpy.ScreenEncoder.configure(ScreenEncoder.java:158)
at com.genymobile.scrcpy.ScreenEncoder.streamScreen(ScreenEncoder.java:68)
at com.genymobile.scrcpy.Server.scrcpy(Server.java:28)
at com.genymobile.scrcpy.Server.main(Server.java:110)
Also downscale and retry in these cases.
Refs #2947 <https://github.com/Genymobile/scrcpy/pull/2947>
Refs #2988 <https://github.com/Genymobile/scrcpy/issues/2988>
PR #2990 <https://github.com/Genymobile/scrcpy/pull/2990>
The function was initially implemented to truncate lines, but was later
generalized to accept custom delimiters. The whole documentation has not
been updated accordingly.
Refs 9619ade706
This aims to fix two issues with the previous implementation:
1. the whole content of downloaded archives were extracted, while only
few files are necessary;
2. the archives were extracted in the prebuild-deps/ directory as is.
As a consequence of (2), the actual directory name relied on the root
directory of the archive. For adb, this root directory was always
"platform-tools", so when bumping the adb version, the target directory
already existed and the dependency was not upgraded (the old one had to
be removed manually).
Expose common function to download a file and check its checksum, but
let the custom script for each dependency extract only the needed files
and reorganize the content if necessary.
Add an option --otg to run scrcpy with only physical keyboard and mouse
simulation (HID over AOA), without mirroring and without requiring adb.
To avoid adding complexity into the scrcpy initialization and screen
implementation, OTG mode is implemented totally separately, with a
separate window.
PR #2974 <https://github.com/Genymobile/scrcpy/pull/2974>
Input events helpers to convert from SDL events to scrcpy events were
implemented in input_manager. To reuse them for OTG mode, move them to
input_events.h.
PR #2974 <https://github.com/Genymobile/scrcpy/pull/2974>
The device disconnection is detected when the video socket closes.
In order to introduce an OTG mode (HID events) without mirroring (and
without server), we must be able to detect USB device disconnection.
This feature will only be used in OTG mode.
PR #2974 <https://github.com/Genymobile/scrcpy/pull/2974>
Acksync is used to delay HID events until some request (in practice,
device clipboard synchronization) is acknowledged by the device.
This mechanism will not be necessary for OTG mode.
PR #2974 <https://github.com/Genymobile/scrcpy/pull/2974>
The device was automatically found by sc_usb_connect(). Instead, expose
a function to find a device from a serial, and let the caller connect to
the device found (if any).
This will allow to list all devices first, then select one device to
connect to.
PR #2974 <https://github.com/Genymobile/scrcpy/pull/2974>
Use it from accept_device() to simplify (at the cost an additional
allocation for each serial, but it is not important).
It will also be useful in other functions in further commits.
PR #2974 <https://github.com/Genymobile/scrcpy/pull/2974>
The server needs to interrupt the sockets on stop, but it must not close
them while other threads may attempt to read from or write to them.
In particular, the video_socket is read by the stream thread, and the
control_socket is written by the controller and read by receiver.
Therefore, close the socket only on sc_server_destroy(), which is called
after all other threads are joined.
Reported by TSAN on close:
WARNING: ThreadSanitizer: data race (pid=3287612)
Write of size 8 at 0x7ba000000080 by thread T1:
#0 close ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:1690 (libtsan.so.0+0x359d8)
#1 net_close ../app/src/util/net.c:280 (scrcpy+0x23643)
#2 run_server ../app/src/server.c:772 (scrcpy+0x20047)
#3 <null> <null> (libSDL2-2.0.so.0+0x905a0)
Previous read of size 8 at 0x7ba000000080 by thread T16:
#0 recv ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:6603 (libtsan.so.0+0x4f4a6)
#1 net_recv_all ../app/src/util/net.c:228 (scrcpy+0x234a9)
#2 stream_recv_packet ../app/src/stream.c:33 (scrcpy+0x2045c)
#3 run_stream ../app/src/stream.c:228 (scrcpy+0x21169)
#4 <null> <null> (libSDL2-2.0.so.0+0x905a0)
Refs ddb9396743
On Windows, the file explorer does not provide any "open a terminal
here" shortcut.
Add a bat file which just runs `cmd` to easily open a terminal directly
in the scrcpy directory (so there is no need to `cd C:\path\…`).
PR #2970 <https://github.com/Genymobile/scrcpy/pull/2970>
For convenience, this new option forces the 3 following options:
- send_device_meta=false
- send_frame_meta=false
- send_dummy_byte=false
This allows to send a raw H.264 stream on the video socket.
Concretely:
adb push scrcpy-server /data/local/tmp/scrcpy-server.jar
adb forward tcp:1234 localabstract:scrcpy
adb shell CLASSPATH=/data/local/tmp/scrcpy-server.jar \
app_process / com.genymobile.scrcpy.Server 1.21 \
raw_video_stream=true tunnel_forward=true control=false
As soon as a client connects via TCP to localhost:1234, it will receive
the raw H.264 stream.
Refs #1419 comment <https://github.com/Genymobile/scrcpy/pull/1419#issuecomment-1013964650>
PR #2971 <https://github.com/Genymobile/scrcpy/pull/2971>
Similar to send_device_frame, this option allows to disable sending the
device name and size on start.
This is only useful when using the scrcpy-server alone to get a raw
H.264 stream, without using the scrcpy client.
PR #2971 <https://github.com/Genymobile/scrcpy/pull/2971>
Move the options unused by the scrcpy client at the end.
These options may be useful to use scrcpy-server directly (to get a raw
H.264 stream for example).
PR #2971 <https://github.com/Genymobile/scrcpy/pull/2971>
Retry with a lower definition if MediaCodec fails before the first
frame, not the first packet.
In practice, the first packet is a config packet without any frame, and
MediaCodec might fail just after.
Refs 2eb6fe7d81
Refs #2963 <https://github.com/Genymobile/scrcpy/issues/2963>
If --no-control is requested, then the controller instance is not
initialized. However, its reference was still passed to screen and
input_manager.
Instead, pass NULL if no controller is available.
MediaCodec errors always trigger IllegalStateException or a subtype
(like MediaCodec.CodecException).
In practice, this avoids to retry if the error is caused by an
IOException when writing the video packet to the socket.
The purpose of automatic downscaling on error is to make mirroring work
by just starting scrcpy without an explicit -m value, even if the
encoder could not encode at the screen definition.
It is only useful when we detect an encoding failure before the first
frame. Downsizing later could be surprising, so disable it.
PR #2947 <https://github.com/Genymobile/scrcpy/pull/2947>
The optimal initial size was computed from the expected dimensions, sent
immediately by the server before encoding any video frame.
However, the actual frame size may be different, for example when the
device encoder does not support the requested size.
To always handle this case properly, position and size the window only
once the first frame size is known.
PR #2947 <https://github.com/Genymobile/scrcpy/pull/2947>
Show the window only after the actual frame size is known (and if no
error has occurred).
This will allow to properly position and size the window when the size
of the first frame is different from the size initially announced by the
server.
PR #2947 <https://github.com/Genymobile/scrcpy/pull/2947>
Now that scrcpy attempts with a lower definition on any MediaCodec
error (or the user explicitly requests to disable auto-downsizing), the
suggestion is unnecessary.
PR #2947 <https://github.com/Genymobile/scrcpy/pull/2947>
Some devices are not able to encode at the device screen definition.
Instead of just failing, try with a lower definition on any MediaCodec
error.
PR #2947 <https://github.com/Genymobile/scrcpy/pull/2947>
The FFmpeg dependency is downloaded from two separate zipfiles.
Symlink include/ to expose everything from a single directory, to
simplify the meson script.
PR #2952 <https://github.com/Genymobile/scrcpy/pull/2952>
The fact that the current prebuilt FFmpeg is split into two separate
zipfiles is an implementation detail.
Use a single Makefile recipe for both files.
PR #2952 <https://github.com/Genymobile/scrcpy/pull/2952>
The components should be configurable independently of the global
scrcpy_options instance: their configuration could be provided
separately, like it is the case for example for some screen parameters.
For consistency, keyboard injection should not depend on scrcpy_options.
In relative mouse mode, the mouse pointer must be "captured" from the
computer.
Toggle (disable/enable) relative mouse mode using any of the hardcoded
capture keys:
- left-Alt
- left-Super
- right-Super
These capture keys do not conflict with shortcuts, since a shortcut is
always a combination of the MOD key and some other key, while the
capture key triggers an action only if it is pressed and released alone.
The relative mouse mode is also automatically enabled on any click in
the window, and automatically disabled on focus lost (it is possible to
lose focus even without the mouse).
The decision to not send motion events when no click is pressed is
specific to Android mouse injection. Other mouse processors (e.g. for
HID mouse) will need to receive all events.
The default mouse injection works in absolute mode: it forwards clicks
at a specific position on screen.
To support HID mouse, add a flag to indicate that the mouse processor
works in relative mode: it forwards mouse motion vectors, without any
absolute reference to the screen.
A scroll event might be produced when a mouse button is pressed (for
example when scrolling while selecting a text). For consistency, pass
the actual buttons state (instead of 0).
In practice, it seems that this use case does not work properly with
Android event injection, but it will work with HID mouse.
The input_manager is strongly tied to the screen, it could not work
independently of the specific screen implementation.
To implement a user-friendly HID mouse behavior, some SDL events
will need to be handled both by the screen and by the input manager. For
example, a click must typically be handled by the input_manager so that
it is forwarded to the device, but in HID mouse mode, the first click
should be handled by the screen to capture the mouse (enable relative
mouse mode).
Make the input_manager a descendant of the screen, so that the screen
decides what to do on SDL events.
Concretely, replace this structure hierarchy:
+- struct scrcpy
+- struct input_manager
+- struct screen
by this one:
+- struct scrcpy
+- struct screen
+- struct input_manager
This avoids to directly pass the options instance (which contains more
data than strictly necessary), and limit the number of parameters for
the init function.
Not all key processors support text injection (HID keyboard does not
support it).
Instead of providing a dummy op function, set it to NULL and check on
the caller side before calling it.
Pass scrcpy input events instead of SDL input events to mouse
processors.
These events represent exactly what mouse processors need, abstracted
from any visual orientation and scaling applied on the SDL window.
This makes the mouse processors independent of the "screen" instance,
and the implementation source code independent of the SDL API.
This aims to make the key/mouse processors independent of the "screen",
by processing scrcpy-specific input events instead of SDL events.
In particular, these scrcpy events are not impacted by any UI window
scaling or rotation (contrary to SDL events).
The input manager exposed functions taking an "actions" parameter,
containing a bitmask-OR of ACTION_UP and ACTION_DOWN.
But they are never called with both actions simultaneously anymore, so
simplify.
Refs 964b6d2243
Refs d0739911a3
This allows to report a meaningful error message if an unsupported
feature is used on an incompatible platform. This is consistent with the
behavior of -K/--hid-keyboard.
The "resize to fit" feature (MOD+w or double-click on black borders)
computed the "optimal size" using the same function computing the
initial window size on start.
However, on "resize to fit", only the black borders must be removed (the
content size must be preserved), so the display bounds must not be
considered.
The icon will be associated to scrcpy.exe in the Windows explorer.
The .ico was created using imagemagick:
convert icon.png icon.ico
It is included as a binary for simplicity.
Refs #2815 <https://github.com/Genymobile/scrcpy/issues/2815>
Prefix the name of threads by "scrcpy-". This improves readability in
the output of `top -H` for example.
Limit the thread names to 16 bytes, because it is limited on some
platforms.
The sockets were never interrupted or closed by the client since recent
changes to run the server from a dedicated thread (see commit
0426708544).
As a side effect, the server could never terminate properly (it was
waiting on socket blocking calls), so it was always killed by the client
after the WATCHDOG_DELAY.
Interrupt the sockets on stop to give the servera chance to terminate
property, then close them.
If --no-control is enabled, then it is not necessary to create a second
communication socket between the client and the server.
This also facilitates the use of the server alone (without the client)
to receive only the raw video stream.
In ffmpeg/doc/APIchanges:
> 2016-04-21 - 7fc329e - lavc 57.37.100 - avcodec.h
> Add a new audio/video encoding and decoding API with decoupled input
> and output -- avcodec_send_packet(), avcodec_receive_frame(),
> avcodec_send_frame() and avcodec_receive_packet().
Refs de9b79ec2d
Refs #2862 <https://github.com/Genymobile/scrcpy/issues/2862>
Thank you clang:
../app/src/control_msg.c:45:5: warning: suspicious concatenation of
string literals in an array initialization; did you mean to separate
the elements with a comma? [-Wstring-concatenation]
"hover-exit",
^
In function ‘memcpy’,
inlined from ‘control_msg_serialize.constprop’ at ../app/src/control_msg.c:77:5,
inlined from ‘run_controller’ at ../app/src/controller.c:69:12:
/usr/include/x86_64-linux-gnu/bits/string_fortified.h:34:10:
warning: ‘__builtin___memcpy_chk’ writing 262138 bytes into a region
of size 262130 overflows the destination [-Wstringop-overflow=]
return __builtin___memcpy_chk (__dest, __src, __len, __bos0 (__dest));
Refs 901d837165
PR #2859 <https://github.com/Genymobile/scrcpy/pull/2859>
Signed-off-by: Yu-Chen Lin <npes87184@gmail.com>
Signed-off-by: Romain Vimont <rom@rom1v.com>
Expose the inject input event mode so that it is possible to wait for
the events to be "finished". This will be necessary to read the
clipboard content only after the COPY or CUT key event is handled.
PR #2834 <https://github.com/Genymobile/scrcpy/pull/2834>
There was only two key injection modes:
- the default one
- the mode with --prefer-text enabled
To prepare the addition of another mode (--raw-key-events), use an enum
instead of a bool.
PR #2831 <https://github.com/Genymobile/scrcpy/pull/2831>
Expose an option to automatically configure and reconnect the device
over TCP/IP, to simplify wireless connection without using adb
explicitly.
There are two variants:
- If a destination address is provided, then scrcpy connects to this
address before starting. The device must listen on the given TCP port
(default is 5555).
- If no destination address is provided, then scrcpy attempts to find
the IP address of the current device (typically connected over USB),
enables TCP/IP mode, then connects to this address before starting.
PR #2827 <https://github.com/Genymobile/scrcpy/pull/2827>
This will allow to read the property "service.adb.tcp.port" to know if
the TCP/IP mode is enabled on the device, and which listening port is
used.
PR #2827 <https://github.com/Genymobile/scrcpy/pull/2827>
Depending on the platform and adb versions, the lines output by adb
could end with "\r\r\n". This util function helps to remove all trailing
'\r'.
PR #2827 <https://github.com/Genymobile/scrcpy/pull/2827>
"adb connect" always returns successfully (with exit code 0), even in
case of failure.
As a workaround, capture its output and check if it starts with
"connected".
PR #2827 <https://github.com/Genymobile/scrcpy/pull/2827>
In addition to disable stdout and stderr of the child process, add a
flag to disable the error log printed by scrcpy if the command failed.
This will we useful for commands which are expected to fail in some
cases (like "adb disconnect" if the device is not connected).
PR #2827 <https://github.com/Genymobile/scrcpy/pull/2827>
Let the caller decide if stdout and stderr must be inherited on process
creation, i.e. if stdout and stderr of the child process should be
printed in the scrcpy console.
This allows to get output and errors for specific adb commands depending
on the context.
PR #2827 <https://github.com/Genymobile/scrcpy/pull/2827>
If SOCK_CLOEXEC exists, then set the flag on socket creation.
Otherwise, use fcntl() (or SetHandleInformation() on Windows) to set the
flag afterwards.
This avoids the sockets to be inherited in child processes.
Refs #2783 <https://github.com/Genymobile/scrcpy/pull/2783>
The options values to configure the server were identified by their
command-line argument index. Now that there are a lot of arguments, many
of them being booleans, it became unreadable and error-prone.
Identify the arguments by a key string instead, and make them optional.
This will also simplify running the server manually for debugging.
To allow seamless copy-paste, on Ctrl+v, a SET_CLIPBOARD request is
performed before injecting Ctrl+v.
But when HID keyboard is enabled, the Ctrl+v injection is not sent on
the same channel as the clipboard request, so they are not serialized,
and may occur in any order. If Ctrl+v happens to be injected before the
new clipboard content is set, then the old content is pasted instead,
which is incorrect.
To minimize the probability of occurrence of the wrong order, a delay of
2 milliseconds was added before injecting Ctrl+v. Then 5ms. But even
with 5ms, the wrong behavior sometimes happens.
To handle it properly, add an acknowledgement mechanism, so that Ctrl+v
is injected over AOA only after the SET_CLIPBOARD request has been
performed and acknowledged by the server.
Refs e4163321f0
Refs 45b0f8123a
PR #2814 <https://github.com/Genymobile/scrcpy/pull/2814>
Pass the information that device clipboard has been set to the key
processor. This avoids the keyprocessor to "guess", and paves the way to
implement a proper acknowledgement mechanism.
PR #2814 <https://github.com/Genymobile/scrcpy/pull/2814>
Tunnel host and port are only meaningful in "adb forward" mode.
They indicate where the client must connect to communicate with the
server. In "adb reverse" mode, the client _listens_, it does not
_connect_.
Refs #2807 <https://github.com/Genymobile/scrcpy/pull/2807>
In "adb forward" mode, by default, scrcpy connects to localhost:PORT,
where PORT is the local port passed to "adb forward". This assumes that
the tunnel is established on the local host with a local adb server
(which is the common case).
For advanced usage, add --tunnel-host and --tunnel-port to force the
connection to a different destination.
Fixes#2801 <https://github.com/Genymobile/scrcpy/issues/2801>
PR #2807 <https://github.com/Genymobile/scrcpy/pull/2807>
Signed-off-by: Romain Vimont <rom@rom1v.com>
Inconditionnally print the scrcpy version first, without using LOGI().
The log level is configured only after parsing the command line
parameters (it may be changed via -V), and command line parsing logs
should not appear before the scrcpy version.
The output of -h/--help was printed on stderr, although it is not an
error.
Printing on stdout allows to pipe the result directly:
scrcpy --help | less
Instead of (in bash):
scrcpy --help |& less
This allows to execute all adb commands with the specific -s parameter,
even if it is not provided by the user.
In practice, calling adb without -s works if there is exactly one device
connected. But some adb commands (for example "adb push" on drag & drop)
could be executed after another device is connected, so the actual
device serial must be known.
The interruptible version of the function to check process success
(sc_process_check_success_intr()) did not accept a close parameter to
avoid a race condition. But as the result, the processes were not closed
at all.
Add a close parameter, and close the process separately to avoid the
race condition.
Cleanup is used for some options like --show-touches to restore the
state on exit.
If the configuration fails, do not crash the whole process. Just log an
error.
PR #2802 <https://github.com/Genymobile/scrcpy/pull/2802>
Before Android 8, executing the "settings" command from a shell was
very slow (~1 second), because it spawned a new app_process to execute
Java code. Therefore, to access settings without performance issues,
scrcpy used private APIs to read from and write to settings.
However, since Android 12, this is not possible anymore, due to
permissions changes.
To make it work again, execute the "settings" command on Android 12 (or
on previous version if the other method failed). This method is faster
than before Android 8 (~100ms).
Fixes#2671 <https://github.com/Genymobile/scrcpy/issues/2671>
Fixes#2788 <https://github.com/Genymobile/scrcpy/issues/2788>
PR #2802 <https://github.com/Genymobile/scrcpy/pull/2802>
Settings read/write errors were silently ignored. Report them via a
SettingsException so that the caller can handle them.
This allows to log a proper error message, and will also allow to
fallback to a different settings method in case of failure.
PR #2802 <https://github.com/Genymobile/scrcpy/pull/2802>
Until now, the code that needed to read/write the Android settings had
to explicitly open and close a ContentProvider.
Wrap these details into a Settings class.
This paves the way to provide an alternative implementation of settings
read/write for Android >= 12.
PR #2802 <https://github.com/Genymobile/scrcpy/pull/2802>
Interrupt any blocking call on process terminated, like on
server_stop().
This allows to interrupt any blocking accept() with correct
synchronization without additional complexity.
Define server callbacks, start the server asynchronously and listen to
connection events to initialize scrcpy properly.
It will help to simplify the server code, and allows to run the UI event
loop while the server is connecting. In particular, this will allow to
receive SIGINT/Ctrl+C events during connection to interrupt immediately.
Currently, server_stop() is called from the same thread as
server_connect_to(), so interruption may never happen.
This is a step to prepare executing the server from a dedicated thread.
Use the option descriptions to generate the optstring and longopts
parameters for the getopt_long() command.
That way, the options are completely described in a single place.
On Linux, socket functions are unblocked by shutdown(), but on Windows
they are unblocked by closesocket().
Expose net_interrupt() and net_close() to abstract these differences:
- net_interrupt() calls shutdown() on Linux and closesocket() on
Windows (if not already called);
- net_close() calls close() on Linux and closesocket() on Windows (if
not already called).
This simplifies the server code, and prevents a data race on close
(reported by TSAN) on Linux (but does not fix it on Windows):
WARNING: ThreadSanitizer: data race (pid=836124)
Write of size 8 at 0x7ba0000000d0 by main thread:
#0 close ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:1690 (libtsan.so.0+0x359d8)
#1 net_close ../app/src/util/net.c:211 (scrcpy+0x1c76b)
#2 close_socket ../app/src/server.c:330 (scrcpy+0x19442)
#3 server_stop ../app/src/server.c:522 (scrcpy+0x19e33)
#4 scrcpy ../app/src/scrcpy.c:532 (scrcpy+0x156fc)
#5 main ../app/src/main.c:92 (scrcpy+0x622a)
Previous read of size 8 at 0x7ba0000000d0 by thread T6:
#0 recv ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:6603 (libtsan.so.0+0x4f4a6)
#1 net_recv ../app/src/util/net.c:167 (scrcpy+0x1c5a7)
#2 run_receiver ../app/src/receiver.c:76 (scrcpy+0x12819)
#3 <null> <null> (libSDL2-2.0.so.0+0x84f40)
When Ctrl+v is pressed, a control is sent to the device to set the
device clipboard before injecting Ctrl+v.
With the InputManager method, it is guaranteed that the device
synchronization is executed before handling Ctrl+v, since the commands
are executed on the device in sequence.
However, HID are injected from the computer, so there is no such
guarantee. As a consequence, on Android, Ctrl+v triggers a paste with
the old clipboard content.
To workaround the issue, wait a bit (2 milliseconds) from the AOA
thread before injecting the event, to leave enough time for the
clipboard to be set before injecting Ctrl+v.
When an AOA HID keyboard is registered, CAPSLOCK and NUMLOCK are both
disabled, regardless of the state of the computer keyboard.
To synchronize the state, on first key event, inject CAPSLOCK and/or
NUMLOCK if necessary.
The serial is necessary to find the correct Android device for AOA.
If it is not explicitly provided by the user via -s, then execute "adb
getserialno" to retrieve it.
The AVOutputFormat name is a comma-separated list. In theory, possible
names for V4L2 are:
- "video4linux2,v4l2"
- "v4l2,video4linux2"
- "v4l2"
- "video4linux2"
To find the muxer in all cases, we must request exactly one muxer name
at a time.
PR #2718 <https://github.com/Genymobile/scrcpy/pull/2718>
Co-authored-by: Romain Vimont <rom@rom1v.com>
Signed-off-by: Romain Vimont <rom@rom1v.com>
The first frames are typically received and decoded with more delay than
the others, causing a wrong slope estimation on start.
To compensate, assume an initial slope of 1, then progressively use the
estimated slope.
To minimize latency (at the cost of jitter), scrcpy always displays a
frame as soon as it available, without waiting.
However, when recording (--record), it still writes the captured
timestamps to the output file, so that the recorded file can be played
correctly without jitter.
Some real-time use cases might benefit from adding a small latency to
compensate for jitter too. For example, few tens of seconds of latency
for live-streaming are not important, but jitter is noticeable.
Therefore, implement a buffering mechanism (disabled by default) to add
a configurable latency delay.
PR #2417 <https://github.com/Genymobile/scrcpy/issues/2417>
Currently, a frame is available to the consumer as soon as it is pushed
by the producer (which can detect if the previous frame is skipped).
Notify the new frames (and frame skipped) via callbacks instead.
This paves the way to add (optional) buffering, which will introduce a
delay between the time when the frame is produced and the time it is
available to be consumed.
The current video buffer only stores one pending frame.
In order to add a new buffering feature, move this part to a separate
"frame buffer". Keep the video_buffer, which currently delegates all its
calls to the frame_buffer.
To fix a data race, commit 5caeab5f6d
called video_buffer_push() and video_buffer_consume() under the
v4l2_sink lock.
Instead, use the previous_skipped indication (initialized with video
buffer locked) to lock only for protecting the has_frame flag.
This enables the possibility for the video_buffer to notify new frames
via callbacks without lock inversion issues.
The function sc_cond_timedwait() accepted a parameter representing the
max duration to wait, because it internally uses SDL_CondWaitTimeout().
Instead, accept a deadline, to be consistent with
pthread_cond_timedwait().
The v4l2_sink implementation directly read the internal video_buffer
field "pending_frame_consumed", which is protected by the internal
video_buffer mutex. But this mutex was not locked, so reads were racy.
Lock using the v4l2_sink mutex in addition, and use a separate field to
avoid depending on the video_buffer internal data.
Commit 21d206f360 added mutex assertions.
However, the "locker" variable to trace the locker thread id was read
and written by several threads without any protection, so it was racy.
Reported by TSAN.
The options --no-display and --no-control are independent.
The controller was not initialized when no display was requested,
because it was assumed that no control could occur without display. But
that's not true (anymore): for example, it is possible to pass
--turn-screen-off.
Fixes#2426 <https://github.com/Genymobile/scrcpy/issues/2426>
Make the versionCode a decimal representation of the scrcpy version.
This will for example allow to correctly number the versionCode of
v1.17.1 after a v1.18 is released:
- v1.18 -> 11800
- v1.17.1 -> 11701
- v1.18.1 -> 11801
Mouse motion events were forwarded as soon as any mouse button was
pressed.
Instead, only consider left-click (and also middle-click and right-click
if --forward-all-clicks is enabled).
Change the default push target from /sdcard/ to /sdcard/Download/.
Pushing to the root of /sdcard/ is not very convenient, many apps do not
expose its content directly.
It can still be changed by --push-target.
PR #2384 <https://github.com/Genymobile/scrcpy/pull/2384>
When removing the black borders (by double-clicking on them, or by
pressing MOD+w), the window is resized to fit the device screen, but its
top-left position was left unchanged.
Instead, move the window so that the new window area is at the center of
the old window area.
Refs #2387 <https://github.com/Genymobile/scrcpy/issues/2387>
It should not be necessary, since screen_render() is called just after
on SDL_WINDOWEVENT_EXPOSED, but in practice the window content might not
be correctly displayed on restored if a rotation occurred while
minimized.
Note that calling screen_render() twice in a row on
SDL_WINDOWEVENT_EXPOSED also "fixes" the issue.
From FFmpeg/doc/APIchanges:
2021-03-17 - f7db77bd87 - lavc 58.133.100 - codec.h
Deprecated av_init_packet(). Once removed, sizeof(AVPacket) will
no longer be a part of the public ABI.
Refs #2302 <https://github.com/Genymobile/scrcpy/issues/2302>
From FFmpeg/doc/APIchanges:
2021-03-17 - f7db77bd87 - lavc 58.133.100 - codec.h
Deprecated av_init_packet(). Once removed, sizeof(AVPacket) will
no longer be a part of the public ABI.
Refs #2302 <https://github.com/Genymobile/scrcpy/issues/2302>
From FFmpeg/doc/APIchanges:
2021-03-17 - f7db77bd87 - lavc 58.133.100 - codec.h
Deprecated av_init_packet(). Once removed, sizeof(AVPacket) will
no longer be a part of the public ABI.
Refs #2302 <https://github.com/Genymobile/scrcpy/issues/2302>
From FFmpeg/doc/APIchanges:
2021-03-17 - f7db77bd87 - lavc 58.133.100 - codec.h
Deprecated av_init_packet(). Once removed, sizeof(AVPacket) will
no longer be a part of the public ABI.
Remove the has_pending boolean, which can be replaced by:
stream->pending != NULL
Refs #2302 <https://github.com/Genymobile/scrcpy/issues/2302>
The argument for option --lock-video-orientation has been made optional
by 5af9d0ee0f.
With getopt_long(), contrary to mandatory arguments, optional arguments
must be given with a '=':
--lock-video-orientation 2 # wrong, parse error
--lock-video-orientation=2 # correct
The input manager was partially initialized statically, but a call to
input_manager_init() was needed anyway, so initialize all the fields
from the "constructor".
This is consistent with the initialization of the other structs.
Remove useless intermediate method with a "mode" parameter (it's always
called with the same mode).
This also avoids the need for a specific injectEventOnDisplay() method,
since it does not conflict with another injectEvent() method anymore.
The frame can be unref immediately after it is pushed to the frame
sinks.
It was not really a memory leak because the frame was unref every time
by avcodec_receive_frame() (and freed on close), but a reference was
unnecessarily kept for too long.
Add a new mode to the --lock-video-orientation option, to lock the
initial orientation of the device.
This avoids to pass an explicit value (0, 1, 2 or 3) and think about
which is the right one.
The screen may not be destroyed immediately on close to avoid undefined
behavior, because it may still receive events from the decoder.
But the visual window must still be closed immediately.
The destruction order is important, but tricky, because the screen is
open/close by the decoder, but destroyed by scrcpy.c on the main thread.
Add assertions to guarantee that the screen is not destroyed before
being closed.
The video buffer is now an internal detail of the screen component.
Since the screen is plugged to the decoder via the frame sink trait, the
decoder does not access to the video buffer anymore.
The fact that the recorder uses a separate thread is an internal detail,
so the functions _start(), _stop() and _join() should not be exposed.
Instead, start the thread on _open() and _stop()+_join() on close().
This paves the way to expose the recorder as a packet sink trait.
The video buffer took ownership of the producer frame (so that it could
swap frames quickly).
In order to support multiple sinks plugged to the decoder, the decoded
frame must not be consumed by the display video buffer.
Therefore, move the producer and consumer frames out of the video
buffer, and use FFmpeg AVFrame refcounting to share ownership while
avoiding copies.
This flag forced the decoder to wait for the previous frame to be
consumed by the display.
It was initially implemented as a compilation flag for testing, not
intended to be exposed at runtime. But to remove ifdefs and to allow
users to test this flag easily, it had finally been exposed by commit
ebccb9f6cc.
In practice, it turned out to be useless: it had no practical impact,
and it did not solve or mitigate any performance issues causing frame
skipping.
But that added some complexity to the codebase: it required an
additional condition variable, and made video buffer calls possibly
blocking, which in turn required code to interrupt it on exit.
To prepare support for multiple sinks plugged to the decoder (display
and v4l2 for example), the blocking call used for pacing the decoder
output becomes unacceptable, so just remove this useless "feature".
Double-click on extra mouse button to open the settings panel (a
single-click opens the notification panel).
This is consistent with the keyboard shortcut MOD+n+n.
PR #2264 <https://github.com/Genymobile/scrcpy/pull/2264>
Signed-off-by: Romain Vimont <rom@rom1v.com>
The shortcut "back on screen on" is a bit special: the control is
requested by the client, but the actual event injection (POWER or BACK)
is determined on the device.
To properly inject DOWN and UP events for BACK, transmit the action as
a control parameter.
If the screen is off:
- on DOWN, inject POWER (DOWN and UP) (wake up the device immediately)
- on UP, do nothing
If the screen is on:
- on DOWN, inject BACK DOWN
- on UP, inject BACK UP
A corner case is when the screen turns off between the DOWN and UP
event. In that case, a BACK UP event will be injected, so it's harmless.
As a consequence of this change, the BACK button is now handled by
Android on mouse released. This is consistent with the keyboard shortcut
(Mod+b) behavior.
PR #2259 <https://github.com/Genymobile/scrcpy/pull/2259>
Refs #2258 <https://github.com/Genymobile/scrcpy/pull/2258>
The screen receives callbacks from the decoder, fed by the stream.
The decoder is run from the stream thread, so waiting for the end of
stream is sufficient to avoid possible use-after-destroy.
When --no-display was passed, screen_destroy() was called while
screen_init() was never called.
In practice, it did not crash because it just freed NULL pointers, but
it was still incorrect.
A skipped frame is detected when the producer offers a frame while the
current pending frame has not been consumed.
However, the producer (in practice the decoder) is not interested in the
fact that a frame has been skipped, only the consumer (the renderer) is.
Therefore, notify frame skip via a consumer callback. This allows to
manage the skipped and rendered frames count at the same place, and
remove fps_counter from decoder.
As soon as the stream is started, the video buffer could notify a new
frame available.
In order to pass this event to the screen without race condition, the
screen must be initialized before the screen is started.
Video buffer is a tool between a frame producer and a frame consumer.
For now, it is used between a decoder and a renderer, but in the future
another instance might be used to swscale decoded frames.
It makes sense to extract default values for bitrate and port range
(which are arbitrary and might be changed in the future).
However, the default values for "max size" and "lock video orientation"
are naturally unlimited/unlocked, and will never be changed. Extracting
these options just added complexity for no benefit, so hardcode them.
After the struct screen is initialized, the window, the renderer and the
texture are necessarily valid, so there is no need to check in
screen_destroy().
There were only two frames simultaneously:
- one used by the decoder;
- one used by the renderer.
When the decoder finished decoding a frame, it swapped it with the
rendering frame.
Adding a third frame provides several benefits:
- the decoder do not have to wait for the renderer to release the
mutex;
- it simplifies the video_buffer API;
- it makes the rendering frame valid until the next call to
video_buffer_take_rendering_frame(), which will be useful for
swscaling on window resize.
The functions SDL_malloc(), SDL_free() and SDL_strdup() were used only
because strdup() was not available everywhere.
Now that it is available, use the native version of these functions.
Small unsigned integers promote to signed int. As a consequence, if v is
a uint8_t, then (v << 24) yields an int, so the left shift is undefined
if the MSB is 1.
Cast to uint32_t to yield an unsigned value.
Reported by USAN (meson x -Db_sanitize=undefined):
runtime error: left shift of 255 by 24 places cannot be represented
in type 'int'
The current process could be waited both by run_file_handler() and
file_handler_stop().
To avoid the race condition, wait the process without closing, then
close with mutex locked.
There were two versions: process_wait() and process_wait_noclose().
Expose a single version with a flag (it was already implemented that way
internally).
The function process_wait() returned a bool (true if the process
terminated successfully) and provided the exit code via an output
parameter exit_code.
But the returned value was always equivalent to exit_code == 0, so just
return the exit code instead.
The size, point and position structs were defined in common.h. Move them
to coords.h so that common.h could be used for generic code to be
included in all source files.
The header libavformat/version.h was included, but not
libavcodec/version.h.
As a consequence, the LIBAVCODEC_VERSION_INT definition depended on the
caller includes.
On Linux, waitpid() both waits for the process to terminate and reaps it
(closes its handle). On Windows, these actions are separated into
WaitForSingleObject() and CloseHandle().
Expose these actions separately, so that it is possible to send a signal
to a process while waiting for its termination without race condition.
This allows to wait for server termination normally, but kill the
process without race condition if it is not terminated after some delay.
Let the server terminate properly once all the sockets are closed.
If it does not terminate (this can happen if the device is asleep), then
kill it.
Note: since the server process termination is detected by a flag set
after waitpid() returns, there is a small chance that the process
terminates (and the PID assigned to a new process) before the flag is
set but before the kill() call. This race condition already existed
before this commit.
Fixes#1992 <https://github.com/Genymobile/scrcpy/issues/1992>
TerminateProcess() is "equivalent" to kill(), while
WaitForSingleObject() is "equivalent" to waitpid(), so the handle must
be closed after WaitForSingleObject().
The (non-daemon) threads were not interrupted on video stream stopped,
leaving the server process alive.
Interrupt them to wake up their blocking call so that they terminate
properly.
Refs #1992 <https://github.com/Genymobile/scrcpy/issues/1992>
Before this change, release.sh built some native stuff, and
Makefile.CrossWindows built the Windows releases.
Instead, use a single release.make to build the whole release. It also
avoids to build the server one more time.
On Windows, scrcpy paused on error before exiting to give the user a
chance to see the user message.
This was a hack and causes issues when using scrcpy from batch scripts.
Disable this pause from the scrcpy binary, and provide a batch wrapper
(scrcpy-console.bat) to pause on error.
Fixes#1875 <https://github.com/Genymobile/scrcpy/issues/1875>
Use "%Iu" on Windows. This fixes the following warning:
../app/src/sys/win/command.c:17:14: warning: unknown conversion type character ‘l’ in format [-Wformat=]
17 | LOGE("Command too long (%" PRIsizet " chars)", len - 1);
This commit in AOSP framework_base added a parameter "attributionTag" to
the call() method:
12ac3f406f%5E%21/#F17
As a consequence, the method did not exist, so scrcpy used the legacy
call() method (using the authority "unknown") as a fallback, which fails
for security reasons.
Fixes#1468 <https://github.com/Genymobile/scrcpy/issues/1468>
The behavior of some methods do not depend on the user-provided options.
These methods can be static. This will allow to call them directly from
the cleanup process.
To avoid possible copy-paste loops between the computer and the device,
the device clipboard is not set if it already contains the expected
content.
But the condition was wrong: it was not set also if it was empty.
Refs 1223a72eb8Fixes#1658 <https://github.com/Genymobile/scrcpy/issues/1658>
A new "repeat" field has been added by
3c1ed5d86c, but it was not initialized in
every code path.
As a consequence, keycodes generated by shortcuts were sent with an
undetermined value, breaking some shortcuts (especially HOME) randomly.
Fixes#1643 <https://github.com/Genymobile/scrcpy/issues/1643>
This avoids to pass specific options values individually. Since these
function are static (internal to the file), this is not a problem to
make them depend on scrcpy_options.
Refs #1623 <https://github.com/Genymobile/scrcpy/pull/1623>
Signed-off-by: Romain Vimont <rom@rom1v.com>
Send COPY and CUT on MOD+c and MOD+x (only supported for Android >= 7).
The shortcuts Ctrl+c and Ctrl+x should generally also work (even before
Android 7), but the active Android app may use them for other actions
instead.
Do not explicitly set the clipboard text if it already contains the
expected content.
Even if copy-paste loops are avoided by the previous commit, this avoids
to trigger a clipboard change on the computer-side.
Refs #1580 <https://github.com/Genymobile/scrcpy/issues/1580>
Do not explicitly set the clipboard text if it already contains the
expected content. This avoids possible copy-paste loops between the
computer and the device.
Pressing Ctrl+v on the device will typically paste the clipboard
content.
Before sending the key event, synchronize the computer clipboard to the
device clipboard to allow seamless copy-paste.
Now that the scrcpy shortcut modifier is Alt by default (and can be
configured), forward Ctrl to the device.
This allows to trigger Android shortcuts.
Fixes#555 <https://github.com/Genymobile/scrcpy/issues/555>
Pressing Alt+c generates a text event containing "c", so "c" was sent to
the device when --prefer-text was enabled.
Ignore text events when the mod state matches a shortcut modifier.
Remove the Cmd modifier on macOS, which was possible only for some
shortcuts but not all.
This paves the way to make the shortcut modifier customizable.
When the client requests to set the clipboard, it may request to press
the PASTE key in addition. To be a bit generic, it was stored as a flag
in ControlMessage.java.
But flags suggest that it represents a bitwise union. Use a simple
boolean instead.
To power the device on, inject KEYCODE_WAKEUP to avoid a possible
race condition (the device might become off between the test
isScreenOn() and the POWER keycode injection).
In theory, this was expected to only happen when a touch event is sent
just before the device is rotated, but some devices do not respect the
encoding size, causing an unexpected mismatch.
Refs #1518 <https://github.com/Genymobile/scrcpy/issues/1518>
Touch events were HiDPI-scaled twice:
- once because the position (provided as floats between 0 and 1) were
converted in pixels using the drawable size (not the window size)
- once due to screen_convert_to_frame_coords()
One possible fix could be to compute the position in pixels from the
window size instead, but this would unnecessarily round the event
position to the nearest window coordinates (instead of drawable
coordinates).
Instead, expose two separate functions to convert to frame coordinates
from either window or drawable coordinates.
Fixes#1536 <https://github.com/Genymobile/scrcpy/issues/1536>
Refs #15 <https://github.com/Genymobile/scrcpy/issues/15>
Refs e40532a376
The header scrcpy.h is intended to be the "public" API. It should not
depend on other internal headers.
Therefore, declare all required structs in this header and adapt
internal code.
The function must return a SDL_LogPriority, but returned an enum
sc_log_level.
(It was harmless because this specific return should never happen, as
asserted.)
This reverts commit 8c8649cfcd.
I cannot reproduce the issue with Ctrl+Shift+o on any device, so in
practice it works, it's too bad to remove the feature for a random bug
on some Android versions on some devices.
In practice, it does not change anything (it just avoids a spurious
wake-up), but semantically, it makes no sense to call
pushClipboardText() with a null value.
Clean up has been broken by 3df63c579d.
The verbosity was correctly initialized for the Server process, but not
for the CleanUp process.
To avoid the problem, initialize a default log level.
Only the main injection method was exposed on Device, the convenience
methods were implemented in Controller.
For consistency, move them all to the Device class.
The Android device listens for clipboard changes to synchronize with the
computer clipboard.
However, if the change comes from scrcpy (for example via Ctrl+Shift+v),
do not notify the change.
Add a command-line option to force "adb forward", without attempting
"adb reverse" first.
This is especially useful for using SSH tunnels without enabling remote
port forwarding.
The verbosity was set either to info (in release mode) or debug (in
debug mode).
Add a command-line argument to change it, so that users can enable debug
logs using the release:
scrcpy -Vdebug
The field lock_video_orientation may only take values between -1 and 3
(included). But the compiler may trigger a warning on the sprintf()
call, because its type could represent values which could overflow the
string (like "-128"):
> warning: ‘%i’ directive writing between 1 and 4 bytes into a region of
> size 3 [-Wformat-overflow=]
Increase the buffer size to remove the warning.
Trilinear filtering can currently only be enabled for OpenGL renderers.
Do not print a warning if the renderer is not OpenGL, as it can confuses
users, while nothing is wrong.
On macOS with renderer "metal", HiDPI scaling may be incorrect on
initialization when several displays are connected.
Resetting the window size fixes the problem.
Refs #15 <https://github.com/Genymobile/scrcpy/issues/15>
Position and scale the content "manually" instead of relying on the
renderer "logical size".
This avoids possible rounding differences between the computed window
size and the content size, causing one row or column of black pixels on
the bottom or on the right.
This also avoids HiDPI scale issues, by computing the scaling manually.
This will also enable to draw items at their expected size on the screen
(unscaled).
Fixes#15 <https://github.com/Genymobile/scrcpy/issues/15>
In maximized state (but not fullscreen), it was possible to resize to
fit the device screen (with Ctrl+x or double-clicking on black borders).
This caused problems on macOS with the "expand to fullscreen" feature,
which behaves like a fullscreen mode but is seen as maximized by SDL.
In that state, resizing to fit causes unexpected results.
To keep the behavior consistent on all platforms, just disable "resize
to fit" when the window is maximized.
On Windows, in maximized+fullscreen state, disabling fullscreen mode
unexpectedly triggers the "restored" then "maximized" events, leaving
the window in a weird state (maximized according to the events, but not
maximized visually).
Moreover, apply_pending_resize() asserts that fullscreen is disabled.
To avoid the issue, if fullscreen is set, just ignore the "restored"
event.
If the content size changes (due to rotation for example) while the
window is maximized or fullscreen, the resize must be applied once
fullscreen and maximized are disabled.
The previous strategy consisted in storing the windowed size, computing
the target size on rotation, and applying it on window restoration. But
tracking the windowed size (while ignoring the non-windowed size) was
tricky, due to unspecified order of SDL events (e.g. size changes can be
notified before "maximized" events), race conditions when reading window
flags, different behaviors on different platforms...
To simplify the whole resize management, store the old content size (the
frame size, possibly rotated) when it changes while the window is
maximized or fullscreen, so that the new optimal size can be computed on
window restoration.
By default, Ctrl+C just kills the process on Windows. This caused
corrupted video files on recording.
Handle Ctrl+C properly to clean up properly.
Fixes#818 <https://github.com/Genymobile/scrcpy/issues/818>
Scroll events were sent with a mouse input device. When scrolling on a
list, this could cause the whole list to be focused, and drawn with the
focus color as background.
Send scroll events with a touchscreen input device instead (like motion
events).
Fixes#1362 <https://github.com/Genymobile/scrcpy/issues/1362>
Now that the server can access the Android settings and clean up
properly, handle the "show touches" option from the server.
The initial state is now correctly restored, even on device
disconnection.
Expose methods to access the Android settings using private APIs.
This allows to read and write settings values immediately without
starting a new process to call "settings".
The window dimensions are integers, so resizing to fit the content may
not be exact.
When computing the optimal size, it could cause to reduce alternatively
the width and height by few pixels, making the "optimal size" unstable.
To avoid this problem, check if the optimal size is already correct
either by keeping the width or the height.
Move the window-to-frame coordinates conversion from the input manager
to the screen.
This will allow to apply more screen-related transformations without
impacting the input manager.
Some compilers warns on uninitialized value in impossible case:
warning: variable 'result' is used uninitialized whenever switch
default is taken [-Wsometimes-uninitialized]
A double-click outside the device content (in the black borders) resizes
so that black borders are removed. But the display rotation was not
taken into account to detect the content.
Use the content size instead of the frame size to fix the issue.
Ref: <https://github.com/Genymobile/scrcpy/issues/898#issuecomment-610993695>
Add Ctrl+Left and Ctrl+Right shortcuts to rotate the display (the
content of the scrcpy window).
Contrary to --lock-video-orientation, the rotation has no impact on
recording, and can be changed dynamically (and immediately).
Fixes#218 <https://github.com/Genymobile/scrcpy/issues/218>
People following default build instructions can be caught off guard by
seeing the build artifacts in the git tree.
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
Signed-off-by: Romain Vimont <rom@rom1v.com>
The server may die before connecting to the client. In that case, the
client was blocked indefinitely (until Ctrl+C) on accept().
To avoid the problem, close the server socket once the server process is
dead.
Binaries created with MinGW (even a simple Hello World) are detected as
malware by some anti-virus. For some reason, only the 32 bits version of
scrcpy is impacted.
Since users should use the 64 bits version by default anyway, remove the
link to the 32 bits version from the main page.
The 32 bits release is still available in the "releases" tab.
See <https://github.com/Genymobile/scrcpy/issues/1102>
2020-03-03 21:39:27 +01:00
262 changed files with 26541 additions and 7076 deletions
- [ ] I have checked that a similar [feature request](https://github.com/Genymobile/scrcpy/issues?q=is%3Aopen+is%3Aissue+label%3A%22feature+request%22) does not already exist.
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
이 어플리케이션은 아래 사항을 따라 설치한다면 [Homebrew] 에서도 사용 가능합니다 :
[Homebrew]: https://brew.sh/
```bash
brew install scrcpy
```
`PATH` 로부터 접근 가능한 `adb` 가 필요합니다. 아직 설치하지 않았다면 다음을 따라 설치해야 합니다 :
```bash
brew cask install android-platform-tools
```
[어플을 직접 설치][BUILD] 할 수도 있습니다.
## 실행
안드로이드 디바이스를 연결하고 실행하십시오:
```bash
scrcpy
```
다음과 같이 명령창 옵션 기능도 제공합니다.
```bash
scrcpy --help
```
## 기능
### 캡쳐 환경 설정
###사이즈 재정의
가끔씩 성능을 향상시키기위해 안드로이드 디바이스를 낮은 해상도에서 미러링하는 것이 유용할 때도 있습니다.
너비와 높이를 제한하기 위해 특정 값으로 지정할 수 있습니다 (e.g. 1024) :
```bash
scrcpy --max-size 1024
scrcpy -m 1024# 축약 버전
```
이 외의 크기도 디바이스의 가로 세로 비율이 유지된 상태에서 계산됩니다.
이러한 방식으로 디바이스 상에서 1920×1080 는 모니터 상에서1024×576로 미러링될 것 입니다.
### bit-rate 변경
기본 bit-rate 는 8 Mbps입니다. 비디오 bit-rate 를 변경하기 위해선 다음과 같이 입력하십시오 (e.g. 2 Mbps로 변경):
```bash
scrcpy --bit-rate 2M
scrcpy -b 2M # 축약 버전
```
###프레임 비율 제한
안드로이드 버전 10이상의 디바이스에서는, 다음의 명령어로 캡쳐 화면의 프레임 비율을 제한할 수 있습니다:
```bash
scrcpy --max-fps 15
```
### Crop (잘라내기)
디바이스 화면은 화면의 일부만 미러링하기 위해 잘라질 것입니다.
예를 들어, *Oculus Go* 의 한 쪽 눈만 미러링할 때 유용합니다 :
```bash
scrcpy --crop 1224:1440:0:0 # 1224x1440 at offset (0,0)
scrcpy -c 1224:1440:0:0 # 축약 버전
```
만약 `--max-size` 도 지정하는 경우, 잘라낸 다음에 재정의된 크기가 적용될 것입니다.
### 화면 녹화
미러링하는 동안 화면 녹화를 할 수 있습니다 :
```bash
scrcpy --record file.mp4
scrcpy -r file.mkv
```
녹화하는 동안 미러링을 멈출 수 있습니다 :
```bash
scrcpy --no-display --record file.mp4
scrcpy -Nr file.mkv
# Ctrl+C 로 녹화를 중단할 수 있습니다.
# 윈도우 상에서 Ctrl+C 는 정상정으로 종료되지 않을 수 있으므로, 디바이스 연결을 해제하십시오.
```
"skipped frames" 은 모니터 화면에 보여지지 않았지만 녹화되었습니다 ( 성능 문제로 인해 ). 프레임은 디바이스 상에서 _타임 스탬프 ( 어느 시점에 데이터가 존재했다는 사실을 증명하기 위해 특정 위치에 시각을 표시 )_ 되었으므로, [packet delay
<pathstyle="opacity:0.2"d="m 16.846877,12 c -1.116351,0 -2.227419,0.912229 -2.015075,2 l 3.122973,16 -5.596557,11.109375 C 11.959876,41.871734 11.885244,42.336988 12.177176,43 c 0.278672,0.632897 0.998812,1 1.747448,1 H 24 34.075375 c 0.748637,0 1.468777,-0.367103 1.747448,-1 0.291932,-0.663012 0.217302,-1.128266 -0.181041,-1.890625 L 30.045225,30 33.168198,14 c 0.212344,-1.087771 -0.898724,-2 -2.015075,-2 H 24 Z"/>
<pathstyle="fill:#cccccc"d="m 16.846877,11 c -1.116351,0 -2.227419,0.912229 -2.015075,2 l 3.122973,16 -5.596557,11.109375 C 11.959876,40.871734 11.885244,41.336988 12.177176,42 c 0.278672,0.632897 0.998812,1 1.747448,1 H 24 34.075375 c 0.748637,0 1.468777,-0.367103 1.747448,-1 0.291932,-0.663012 0.217302,-1.128266 -0.181041,-1.890625 L 30.045225,29 33.168198,13 c 0.212344,-1.087771 -0.898724,-2 -2.015075,-2 H 24 Z"/>
<pathstyle="fill:#e4e4e4"d="m 4,33 v 2 c 0,1.108 0.892,2 2,2 h 36 c 1.108,0 2,-0.892 2,-2 v -2 z"/>
<pathstyle="opacity:0.1"d="m 11.494141,15 a 1.5,1.5 0 0 0 -0.832032,0.255859 1.5,1.5 0 0 0 -0.40625,2.082032 l 3.13086,4.654297 C 10.404945,24.606192 8.4012371,28.299159 8.0019531,32.460938 7.9284599,34.000879 9.5546875,34 9.5546875,34 H 38.40625 c 0,0 1.672856,-3.38e-4 1.591797,-1.617188 -0.416529,-4.131451 -2.415618,-7.796833 -5.380859,-10.394531 l 3.126953,-4.65039 a 1.5,1.5 0 0 0 -0.40625,-2.082032 1.5,1.5 0 0 0 -1.125,-0.228515 1.5,1.5 0 0 0 -0.957032,0.634765 l -3.072265,4.566407 C 29.78649,18.814887 26.990024,18 24.001953,18 c -2.989385,0 -5.786177,0.815488 -8.183594,2.230469 l -3.074218,-4.56836 A 1.5,1.5 0 0 0 11.787109,15.027344 1.5,1.5 0 0 0 11.494141,15 Z"/>
<pathstyle="fill:#077063"d="M 6,5 C 4.892,5 4,5.892 4,7 V 33 H 44 V 7 C 44,5.892 43.108,5 42,5 Z"/>
<pathstyle="opacity:0.1;fill:#ffffff"d="M 6,5 C 4.892,5 4,5.892 4,7 V 8 C 4,6.892 4.892,6 6,6 h 36 c 1.108,0 2,0.892 2,2 V 7 C 44,5.892 43.108,5 42,5 Z"/>
<pathstyle="fill:#30dd81"d="m 24.002386,17.000034 c -8.355868,0 -15.2214979,6.346843 -15.9999669,14.460906 C 7.9289259,33.000882 9.5544999,33 9.5544999,33 H 38.406003 c 0,0 1.672201,-3.35e-4 1.591142,-1.617185 C 39.182807,23.305596 32.331836,17.000034 24.002386,17.000034 Z"/>
@ -20,10 +20,28 @@ provides display and control of Android devices connected on USB (or over TCP/IP
Make scrcpy window always on top (above other windows).
.TP
.BI"\-b, \-\-bit\-rate "value
.BI"\-\-audio\-bit\-rate "value
Encode the audio at the given bit\-rate, expressed in bits/s. Unit suffixes are supported: '\fBK\fR' (x1000) and '\fBM\fR' (x1000000).
Default is 196K (196000).
.TP
.BI"\-\-audio\-codec "name
Select an audio codec (opus or aac).
Default is opus.
.TP
.BI"\-\-audio\-encoder "name
Use a specific MediaCodec audio encoder (depending on the codec provided by \fB\-\-audio\-codec\fR).
The available encoders can be listed by \-\-list\-encoders.
.TP
.BI"\-b, \-\-video\-bit\-rate "value
Encode the video at the given bit\-rate, expressed in bits/s. Unit suffixes are supported: '\fBK\fR' (x1000) and '\fBM\fR' (x1000000).
Default is 8000000.
Default is 8M (8000000).
.TP
.BI"\-\-crop "width\fR:\fIheight\fR:\fIx\fR:\fIy
@ -33,6 +51,44 @@ 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.
.TP
.BI"\-\-display "id
Specify the device display id to mirror.
The available display ids can be listed by \-\-list\-displays.
Default is 0.
.TP
.BI"\-\-display\-bufferms
Add a buffering delay (in milliseconds) before displaying. This increases latency to compensate for jitter.
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
.B\-\-force\-adb\-forward
Do not attempt to use "adb reverse" to connect to the device.
.TP
.B\-\-forward\-all\-clicks
By default, right-click triggers BACK (or POWER on) and middle-click triggers HOME. This option disables these shortcuts and forward the clicks to the device instead.
.TP
.B\-f,\-\-fullscreen
Start in fullscreen.
@ -42,10 +98,42 @@ Start in fullscreen.
Print this help.
.TP
.BI"\-\-lock\-video\-orientation "value
Lock video orientation to \fIvalue\fR. Values are integers in the range [-1..3]. Natural device orientation is 0 and each increment adds 90 degrees counterclockwise.
.B\-K,\-\-hid\-keyboard
Simulate a physical keyboard by using HID over AOAv2.
Default is -1 (unlocked).
This provides a better experience for IME users, and allows to generate non-ASCII characters, contrary to the default injection method.
It may only work over USB.
The keyboard layout must be configured (once and for all) on the device, via Settings -> System -> Languages and input -> Physical keyboard. This settings page can be started directly:
adb shell am start -a android.settings.HARD_KEYBOARD_SETTINGS
However, the option is only available when the HID keyboard is enabled (or a physical keyboard is connected).
Also see \fB\-\-hid\-mouse\fR.
.TP
.B\-\-legacy\-paste
Inject computer clipboard text as a sequence of key events on Ctrl+v (like MOD+Shift+v).
This is a workaround for some devices not behaving as expected when setting the device clipboard programmatically.
.TP
.B\-\-list\-encoders
List video and audio encoders available on the device.
.TP
.B\-\-list\-displays
List displays available on the device.
.TP
\fB\-\-lock\-video\-orientation\fR[=\fIvalue\fR]
Lock video orientation to \fIvalue\fR. Possible values are "unlocked", "initial" (locked to the initial orientation), 0, 1, 2 and 3. Natural device orientation is 0, and each increment adds a 90 degrees rotation counterclockwise.
Default is "unlocked".
Passing the option without argument is equivalent to passing "initial".
.TP
.BI"\-\-max\-fps "value
@ -57,6 +145,36 @@ Limit both the width and height of the video to \fIvalue\fR. The other dimension
Default is 0 (unlimited).
.TP
.B\-M,\-\-hid\-mouse
Simulate a physical mouse by using HID over AOAv2.
In this mode, the computer mouse is captured to control the device directly (relative mouse mode).
LAlt, LSuper or RSuper toggle the capture mode, to give control of the mouse back to the computer.
It may only work over USB.
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.
This option disables this automatic synchronization.
.TP
.B\-\-no\-downsize\-on\-error
By default, on MediaCodec error, scrcpy automatically tries again with a lower definition.
This option disables this behavior.
.TP
.B\-n,\-\-no\-control
Disable device control (mirror the device in read\-only).
@ -66,11 +184,41 @@ Disable device control (mirror the device in read\-only).
Do not display device (only when screen recording is enabled).
.TP
.BI"\-p, \-\-port "port[:port]
.B\-\-no\-key\-repeat
Do not forward repeated key events when a key is held down.
.TP
.B\-\-no\-mipmaps
If the renderer is OpenGL 3.0+ or OpenGL ES 2.0+, then mipmaps are automatically generated to improve downscaling quality. This option disables the generation of mipmaps.
.TP
.B\-\-no\-power\-on
Do not power on the device on start.
.TP
.B\-\-otg
Run in OTG mode: simulate physical keyboard and mouse, as if the computer keyboard and mouse were plugged directly to the device via an OTG cable.
In this mode, adb (USB debugging) is not necessary, and mirroring is disabled.
LAlt, LSuper or RSuper toggle the mouse capture mode, to give control of the mouse back to the computer.
If any of \fB\-\-hid\-keyboard\fR or \fB\-\-hid\-mouse\fR is set, only enable keyboard or mouse respectively, otherwise enable both.
It may only work over USB.
See \fB\-\-hid\-keyboard\fR and \fB\-\-hid\-mouse\fR.
.TP
.BI"\-p, \-\-port "port\fR[:\fIport\fR]
Set the TCP port (range) used by the client to listen.
Default is 27183:27199.
.TP
.B\-\-power\-off\-on\-close
Turn the device screen off when closing scrcpy.
.TP
.B\-\-prefer\-text
Inject alpha characters and space as text events instead of key events.
@ -78,11 +226,19 @@ Inject alpha characters and space as text events instead of key events.
This avoids issues when combining multiple keys to enter special characters,
but breaks the expected behavior of alpha keys in games (typically WASD).
.TP
.B"\-\-print\-fps
Start FPS counter, to print framerate logs to the console. It can be started or stopped at any time with MOD+i.
.TP
.BI"\-\-push\-target "path
Set the target directory for pushing files to the device by drag & drop. It is passed as\-is to "adb push".
Default is "/sdcard/".
Default is "/sdcard/Download/".
.TP
.B\-\-raw\-key\-events
Inject key events for all input keys, and ignore text events.
.TP
.BI"\-r, \-\-record "file
@ -98,27 +254,112 @@ option if set, or by the file extension (.mp4 or .mkv).
Force recording format (either mp4 or mkv).
.TP
.B\-\-render\-expired\-frames
By default, to minimize latency, scrcpy always renders the last available decoded frame, and drops any previous ones. This flag forces to render all frames, at a cost of a possible increased latency.
.BI"\-\-render\-driver "name
Request SDL to use the given render driver (this is just a hint).
Supported names are currently "direct3d", "opengl", "opengles2", "opengles", "metal" and "software".
.URhttps://wiki.libsdl.org/SDL_HINT_RENDER_DRIVER
.UE
.TP
.BI"\-\-rotation "value
Set the initial display rotation. Possibles values are 0, 1, 2 and 3. Each increment adds a 90 degrees rotation counterclockwise.
.TP
.BI"\-s, \-\-serial "number
The device serial number. Mandatory only if several devices are connected to adb.
.TP
.BI"\-\-shortcut\-mod "key\fR[+...]][,...]
Specify the modifiers to use for scrcpy shortcuts. Possible keys are "lctrl", "rctrl", "lalt", "ralt", "lsuper" and "rsuper".
A shortcut can consist in several keys, separated by '+'. Several shortcuts can be specified, separated by ','.
For example, to use either LCtrl+LAlt or LSuper for scrcpy shortcuts, pass "lctrl+lalt,lsuper".
Default is "lalt,lsuper" (left-Alt or left-Super).
.TP
.BI"\-\-tcpip\fR[=\fIip\fR[:\fIport\fR]]
Configure and reconnect the device over TCP/IP.
If a destination address is provided, then scrcpy connects to this address before starting. The device must listen on the given TCP port (default is 5555).
If no destination address is provided, then scrcpy attempts to find the IP address and adb port of the current device (typically connected over USB), enables TCP/IP mode if necessary, then connects to this address before starting.
.TP
.B\-S,\-\-turn\-screen\-off
Turn the device screen off immediately.
.TP
.B\-t,\-\-show\-touches
Enable "show touches" on start, disable on quit.
Enable "show touches" on start, restore the initial value on exit.
It only shows physical touches (not clicks from scrcpy).
.TP
.BI"\-\-tunnel\-host "ip
Set the IP address of the adb tunnel to reach the scrcpy server. This option automatically enables --force-adb-forward.
Default is localhost.
.TP
.BI"\-\-tunnel\-port "port
Set the TCP port of the adb tunnel to reach the scrcpy server. This option automatically enables --force-adb-forward.
Default is 0 (not forced): the local port used for establishing the tunnel will be used.
.TP
.BI"\-\-v4l2-sink "/dev/videoN
Output to v4l2loopback device.
It requires to lock the video orientation (see \fB\-\-lock\-video\-orientation\fR).
.TP
.BI"\-\-v4l2-buffer "ms
Add a buffering delay (in milliseconds) before pushing frames. This increases latency to compensate for jitter.
This option is similar to \fB\-\-display\-buffer\fR, but specific to V4L2 sink.
Default is 0 (no buffering).
.TP
.BI"\-V, \-\-verbosity "value
Set the log level ("verbose", "debug", "info", "warn" or "error").
Default is "info" for release builds, "debug" for debug builds.
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.