Commit Graph

1372 Commits

Author SHA1 Message Date
Romain Vimont
be86e14e05 Factorize record format parsing
Convert either the filename extension or the explicit record format
to a sc_record_format using the same function.

PR #3978 <https://github.com/Genymobile/scrcpy/pull/3978>
2023-05-08 17:11:34 +02:00
Romain Vimont
8c650e53cd Add --no-video
Similar to --no-audio, add --no-video to play audio only.

Fixes #3842 <https://github.com/Genymobile/scrcpy/issues/3842>
PR #3978 <https://github.com/Genymobile/scrcpy/pull/3978>
2023-05-08 17:11:34 +02:00
Romain Vimont
e89e772c7c Remove unnecessary 'else'
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>
2023-05-08 16:41:12 +02:00
Romain Vimont
92483fe11b Disable controls on --no-mirror
If mirroring is disabled, control must also be disabled.

PR #3978 <https://github.com/Genymobile/scrcpy/pull/3978>
2023-05-08 16:41:01 +02:00
Romain Vimont
6928acdeac Rename --no-display to --no-mirror
The option impacts both video and audio playback, so "no display" is not
an appropriate name.

PR #3978 <https://github.com/Genymobile/scrcpy/pull/3978>
2023-05-08 16:40:58 +02:00
Romain Vimont
0f3af2d20b Fix build for FFmpeg < 3.3
The constant AV_CODEC_ID_AV1 was introduced in FFmpeg 3.3. Add an ifdef
to support older versions.

Fixes #3939 <https://github.com/Genymobile/scrcpy/issues/3939>
2023-04-23 12:26:46 +02:00
Yan
c083a7cc90 Force OpenGL Core Profile context on macOS
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>
2023-04-12 21:26:24 +02:00
Romain Vimont
051b74c883 Extract sc_display from sc_screen
Move the display code to a separate component.
2023-04-06 19:48:26 +02:00
Romain Vimont
2e532afd2b Pass const pointers to events
SDL_Events are only read.
2023-04-06 19:48:01 +02:00
Romain Vimont
669e9a8d1e Fix "ip route" parsing
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'.
2023-04-02 19:30:23 +02:00
Romain Vimont
2f9396e24a Simplify clock estimation
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.
2023-03-30 20:58:33 +02:00
Romain Vimont
478aece68f Replace "bit-rate" with "bit rate" 2023-03-20 08:35:13 +01:00
Romain Vimont
39544f34b4 Add --audio-output-buffer
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>
2023-03-14 23:54:07 +01:00
Romain Vimont
cbca79b95b Fix v4l2 sink
The codec id to write as codec parameters is the one from the v4l2
encoder, not from the decoder.

Regression introduced by be985b8242.

Fixes #3795 <https://github.com/Genymobile/scrcpy/issues/3795>
2023-03-12 12:45:49 +01:00
Romain Vimont
02586cf21f Fix build issue on FFmpeg < 5.1
An include was missing.

