The recorder opened the target file from the packet sink open()
callback, called by the demuxer. Only then the recorder thread was
started.
One golden rule for the recorder is to never block the demuxer for I/O,
because it would impact mirroring. This rule is respected on recording
packets, but not for the initial recorder opening.
Therefore, start the recorder thread from sc_recorder_init(), open the
file immediately from the recorder thread, then make it wait for the
stream to start (on packet sink open()).
Now that the recorder can report errors directly (rather than making the
demuxer call fail), it is possible to report file opening error even
before the packet sink is open.
The recorder has two initialization phases: one to initialize the
concrete recorder object, and one to open its packet_sink trait.
Initialize mutex and condvar as part of the object initialization.
If there were several packet_sink traits (spoiler: one for video, one
for audio), then the mutex and condvar would still be initialized only
once.
Stop scrcpy on recorder errors.
It was previously indirectly stopped by the demuxer, which failed to
push packets to a recorder in error. Report it directly instead:
- it avoids to wait for the next demuxer call;
- it will allow to open the target file from a separate thread and stop
immediately on any I/O error.
User-friendly error messages are printed on specific configuration
exceptions. In that case, do not print the stacktrace.
Also handle the user-friendly error message directly where the error
occurs, and print multiline messages in a single log call, to avoid
confusing interleaving.
On the scrcpy-deps repo, I built FFmpeg 5.1.2 binaries for Windows with
only the features used by scrcpy.
For comparison, here are the sizes of the dll for FFmpeg 5.1.2:
- before: 89M
- after: 4.7M
It also allows to upgrade the old FFmpeg version (4.3.1) used for win32.
Refs <https://github.com/rom1v/scrcpy-deps>
Refs <https://github.com/Genymobile/scrcpy/issues/1753>
As reported by gradle:
> Setting the namespace via a source AndroidManifest.xml's package
> attribute is deprecated.
>
> Please instead set the namespace (or testNamespace) in the module's
> build.gradle file, as described here:
> https://developer.android.com/studio/build/configure-app-module#set-namespace
Running scrcpy --tcpip on a device already connected via TCP/IP did not
initialize server->serial.
As a consequence, in debug mode, an assertion failed:
scrcpy: ../app/src/server.c:770: run_server: Assertion
`server->serial' failed.
In release mode, scrcpy failed with this error:
adb: -s requires an argument
Scrcpy does not use FFmpeg network features. Initialize network locally
instead (useful only for Windows).
The include block has been moved to fix the following warning:
Please include winsock2.h before windows.h
DesktopConnection implements Closeable, so it is implicitly closed after
its try-with-resources block. Closing the DesktopConnection shutdowns
the sockets, so it is necessary in particular to wake up blocking read()
calls from the controller.
But the controller thread was joined before the DesktopConnection was
closed, causing a deadlock. To fix the problem, join the controller
thread only after the DesktopConnection is closed.
Refs 400a1c69b1
When a call to a packet or frame sink fails, do not log the error on the
caller side: either the "failure" is expected (explicitly stopped) or it
must be logged by the packet or frame sink implementation.
On close, the client closes the socket. This wakes up socket blocking
calls on the server-side, by throwing an exception. Since this exception
is expected, it was not logged.
However, other IOExceptions might occur, which must not be ignored. For
that purpose, log only IOException when they are not caused by an EPIPE
error.