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.
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>