Fixes #3783 <https://github.com/Genymobile/scrcpy/issues/3783>
2023-03-12 08:54:42 +01:00
Romain Vimont
80a6fa7a01 Fix comparison warning
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) {
                    ~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~
2023-03-12 08:37:08 +01:00
Ruoyu Zhong
6b769675fa Fix an "expected expression" error
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>
2023-03-12 08:26:17 +01:00
Romain Vimont
affda26bfa Document audio player
Add some high-level documentation on the audio player implementation.
2023-03-12 02:04:58 +01:00
Romain Vimont
0bf866fa8d Apply new compensation only if it changed
If the compensation is the same (typically when it is 0), do not reapply
it.
2023-03-12 02:04:58 +01:00
Romain Vimont
73727e7fdf Disable clock drift compensation for tiny values
For less than 1ms, the estimated drift is just noise.
2023-03-12 02:04:58 +01:00
Romain Vimont
c22c87eded Fail on deprecated options
Suggest the video and audio specific options instead.
2023-03-12 02:04:58 +01:00
Romain Vimont
426dfbf21d Remove dead code about the deprecated -F option
The -F option was already removed.
2023-03-12 02:04:58 +01:00
Romain Vimont
5512777404 Remove deprecated option --render-expired-frames
This option did nothing since it was deprecated. Totally remove it.
2023-03-12 02:04:58 +01:00
Romain Vimont
eca8766545 Compute buffering and compensation without lock
Once underflow has been read with a lock, the buffering and compensation
may be performed without shared variables.
2023-03-12 02:04:58 +01:00
Romain Vimont
0b8a5ca923 Do not read avg_buffering from the player thread
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).
2023-03-12 02:04:58 +01:00
Romain Vimont
e06acc1ba2 Simplify bytebuf naming
Rename read_available to can_read and write_available to can_write.
This is more readable.
2023-03-12 02:04:57 +01:00
Romain Vimont
14f9d82fda Add audio sample ring-buffer
Add a thin wrapper around bytebuf to handle samples instead of bytes.
This simplifies the audio player, which mostly handles samples.
2023-03-12 02:04:07 +01:00
Romain Vimont
bb509d9317 Define the audio output buffer in milliseconds
In theory, this buffer must be dimensioned for a target duration, so its
size in bytes should depend on the sample rate.
2023-03-11 15:57:25 +01:00
Romain Vimont
238ab872ba Pass video size as codec metadata
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.
2023-03-11 15:57:25 +01:00
Romain Vimont
3a72f3fb4d Report errors on screen event error
Make scrcpy fail if an important screen event (like frame update) fails.
2023-03-11 15:57:25 +01:00
Romain Vimont
be985b8242 Copy codec parameters from context
Now that the recorder have access to the codec context, it may
automatically initialize the stream codec parameters.

The V4L2 sink could do the same.
2023-03-11 15:57:25 +01:00
Romain Vimont
a9f6001f51 Simplify recorder
After the refactor performed by the previous commit, the functions to
wait the video stream and the audio stream could be inlined.
2023-03-11 15:57:25 +01:00
Romain Vimont
5052e15f7f Create recorder streams from packet sinks ops
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).
2023-03-11 15:57:25 +01:00
Romain Vimont
4bdf632dfa Pass AVCodecContext to packet sinks
Create the codec context from the demuxer, so that it can fill context
data for the decoder and recorder.
2023-03-11 15:57:25 +01:00
Romain Vimont
4db50ddbb7 Enable log signaling buffering threshold exceeded
It is as important as underflow logs.
2023-03-11 15:55:44 +01:00
Romain Vimont
46f6918179 Stop and join sc_file_pusher only if initialized
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.
2023-03-10 22:45:48 +01:00
chengjian.scj
d93582724d Initialize interrupted field explicitly
The field sc_fps_counter.interrupted was never initialized explicitly.

