Commit Graph

2393 Commits (uhid.38)
 

Author SHA1 Message Date
Romain Vimont 5ebf31d483 Remove useless screen render on initialization
screen_render() should not be called on initialization:
 1. it is useless, since the window is hidden until the first frame;
 2. it writes an empty texture (probably green) to the renderer.
6 years ago
Romain Vimont d977202224 Add Ctrl+i shortcut to enable/disable FPS counter
Disable FPS counter on start, and use Ctrl+i to enable/disable it.
6 years ago
Romain Vimont 000ced9ba8 Refactor screencontrol to inputmanager
The "screen control" handled user input, which happened to be only
used to control the screen.

The controller and screen were passed to every function. Instead, group
them in a struct input_manager.

The purpose is to add a new shortcut to enable/disable FPS counter. This
feature is not related to "screen control", and will require access to
the "frames" instance.
6 years ago
Romain Vimont fb0e467585 Add description for meson options
The descriptions are displayed in the result of:

    mesonconf builddir
6 years ago
Romain Vimont 42882702d7 Expose skip_frames as a build option
It can be initially configured by:

    meson builddir -Dskip_frames=false

Or on an existing builddir by:

    mesonconf builddir -Dskip_frames=false
6 years ago
Romain Vimont 38e6682875 Add FPS counter
Remove frame counter from scrcpy.c and add a new FPS counter, logging as
INFO the measured frame rate every second (on new frame).
6 years ago
Romain Vimont c6c17af840 Do not print usage on command error
On error, a message is printed. If we print usage afterwards, it's easy
to miss it.
6 years ago
Romain Vimont 8697659890 Expose device serial as an optional argument
The device serial was provided as a positional argument:

    scrcpy 0123456789abcdef

Instead, expose it as an optional argument, -s or --serial:

    scrcpy -s 0123456789abcdef

This avoids inconsistency between platforms when the positional
argument is passed before the options (which is undefined).
6 years ago
Romain Vimont 23d92a95b6 Extract argument parsing to specific functions
To avoid a big switch/case, implement the argument parsing logic in
separate static functions.
6 years ago
Romain Vimont 111068d733 Use SDL_bool return to indicate success
For clarity and consistency across the application, return SDL_TRUE
(instead of 0) on success and SDL_FALSE on failure (instead of
non-zero).
6 years ago
Romain Vimont d3c76c004e Sort parameters by letter
For readability, sort the command-line arguments parsing by letter.
6 years ago
Romain Vimont 9a07b694f1 Add run script
Add a script to simplify the execution of scrcpy generated in a specific
build directory.

To run scrcpy generated in builddir, with a video size of 1024:

    ./run builddir -m 1024
6 years ago
Romain Vimont 07983d914f Accept prebuilt server
Expose a 'prebuilt_server' option to pass the path of the prebuilt
binary, so that the build does not require Android SDK.

Usage:

    meson builddir -Dprebuilt_server=/tmp/my_prebuilt_server.jar
6 years ago
Romain Vimont 0efa9305eb Require Meson 0.37
Older versions of Meson are too limited, and it's simple to install a
newer version ("pip3 install meson").
6 years ago
Romain Vimont 4c49b27e9f Always invoke gradle except as root
The custom target used to invoke Gradle from Meson should always
be built, otherwise, the server would not be rebuilt on source changes.

However, when enabling "build_always", gradle is invoked as root on
"sudo ninja install" after "ninja", so it downloads the whole Gradle
world into /root/.gradle.

To avoid the problem, just do not call gradle if the effective user id
is 0.
6 years ago
Romain Vimont c2127d0819 Replace meson subprojects by subdir
Since Meson 0.44, subproject_dir may not be '.' anymore. This implies we
must move app/ and server/ to a subprojects/ directory, which requires
to also change some gradle files.

Instead, just use subdir(), with options to disable building of the app
or the server.
6 years ago
Romain Vimont ff94462d8a Refactor build system
The client was built with Meson, the server with Gradle, and were run by
a Makefile.

Add a Meson script for the server (which delegates to Gradle), and a
parent script to build and install both the client and the server to the
system, typically with:

    meson --buildtype release build
    cd build
    ninja
    sudo ninja install

