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