Signed-off-by: Romain Vimont <rom@rom1v.com>
2023-03-10 22:33:52 +01:00
Romain Vimont
408f458636 Decrease recorder thread priority
Recording is background task, writing the packets to a file is not
urgent.
2023-03-10 22:22:16 +01:00
Romain Vimont
aa450ffc3f Increase audio thread priority
The audio demuxer thread is the one filling the audio buffer read by the
SDL audio thread. It is time critical to avoid buffer underflow.
2023-03-10 22:22:16 +01:00
Romain Vimont
5ee59e0f13 Add thread priority API
Expose an API to change the priority of the current thread.
2023-03-10 22:22:16 +01:00
Romain Vimont
4a25f3e53b Print info logs to stdout
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
2023-03-10 22:22:15 +01:00
Romain Vimont
7da45c246e Warn on ignored audio options
For raw audio codec, some audio options are ignored.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
d2952c7e93 Add --audio-codec=raw option
Add support for raw (PCM S16 LE) audio codec (a raw decoder is included
in FFmpeg).

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
02dd1be4a1 Stop on decoder frame push error
On push, frame sinks report downstream errors to stop upstream
components. Do not ignore the error.
2023-03-10 22:22:15 +01:00
Romain Vimont
df55bc2683 Add --audio-buffer
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>
2023-03-10 22:22:15 +01:00
Romain Vimont
d66b0b3dcc Add compat support for FFmpeg < 5.1
The new chlayout API has been introduced in FFmpeg 5.1. Use the old
channel_layout API on older versions.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
fbe0f951e1 Add audio player
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>
2023-03-10 22:22:15 +01:00
Romain Vimont
e1333f6f3b Optionally do not delay the first frame
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>
2023-03-10 22:22:15 +01:00
Romain Vimont
9b3ca208bf Accept clock estimation with a single point
If there is only one point, assume the slope is 1.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
48a537d45c Remove anonymous struct in delay buffer
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>
2023-03-10 22:22:15 +01:00
Romain Vimont
1230149fdd Use delay buffer as a frame source/sink
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>
2023-03-10 22:22:15 +01:00
Romain Vimont
974227a3fc Use frame source trait in decoder 2023-03-10 22:22:15 +01:00
Romain Vimont
6543964f12 Introduce frame source trait
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.
2023-03-10 22:22:15 +01:00
Romain Vimont
f3197e178d Use packet source trait in demuxer 2023-03-10 22:22:15 +01:00
Romain Vimont
c39054a63d Introduce packet source 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.
2023-03-10 22:22:15 +01:00
Romain Vimont
f410f2bdc4 Extract sc_delay_buffer
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.
2023-03-10 22:22:15 +01:00
Romain Vimont
6379c08012 Fix buffering pts conversion
The mistake had no effect, because tick is also internally expressed in
microseconds.
2023-03-10 22:22:15 +01:00
Romain Vimont
4540f1d69e Report video buffer downstream errors
Make the video buffer stop if its consumer could not receive a frame.
2023-03-10 22:22:15 +01:00
Romain Vimont
ad94ccca0b Stop the video buffer on error
If an error occurs from the video buffer thread (typically an
out-of-memory error), then stop.
2023-03-10 22:22:15 +01:00
Romain Vimont
a3703340fc Fix possible race condition on video_buffer end
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.
2023-03-10 22:22:15 +01:00
Romain Vimont
6f38c6311b Remove sc_queue
All uses have been replaced by VecDeque.
2023-03-10 22:22:15 +01:00
Romain Vimont
338310677e Remove cbuf
All uses have been replaced by VecDeque.
2023-03-10 22:22:15 +01:00
Romain Vimont
f978e4d6de Use VecDeque in aoa_hid
Replace cbuf by VecDeque in aoa_hid
2023-03-10 22:22:15 +01:00
Romain Vimont
a0a65b3c4d Use VecDeque in file_pusher
Replace cbuf by VecDeque in file_pusher.

As a side-effect, the new implementation does not limit the queue to an
arbitrary value.
2023-03-10 22:22:15 +01:00
Romain Vimont
4d989de9ae Use VecDeque in controller
Replace cbuf by VecDeque in controller.
2023-03-10 22:22:15 +01:00
Romain Vimont
f25a67f342 Use VecDeque in video_buffer
The packets queued for buffering were wrapped in a dynamically allocated
structure with a "next" field.

To avoid this additional layer of allocation and indirection, use a
VecDeque.
2023-03-10 22:22:15 +01:00
Romain Vimont
efc15744da Use VecDeque in recorder
The packets queued for recording were wrapped in a dynamically allocated
structure with a "next" field.

To avoid this additional layer of allocation and indirection, use a
VecDeque.
2023-03-10 22:22:15 +01:00
Romain Vimont
33df484912 Introduce VecDeque
Introduce a double-ended queue implemented with a growable ring buffer.