In addition, use a separate Makefile to build a "portable" version of
the application (where the client expects the server to be in the
current directory). Typically:

    make release-portable
    cd dist/scrcpy
    ./scrcpy

This is especially useful for Windows builds, which are not "installed".
6 years ago
Romain Vimont 396df8a9d8 Provide config.h.in for old meson versions
The current meson version is able to generate a config.h from a
configuration data object without any template.

However, older versions of meson require a template, so provide it for
compatibility.
6 years ago
Romain Vimont 3ed80a1fac Define macros wrappers for logs
Use macros to wrap SDL_Log* functions with the "application" category.
6 years ago
Romain Vimont d45ef1a295 Do not use too recent set_quoted()
Old versions of meson do not support set_quoted(). Replace the call by
the old-fashioned manual quotation.
6 years ago
Romain Vimont a5b6c6cc2d Enable debug logs only for debug builds on server
Print the logs only if their level is not under the threshold, which is
defined to INFO in release mode and DEBUG in debug mode.
6 years ago
Romain Vimont ad41bacb48 Fix "terminate process" on Windows
CloseHandle() does not terminate the process. TerminateProcess() does.
6 years ago
Romain Vimont 6fe65d9f5c Log with category APPLICATION
All our logs should use APPLICATION category. The logs for other
categories are not printed by default under the "critical" level.
6 years ago
Romain Vimont 598ddcbfbc Disable sanitizer on debug builds
On our Windows machine, the mingw ld.exe does not support sanitizers.

Exclude them from the default debug build.
6 years ago
Romain Vimont 4dbc450d01 Enable debug logs only for debug builds
In release mode, use the default log priorities.
6 years ago
Romain Vimont 2f3e00ed98 Enable link-time optimization for release
Because why not.
6 years ago
Romain Vimont 000c70a644 Decompose accented characters
Characters like 'é' or 'î' are not resolved by getEvents(). For example,
getEvents("é") returns null.

However, it is possible to decompose them. For example,
getEvents("\u0301e") returns the events generating "é".

Thank you Philippe! ;)
6 years ago
Romain Vimont 0fce4f95b9 Properly clean up on exit
The SDL clean up does not crash anymore on exit, probably since the
memory corruption caused by calling SDLNet_TCP_Close() too early has
been resolved.
6 years ago
Romain Vimont eb09fefd43 Timeout the server socket connection
Wait no more than 2 seconds for accepting the connection from the
device, since it blocks the event loop, preventing to react to SIGTERM
(Ctrl+C).
6 years ago
Romain Vimont 90a46b4c45 Improve startup time
On startup, the client has to:
 1. listen on a port
 2. push and start the server to the device
 3. wait for the server to connect (accept)
 4. read device name and size
 5. initialize SDL
 6. initialize the window and renderer
 7. show the window

From the execution of the app_process command to start the server on the
device, to the execution of the java main method, it takes ~800ms. As a
consequence, step 3 also takes ~800ms on the client.

Once complete, the client initializes SDL, which takes ~500ms.

These two expensive actions are executed sequentially:

                     HOST              DEVICE
listen on port        |                  |
push/start the server |----------------->|| app_process loads the jar
accept the connection .   ^              ||
                      .   |              ||
                      .   | WASTE        ||
                      .   |  OF          ||
                      .   | TIME         ||
                      .   |              ||
                      .   |              ||
                      .   v              X execution of our java main
connection accepted   |<-----------------| connect to the host
init SDL             ||                  |
                     || ,----------------| send frames
                     || |,---------------|
                     || ||,--------------|
                     || |||,-------------|
                     || ||||,------------|
init window/renderer  | |||||,-----------|
display frames        |<++++++-----------|
(many frames skipped)

The rationale for step 3 occuring before step 5 is that initializing
SDL replaces the SIGTERM handler to receive the event in the event loop,
so pressing Ctrl+C during step 5 would not work (since it blocks the
event loop).

But this is not so important; let's parallelize the SDL initialization
with the app_process execution (we'll just add a timeout to the
connection):

                     HOST              DEVICE
listen on port        |                  |
push/start the server |----------------->||app_process loads the jar
init SDL             ||                  ||
                     ||                  ||
                     ||                  ||
                     ||                  ||
                     ||                  ||
                     ||                  ||
