In the recorder, if the video or audio stream is disabled, do not wait
for its initialization (it will never happen) to process the header.
In that case (scrcpy --no-audio --record=file.mp4), this caused the
whole content to be buffered in memory, and written only on exit.
The sc_cond_wait() in sc_recorder_process_header() needs to be notified
of changes to video_init/audio_init (protected by stream_cond) and
video_queue/audio_queue (protected by queue_cond).
Use only one condition variable to simplify.
The comment was outdated:
- the "meta" header is now always present (not only when recording is
enabled);
- it is not only used for the video stream, but also for the audio
stream.
On some window managers (e.g. on Windows), performing a resize while the
window is minimized does nothing (the restored window keeps its old
size).
Therefore, like for maximized and fullscreen states, wait for the window
to be restored to apply a resize.
Refs #3947 <https://github.com/Genymobile/scrcpy/issues/3947>
When the scrcpy window is minimized on Windows with D3D9, texture
creation and update fail.
In that case, do not terminate scrcpy. Instead, store the pending size
or frame to update, to attempt again during the next update or
rendering.
Fixes#3947 <https://github.com/Genymobile/scrcpy/issues/3947>
Some server parameters may depend on one another. For example,
audio_bit_rate is meaningless if audio is false.
But it is inconsistent to disable some parameters based on these
dependencies checks, but not others. Handling all dependencies between
parameters would add too much complexity for no benefit.
So just pass individual parameters independently.
PR #3978 <https://github.com/Genymobile/scrcpy/pull/3978>
By default, SDL creates an OpenGL 2.1 context on macOS for an OpenGL
renderer. As a consequence, mipmapping is not supported.
Force to use a core profile context, to get a higher version.
Before:
INFO: Renderer: opengl
INFO: OpenGL version: 2.1 NVIDIA-14.0.32 355.11.11.10.10.143
WARN: Trilinear filtering disabled (OpenGL 3.0+ or ES 2.0+ required)
After:
INFO: Renderer: opengl
DEBUG: Creating OpenGL Core Profile context
INFO: OpenGL version: 4.1 NVIDIA-14.0.32 355.11.11.10.10.143
INFO: Trilinear filtering enabled
when running with:
scrcpy --verbosity=debug --render-driver=opengl
Note: Since SDL_CreateRenderer() causes a fallback to OpenGL 2.1, the
profile and version attributes have to be set and the context created
_after_.
PR #3895 <https://github.com/Genymobile/scrcpy/pull/3895>
Signed-off-by: Romain Vimont <rom@rom1v.com>
If a line did not end with '\r', then the final `\n' was replaced by
'\0' for parsing the current line. This `\0` was then mistakenly
considered as the end of the whole "ip route" output, so the remaining
lines were not parsed, causing "scrcpy --tcpip" to fail in some cases.
To fix the issue, read the final character of the current line before it
is (possibly) overwritten by '\0'.
The slope encodes the drift between the device clock and the computer
clock. Its real value is expected very close to 1.
To estimate it, just assume it is exactly 1.
Since the clock is used to estimate very close points in the future, the
error caused by clock drift is totally negligible, and in practice it is
way lower than the slope estimation error.
Therefore, only estimate the offset.
On some systems, the SDL audio callback is not called frequently enough
(for example it requests 5ms of samples every 10ms), because the output
buffer is too small.
By default, we want to use a small value (5ms) to minimize latency and
buffer underrun, but if it does not work well, users need a way to
increase it.
Refs #3793 <https://github.com/Genymobile/scrcpy/issues/3793>
An int was compared with an unsigned:
../app/src/audio_player.c:290:27: warning: comparison of integers of
different signs: 'int' and 'unsigned int' [-Wsign-compare]
if (abs(diff) < ap->sample_rate / 1000) {
~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~
In C, a label can only be followed by a statement, not a declaration.
An error in `app/src/screen.c` violated this, and led to a build error
with an error message similar to the one below:
../app/src/screen.c:821:13: error: expected expression
bool ok = sc_screen_init_size(screen);
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/13.0.0/include/stdbool.h:15:14: note: expanded from macro 'bool'
#define bool _Bool
^
../app/src/screen.c:822:18: error: use of undeclared identifier 'ok'
if (!ok) {
^
2 errors generated.
This could be fixed by introducing a new block (or compound statement;
as is already being done in the next `case`). That is a statement.
Fixes#3785 <https://github.com/Genymobile/scrcpy/issues/3785>
PR #3787 <https://github.com/Genymobile/scrcpy/pull/3787>
Signed-off-by: Ruoyu Zhong <zhongruoyu@outlook.com>
Signed-off-by: Romain Vimont <rom@rom1v.com>
On buffer underflow, the average buffering must be updated, but it is
intended to be accessed only from the receiver thread.
Make the player and the receiver thread communicate the underflow via a
new field (ap->underflow).
On initial connection, scrcpy sent some device metadata:
- the device name (to be used as window title)
- the initial video size (before any frame or even SPS/PPS)
But it is better to provide the initial video size as part as the video
stream, so that it can be demuxed and exposed via AVCodecContext to
sinks.
This avoids to pass an explicit "initial frame size" for the screen, the
recorder and the v4l2 sink.
Previously, the packet sink push() implementation just set the codec and
notified a wait condition. Then the recorder thread read the codec and
created the AVStream.
But this was racy: an AVFrame could be pushed before the creation of the
AVStream, causing its video_stream_index or audio_stream_index to be
initialized to -1.
Also, in the future, the AVStream initialization might need data
provided by the packet sink open(), so initialize it there (with a
mutex).
The sc_file_pusher is lazy-initialized, but it was stopped and joined in
all cases (accessing uninitialized values).
Detected by poisoning the struct scrcpy instance with ASAN enabled.
All server logs were printed to stdout, while all client logs were
printed to stderr.
Instead, use stderr for warnings and errors, stdout for the others:
- stdout: verbose, debug, info
- stderr: warn, error
Expose an option to add a buffering delay (in milliseconds) before
playing audio.
This is similar to the options --display-buffer and --v4l2-buffer for
video frames.
PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
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.
PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
Co-authored-by: Simon Chan <1330321+yume-chan@users.noreply.github.com>
A delay buffer delayed all the frames except the first one, to open the
scrcpy window immediately and get a picture.
Make this feature optional, so that the delay buffer might also be used
for audio (especially for simulating a high delay for debugging).
PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
For clarity, the fields used only when a delay was set were wrapped in
an anonymous structure.
Now that the delay buffer has been extracted to a separate component,
the delay is necessarily set (it may not be 0), so the fields are always
used.
PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
The components needing delayed frames (sc_screen and sc_v4l2_sink)
managed a sc_video_buffer instance, which itself embedded a
sc_frame_buffer instance (to keep only the most recent frame).
In theory, these components should not be aware of delaying: they should
just receive AVFrames later, and only handle a sc_frame_buffer.
Therefore, refactor sc_delay_buffer as a frame source (it consumes)
frames) and a frame sink (it produces frames, after some delay), and
plug an instance in the pipeline only when a delay is requested.
This also removes the need for a specific sc_video_buffer.
PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
There was a frame sink trait, implemented by components able to receive
AVFrames, but each frame source had to manually send frame to sinks.
In order to mutualise sink management, add a frame sink trait.
There was a packet sink trait, implemented by components able to
receive AVPackets, but each packet source had to manually send packets
to sinks.
In order to mutualise sink management, add a packet source trait.
A video buffer had 2 responsibilities:
- handle the frame delaying mechanism (queuing packets and pushing them
after the expected delay);
- keep only the most recent frame (using a sc_frame_buffer).
In order to be able to reuse only the frame delaying mechanism, extract
it to a separate component, sc_delay_buffer.
The video_buffer thread clears the queue once it is stopped, but new
frames might still be pushed asynchronously.
To avoid the problem, do not push any frame once the video_buffer is
stopped.