Inspired from the Rust VecDeque type:
<https://doc.rust-lang.org/std/collections/struct.VecDeque.html>
2023-03-10 22:22:15 +01:00
Romain Vimont
457385d5f4 Add sc_allocarray() util
Add a function to allocate an array, which fails safely in the case
where the multiplication would overflow.
2023-03-10 22:22:15 +01:00
Romain Vimont
c735b8c127 Use reallocarray() in sc_vector
This fails safely in case of overflow.
2023-03-10 22:22:15 +01:00
Romain Vimont
6dceb32817 Add compat for reallocarray()
This function fails safely in the case where the multiplication would
overflow.
2023-03-10 22:22:15 +01:00
Romain Vimont
6e05d7047a Call avcodec_receive_frame() in a loop
Since in scrcpy a video packet passed to avcodec_send_packet() is always
a complete video frame, it is sufficient to call avcodec_receive_frame()
exactly once.

In practice, it also works for audio packets: the decoder produces
exactly 1 frame for 1 input packet.

In theory, it is an implementation detail though, so
avcodec_receive_frame() should be called in a loop.
2023-03-10 22:22:15 +01:00
Romain Vimont
c1528cdca9 Add --require-audio
By default, scrcpy mirrors only the video when audio capture fails on
the device. Add an option to force scrcpy to fail if audio is enabled
but does not work.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
b60a8aa657 Add two-step write feature to bytebuf
If there is exactly one producer, then it can assume that the remaining
space in the buffer will only increase until it writes something.

This assumption may allow the producer to write to the buffer (up to a
known safe size) without any synchronization mechanism, thus allowing
to read and write different parts of the buffer in parallel.

The producer can then commit the write with a lock held, and update its
knowledge of the safe empty remaining space.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
20d41fdd7e Introduce bytebuf util
Add a ring-buffer for bytes. It will be useful for audio buffering.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
619730edaf Pass AVCodecContext to frame sinks
Frame consumers may need details about the frame format.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
e22660d698 Add an audio decoder
PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
05f0e35d2a Give a name to decoder instances
This will be useful in logs.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
99837fa600 Rename decoder to video_decoder
This prepares the introduction of audio_decoder.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
b65301f672 Add --list-displays
Add an option to list the device displays properly.
2023-03-10 22:22:15 +01:00
Romain Vimont
50d56a9a2b Quit on audio configuration failure
When audio capture fails on the device, scrcpy continues mirroring the
video stream. This allows to enable audio by default only when
supported.

However, if an audio configuration occurs (for example the user
explicitly selected an unknown audio encoder), this must be treated as
an error and scrcpy must exit.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
9196dc1563 Add --list-encoders
Add an option to list the device encoders properly.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
b7e5284adf Move await_for_server() logs
Print the logs on the caller side. This will allow to call the function
in another context without printing the logs.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
f9960e959f Add --audio-encoder
Similar to --video-encoder, but for audio.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
b03c864c70 Add --audio-codec-options
Similar to --video-codec-options, but for audio.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
4601735e51 Add support for AAC audio codec
Add option --audio-codec=aac.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
839b842aa7 Add --audio-codec
Introduce the selection mechanism. Alternative codecs will be added
later.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
0870b8c8be Add --audio-bit-rate
Add an option to configure the audio bit-rate.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
e694619d53 Rename --encoder to --video-encoder
This prepares the introduction of --audio-encoder.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
31555fa530 Rename --codec-options to --video-codec-options
This prepares the introduction of --audio-codec-options.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
9087e85c3f Rename --bit-rate to --video-bit-rate
This prepares the introduction of --audio-bit-rate.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
cee40ca047 Rename --codec to --video-codec
This prepares the introduction of --audio-codec.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
a1802dab76 Remove default bit-rate on client side
If no bit-rate is passed, let the server use the default value (8Mbps).