accept the connection .                  ||
                      .                  X execution of our java main
connection accepted   |<-----------------| connect to the host
init window/renderer  |                  |
display frames        |<-----------------| send frames
                      |<-----------------|

In addition, show the window only once the first frame is available to
avoid flickering (opening a black window for 100~200ms).

Note: the window and renderer are initialized after the connection is
accepted because they use the device information received from the
device.
6 years ago
Romain Vimont 063cfd1326 Turn screen on in control()
Turning the screen on is semantically associated to control(): only
creating the EventController object should not turn the screen on.
6 years ago
Romain Vimont 523097eadf Provide decoder_init()
Expose an initializer so that the caller does not have to guess what
fields must be initialized.
6 years ago
Romain Vimont 4662198261 Do not release TCP sockets while still in use
SDLNet_TCP_Close() not only closes, but also release the resources.

Therefore, we must not close the socket if another thread attempts to
read it.

For that purpose, move socket closing from server_stop() to
server_destroy().
6 years ago
Romain Vimont d658586d0d Enable sanitizer in debug builds
"make build-debug" will build with ASAN and USAN enabled.
6 years ago
Romain Vimont fe21d9dfb5 Move frame updating to screen.c
Replace screen_update() by a higher-level screen_update_frame() handling
the whole frame updating, so that scrcpy.c just call it without managing
implementation details.
6 years ago
Romain Vimont 7458d8271e Kill the server immediately on close
Do not wait 100ms anymore to let the server print any exception: we
justly want to ignore them.

Moreover, there is no nanosleep() on Windows, so this solve another
problem.
6 years ago
Romain Vimont c683872bbc Avoid server stacktraces on close
On close, the socket is closed by the client, and the server process is
killed.

This leads to (expected) exceptions, that should not be printed.
6 years ago
Romain Vimont 2fdc368c41 Do not try to decode video when EOF is reached
When the video stream socket is closed and read_packey() returns -1,
av_read_frame() still returns 0.

To detect EOF, check the flag eof_reached in the AVIOContext.

This avoids garbage errors on closing.
6 years ago
Romain Vimont a8aa3d39b7 Send "screen on" command only on mouse down
Avoid to send the command twice, once on mouse down, once on mouse up.
6 years ago
Romain Vimont 127e56780a Fix deadlock on exit if SKIP_FRAMES disabled
On exit, the renderer will not consume frames anymore, so signal the
condition variable to wake up the decoder.
6 years ago
Romain Vimont 629c296207 Move frame swapping logic to frame.c
Expose frames_offer_decoded_frame() and frames_consume_rendered_frame()
so that callers are not exposed to frame swapping (between the decoding
and rendering frames) details.
6 years ago
Romain Vimont 0d7f050389 Unlock mutex on screen update failure
The mutex was not unlocked on all code paths.
6 years ago
Romain Vimont e8dfb723af Move control-related code to screencontrol.c
Move the code handling user input from scrcpy.c to a separate file,
screencontrol.c.
6 years ago
Romain Vimont e1749a0c09 Remove the "adb reverse" tunnel immediately
As soon as we accepted a connection, we can remove the "adb reverse"
tunnel.
6 years ago
Romain Vimont 3b06e7d500 Move device-related code to device.c
Move the code to read the initial device info from scrcpy.c to a
separate file, device.c.
6 years ago
Romain Vimont 28c5cc030b Move server-related code to server.c
The file server.c already existed, but exposed a low-level API. Make it
higher-level, so that scrcpy.c does not handle server details directly.
6 years ago
Romain Vimont 6c578b5caa Move screen-related code to screen.c
The file scrcpy.c contains too many different things in addition to the
main logic, so move the screen code to a separate file, screen.c.
6 years ago
Romain Vimont 14c58546a7 Add missing include guards
In practice, these headers are included only once, but it's a good
practice to always use include guards.
6 years ago
Romain Vimont ffae15e36a Rename control to controller
The struct decoder is defined in decoder.h.

For naming consistency, define the struct controller in controller.h.
6 years ago
Romain Vimont 7b7fd77134 Add missing static
Some functions in scrcpy.c are not used outside the file, so declare
them static.
6 years ago