Control messages are queued from the main thread and sent to the device
from a separate thread.
When the queue is full, messages are just dropped. This avoids to
accumulate too much delay between the client and the device in case of
network issue.
However, some messages should not be dropped: for example, dropping a
UHID_CREATE message would make all further UHID_INPUT messages invalid.
Therefore, mark these messages as non-droppable.
A non-droppable event is queued anyway (resizing the queue if
necessary, unless the allocation fails).
PR #5270 <https://github.com/Genymobile/scrcpy/pull/5270>
This allows to schedule a runnable to be executed on the main thread,
until the event loop is explicitly terminated.
It is guaranteed that all accepted runnables will be executed (this
avoids possible memory leaks if a runnable owns resources).
PR #5270 <https://github.com/Genymobile/scrcpy/pull/5270>
It is better to disable Nagle's algorithm to avoid unnecessary latency
for control messages. (I'm not sure this has any impact for a local TCP
socket though.)
Many parsing and formatting C functions like strtof() and asprintf() are
locale-dependent. Forcing a C locale just for the conversions in a way
that works on all platforms is a mess.
In practice, this is not a problem, scrcpy always uses the C locale,
because it never calls:
setlocale(LC_ALL, "");
But the max-fps option should not depend on the locale configuration
anyway.
Since the value is parsed by the client in Java anyway, just forward the
string value as is.
Android accepts a float value, there is no reason to limit the option
to be an integer.
In particular, it allows to capture at a rate lower than 1 fps. For
example, to capture 1 frame every 5 seconds:
scrcpy --video-source=camera --max-fps=0.2
It was already possible to pass a float manually:
scrcpy --video-source=camera \
--video-codec-options=max-fps-to-encoder:float=0.2
But accepting a float directly for --max-fps is more convenient.
Refs <https://developer.android.com/reference/android/media/MediaFormat#KEY_MAX_FPS_TO_ENCODER>
A video width or height of 0 triggered an assert.
Fail explicitly instead: the server may actually send this size in
practice (for example on cropping with small dimensions, even if the
requested crop size is not 0).
The delay buffer clock estimates the clock offset between the PTS and
the frame decoded date using an "Exponentially Weighted Moving Average"
(EWMA).
But for the first frames, the clock have less than SC_CLOCK_RANGE
points to average. Since the timing for the first frames are typically
the worst ones, give more weight to the last point for the estimation.
Once SC_CLOCK_RANGE points are available (i.e. when SC_CLOCK_RANGE ==
clock->range), the new estimation is equivalent to the previous version.
The delay buffer `stopped` field was not initialized.
Since it practice the unique instance of sc_delay_buffer is initialized
in static memory, the flag was initialized to false as a side effect.
But with commit fd0f432e87, in debug mode
only, the delay buffer was broken.
"Could not" implies that the system tried to disable the option but
encountered an issue or failure.
"Cannot" indicates a rule or restriction, meaning it's not possible to
perform the action at all.
In Java, control messages were parsed using manual buffering, which was
convoluted and error-prone.
Instead, read the socket directly through a DataInputStream and a
BufferedInputStream. Symmetrically, use a DataOutputStream and a
BufferedOutputStream to write messages.
Even if the pointer is a mouse, inject it as a finger unless it is
required to be a mouse, that is:
- when it is a HOVER_MOUSE event, or
- when a secondary button is pressed.
Some apps/games only accept events from a finger/touchscreen, so using a
mouse by default does not work for them.
For simplicity, make this change on the server side just before
event injection (so that the client does not need to know about this
hacky behavior).
Refs 6808288823
Refs c7b1d0ea9aFixes#5162 <https://github.com/Genymobile/scrcpy/issues/5162>
Fixes#5163 <https://github.com/Genymobile/scrcpy/issues/5163>
By default, the audio source is initialized to SC_AUDIO_SOURCE_AUTO, and
is "resolved" only if audio is enabled.
But the server arguments were built assuming that the audio source was
never SC_AUDIO_SOURCE_AUTO (even with audio disabled), causing a crash.
Regression introduced by a10f8cd798.
Automatically switch implicit audio source to "playback" if --audio-dup
is passed.
This allows to run:
scrcpy --audio-dup
without specifying explicitly:
scrcpy --audio-source=playback --audio-dup
PR #5102 <https://github.com/Genymobile/scrcpy/pull/5102>
Add a new method to capture audio playback.
It requires Android 13 (where the Shell app has MODIFY_AUDIO_ROUTING
permission).
The main benefit is that it supports keeping audio playing on the device
(implemented in a further commit).
Fixes#4380 <https://github.com/Genymobile/scrcpy/issues/4380>
PR #5102 <https://github.com/Genymobile/scrcpy/pull/5102>
Co-authored-by: Simon Chan <1330321+yume-chan@users.noreply.github.com>
The MediaRecorder constant should not belong to the AudioSource enum.
This will allow to add a new AudioSource which has no meaningful
MediaRecorder audio source value.
PR #5102 <https://github.com/Genymobile/scrcpy/pull/5102>
Move the implementation to AudioDirectCapture and extract an
AudioCapture interface.
This will allow to provide another AudioCapture implementation.
PR #5102 <https://github.com/Genymobile/scrcpy/pull/5102>