This avoids to define a default value on both sides, and to pass the
default bit-rate as an argument when starting the server.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
17d5301c0f Record at least video packets on stop
If the recorder is stopped while it has not received any audio packet
yet, make sure the video stream is correctly recorded.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
13a3395a33 Disable audio on initialization error
By default, audio is enabled (--no-audio must be explicitly passed to
disable it).

However, some devices may not support audio capture (typically devices
below Android 11, or Android 11 when the shell application is not
foreground on start).

In that case, make the server notify the client to dynamically disable
audio forwarding so that it does not wait indefinitely for an audio
stream.

Also disable audio on unknown codec or missing decoder on the
client-side, for the same reasons.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
7de0622214 Add audio recording support
Make the recorder accept two input sources (video and audio), and mux
them into a single file.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
3d29f6ef06 Rename video-specific variables in recorder
This paves the way to add audio-specific variables.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
609b098a97 Do not merge config audio packets
For video streams (at least H.264 and H.265), the config packet
containing SPS/PPS must be prepended to the next packet (the following
keyframe).

For audio streams (at least OPUS), they must not be merged.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
de430bc4aa Add an audio demuxer
Add a demuxer which will read the stream from the audio socket.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
f60b5767f4 Force --no-audio if no display and no recording
The client does not use the audio stream if there is no display and no
recording (i.e. only V4L2), so disable audio so that the device does not
attempt to capture it.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
d499f890e7 Give a name to demuxer instances
This will be useful in logs.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
e9876788c9 Rename demuxer to video_demuxer
There will be another demuxer instance for audio.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Simon Chan
e841241a8e Add a new socket for audio stream
When audio is enabled, open a new socket to send the audio stream from
the device to the client.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>

Co-authored-by: Romain Vimont <rom@rom1v.com>
Signed-off-by: Romain Vimont <rom@rom1v.com>
2023-03-10 22:22:15 +01:00
Simon Chan
3cf03e4a4b Add --no-audio option
Audio will be enabled by default (when supported). Add an option to
disable it.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>

Co-authored-by: Romain Vimont <rom@rom1v.com>
Signed-off-by: Romain Vimont <rom@rom1v.com>
2023-03-10 22:22:15 +01:00
Romain Vimont
ef6a3b97a7 Reorder initialization
Initialize components in the pipeline order: demuxer first, decoder and
recorder second.
2023-03-10 22:22:15 +01:00
Romain Vimont
f9efe48aac Refactor recorder logic
Process the initial config packet (necessary to write the header)
separately.
2023-03-10 22:22:15 +01:00
Romain Vimont
4b246cd963 Move last packet recording
Write the last packet at the end.
2023-03-10 22:22:15 +01:00
Romain Vimont
3c407773e9 Add start() function for recorder
For consistency with the other components, do not start the internal
thread from an init() function.
2023-03-10 22:22:15 +01:00
Romain Vimont
a039124d5d Open recording file from the recorder thread
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.
2023-03-10 22:22:15 +01:00
Romain Vimont
6b5dfef923 Inline packet_sink impl in recorder
Remove useless wrappers.
2023-03-10 22:22:15 +01:00
Romain Vimont
fb29135591 Initialize recorder fields from init()
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.
2023-03-10 22:22:15 +01:00
Romain Vimont
b1b33e3eaf Report recorder errors
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.
2023-03-10 22:22:15 +01:00
Romain Vimont
db5751a76a Move previous packet to a local variable
It is only used from run_recorder().
2023-03-10 22:22:15 +01:00
Romain Vimont
b6744e7887 Move pts_origin to a local variable
It is only used from run_recorder().
2023-03-10 22:22:15 +01:00
Romain Vimont
181fb555bb Change PTS origin type from uint64_t to int64_t
It is initialized from AVPacket.pts, which is an int64_t.
2023-03-10 22:22:15 +01:00
Romain Vimont
fa99763668 Fix --encoder documentation
Mention that it depends on the codec provided by --codec (which is not
necessarily H264 anymore).
2023-03-10 22:22:15 +01:00
Romain Vimont
c78254fcd1 Split server stop() and join()
For consistency with the other components, call stop() and join()
separately.

This allows to stop all components, then join them all.
2023-03-10 22:22:15 +01:00
Romain Vimont
e30e692b36 Print FFmpeg logs
FFmpeg logs are redirected to a specific SDL log category.

Initialize the log level for this category to print them as expected.
2023-03-10 22:22:15 +01:00
Romain Vimont
10e8295aea Move FFmpeg callback initialization
Configure FFmpeg log redirection on start from a log helper.
2023-03-10 22:22:15 +01:00
Romain Vimont
b5d41ad4f6 Fix useless garbage initialization
The variable `p` was initialized with a garbage value (a `const char **`
casted to `char *`). Fortunately, it was never read.

Refs <https://github.com/Genymobile/scrcpy/issues/3765>
2023-03-03 11:12:31 +01:00
Romain Vimont
389dd77b50 Fix MIN/MAX macros
Expressions like "x < MAX(y, z)" were broken.
2023-03-03 01:18:10 +01:00
Romain Vimont
3c3c07db05 Initialize server->serial in all cases
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
2023-02-28 12:34:34 +01:00
Romain Vimont
6b422e21bf Fix error message on icon loading failure 2023-02-27 20:51:54 +01:00
Romain Vimont
8e8b039a63 Do not use avformat network
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
2023-02-27 20:51:54 +01:00
Romain Vimont
0702be86d8 Accept Windows Sockets from version 1.1
Version 2.2 is probably not necessary (1.1 is the version required by
FFmpeg when network is enabled).

Refs <891ed24f77/libavformat/network.c (L63)>
Refs <https://learn.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-wsastartup>
2023-02-27 20:51:54 +01:00
Romain Vimont
0cea7fb24c Fix WSAStartup() error check on Windows 2023-02-27 20:51:35 +01:00
Romain Vimont
5d6bcc5966 Use enum for long options constants
This avoids to manually assign values.
2023-02-21 19:47:27 +01:00
Romain Vimont
5973d4cdd7 Initialize mouse_input_mode explicitly
The explicit initialization was missing. It had no consequences because
SC_MOUSE_INPUT_MODE_INJECT == 0.

Fixes #3749 <https://github.com/Genymobile/scrcpy/issues/3749>
2023-02-21 12:11:39 +01:00
Romain Vimont
0a151b96fe Accept muxing AV1 into MP4 container
MP4 supports AV1.

Refs d2dce51038
2023-02-20 20:49:56 +01:00
Romain Vimont
e02f30f895 Remove unnecessary error logs
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.
2023-02-19 02:10:14 +01:00
Romain Vimont
25e2eb7d7c Document default video codec
Mention the default option value, like for other commands.
2023-02-18 19:10:25 +01:00
Romain Vimont
280a9afda8 Fix command-line help typo 2023-02-18 18:11:34 +01:00
Romain Vimont
e91618586c Prefix receiver by sc_
Like all other components in scrcpy.
2023-02-18 09:37:31 +01:00
Romain Vimont
680ddf64be Fix demuxer error message
Now that there are several possible codecs, do not hardcode H.264 in the
error message.

Refs 3e517cd40e
2023-02-18 09:31:06 +01:00
Romain Vimont
439a1fd4ed Rename 'uid' to 'scid'
A random identifier is generated to differentiate multiple running
scrcpy instances. Rename it from 'uid' to 'scid' (scrcpy id) not to
confuse it with Linux UID.

Fixes #3729 <https://github.com/Genymobile/scrcpy/issues/3729>
Refs 4315be1648
2023-02-11 09:58:40 +01:00
Romain Vimont
49eb326ce9 Extract packet merging
Config packets must be prepended to the next media packet. Extract the
logic to a new sc_packet_merger helper to simplify the demuxer code.
2023-02-11 09:44:33 +01:00
Romain Vimont
f03f32267e Remove unused parser
Since 1c02b58412, the parser is not used
anymore.
2023-02-10 23:18:11 +01:00
Romain Vimont
730eb1086a Properly report demuxer errors
All demuxer errors were reported as "device disconnected", even if the
failure was not related to device socket read.
2023-02-10 18:55:43 +01:00
Romain Vimont
4f9e9c6619 Prefix UI events constants by SC_ 2023-02-10 18:55:43 +01:00
Romain Vimont
953edfd1df Split codec_id reading
Receive codec id and convert it to AVCodecID separately.

This will allow the caller to distinguish between EOS and unknown codec
id.
2023-02-10 18:55:43 +01:00
Romain Vimont
230b8274b9 Fix error return value
The function returns an enum AVCodecID, not a bool.
2023-02-10 18:55:43 +01:00
Romain Vimont
40866ddc10 Fix demuxer error message
The message applies to all packets, not only config packets.
2023-02-10 18:55:39 +01:00
Romain Vimont
bd56c0abf7 Remove unused codec context
The demuxer does not need any codec context.
2023-02-10 18:46:01 +01:00
Romain Vimont
d2dce51038 Add support for AV1
Add option --codec=av1.

PR #3713 <https://github.com/Genymobile/scrcpy/pull/3713>
2023-02-06 11:00:49 +01:00
Romain Vimont
4342c5637d Add support for H265
Add option --codec=h265.

PR #3713 <https://github.com/Genymobile/scrcpy/pull/3713>
Fixes #3092 <https://github.com/Genymobile/scrcpy/issues/3092>
2023-02-06 11:00:49 +01:00
Romain Vimont
3e517cd40e Add option to select video codec
Introduce the selection mechanism. Alternative codecs will be added in
further commits.

PR #3713 <https://github.com/Genymobile/scrcpy/pull/3713>
2023-02-06 10:58:45 +01:00
Romain Vimont
f70f6cdd3e Simplify server info initialization
Use sc_read16be() to read 16-bit integer fields.
2023-02-03 12:31:28 +01:00
Romain Vimont
1c82c3923d Compute relative PTS on the client-side
The PTS received from MediaCodec are expressed relative to an arbitrary
clock origin. We consider the PTS of the first frame to be 0, and the
PTS of every other frame is relative to this first PTS (note that the
PTS is only used for recording, it is ignored for mirroring).

For simplicity, this relative PTS was computed on the server-side.

To prepare support for multiple stream (video and audio), send the
packet with its original PTS, and handle the PTS offset on the
client-side (by the recorder).

Since we can't know in advance which stream will produce the first
packet with the lowest PTS (a packet received later on one stream may
have a PTS lower than a packet received earlier on another stream),
computing the PTS on the server-side would require unnecessary waiting.
2023-02-03 12:31:28 +01:00
Simon Chan
0afef0c634 Forward action button to device
On click event, only the whole buttons state was passed to the device.
In addition, on ACTION_DOWN and ACTION_UP, pass the button associated to
the action.

Refs #3635 <https://github.com/Genymobile/scrcpy/issues/3635>

Co-authored-by: Romain Vimont <rom@rom1v.com>
Signed-off-by: Romain Vimont <rom@rom1v.com>
2023-01-30 20:57:54 +01:00
Romain Vimont
4315be1648 Use random name for device socket
For the initial connection between the device and the computer, an adb
tunnel is established (with "adb reverse" or "adb forward").

The device-side of the tunnel is a local socket having the hard-coded
name "scrcpy". This may cause issues when several scrcpy instances are
started in a few seconds for the same device, since they will try to
bind the same name.

To avoid conflicts, make the client generate a random UID, and append
this UID to the local socket name ("scrcpy_01234567").
2023-01-27 21:51:59 +01:00