Commit graph

393 commits

Author SHA1 Message Date
Simon Chan
cab354102d Create AudioRecord by reflection as a fallback
Some devices (Vivo phones) fail to create an AudioRecord from an
AudioRecord.Builder (which throws a NullPointerException).

In that case, create an AudioRecord instance directly by reflection.

The AOSP version of AudioRecord constructor code can be found at:
 - Android 11 (R):
   <https://cs.android.com/android/platform/superproject/+/android-11.0.0_r1:frameworks/base/media/java/android/media/AudioRecord.java;l=335;drc=64ed2ec38a511bbbd048985fe413268335e072f8>
 - Android 12 (S):
   <https://cs.android.com/android/platform/superproject/+/android-12.0.0_r1:frameworks/base/media/java/android/media/AudioRecord.java;l=388;drc=2eebf929650e0d320a21f0d13677a27d7ab278e9>
 - Android 13 (T, functionally identical to Android 12):
   <https://cs.android.com/android/platform/superproject/+/android-13.0.0_r1:frameworks/base/media/java/android/media/AudioRecord.java;l=382;drc=ed242da52f975a1dd18671afb346b18853d729f2>
 - Android 14 (U): Not released, but expected to change

PR #3862 <https://github.com/Genymobile/scrcpy/pull/3862>
Fixes #3805 <https://github.com/Genymobile/scrcpy/issues/3805>

Signed-off-by: Romain Vimont <rom@rom1v.com>
2023-05-26 18:56:43 +02:00
Romain Vimont
597d2ccc01 Rename FORMAT to ENCODING
The AudioFormat contains several properties. This specific value is
named "encoding".
2023-05-24 22:13:09 +02:00
Romain Vimont
38900d7730 Extract audio source to a static constant
For consistency with the other parameters.
2023-05-24 22:13:09 +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
feab87053a Convert screen encoder to async processor
Contrary to the other tasks (controller and audio capture/encoding), the
screen encoder was executed synchronously. As a consequence,
scrcpy-server could not terminate until the screen encoder returned.

Convert it to an async processor. This allows to terminate on controller
error, and this paves the way to disable video mirroring.

PR #3978 <https://github.com/Genymobile/scrcpy/pull/3978>
2023-05-08 16:41:09 +02:00
Romain Vimont
751a3653a0 Add missing @Override annotations
PR #3978 <https://github.com/Genymobile/scrcpy/pull/3978>
2023-05-08 16:41:06 +02:00
Romain Vimont
9c08eb79cb Close connection at the end of finally-block
The async processors use the socket file descriptors from the
connection. Therefore, the connection must not be closed before all
async processor threads are joined.

PR #3978 <https://github.com/Genymobile/scrcpy/pull/3978>
2023-05-08 16:41:04 +02:00
Romain Vimont
9cfea347d0 Remove Options setters
Now that options parsing is performed from the Options class, setters
are not necessary anymore.
2023-04-09 20:02:39 +02:00
Romain Vimont
ce064fb5e0 Move options parsing to Options class 2023-04-09 20:02:39 +02:00
Romain Vimont
afcdfc7fd7 Fix checkstyle violation
Checkstyle reported this error:

    [ant:checkstyle] [ERROR] AudioCapture.java:89:145: '+' should be on
    a new line. [OperatorWrap]
2023-04-09 20:01:58 +02:00
Simon Chan
fdf465851c Add Android version check in raw audio recorder
Do not attempt to capture audio below Android 11, this may cause a
segfault on the device.

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

Signed-off-by: Romain Vimont <rom@rom1v.com>
2023-04-04 18:37:30 +02:00
Romain Vimont
f77e1c474e Fix copy-paste for some devices
On Honor Magic 5 Pro, the method to get the clipboard content has been
modified in the framework.

Adapt the call to make it work also on this device.

Fixes #3885 <https://github.com/Genymobile/scrcpy/issues/3885>
2023-04-01 11:52:37 +02:00
Romain Vimont
2fff9b9edf Adapt FakeContext for Android 14
This fixes audio for Android 14 developer preview 2.

Fixes #3784 <https://github.com/Genymobile/scrcpy/issues/3784>

Suggested-by: Namelesswonder <Namelesswonder@users.noreply.github.com>
2023-03-20 08:40:34 +01:00
Romain Vimont
57f879d68a Adapt clipboard wrappers to Android 14
A new deviceId parameter has been added.

Fixes #3784 <https://github.com/Genymobile/scrcpy/issues/3784>
2023-03-20 08:40:25 +01:00
Romain Vimont
3626d90004 Use separate audio capture code for Android 11
The code to start audio capture is more complicated for Android 11
(launch a fake popup, wait, make several attempts, close the shell
package).

Use a distinct code path specific to Android 11.
2023-03-17 21:30:04 +01:00
Romain Vimont
02f4ff7534 Make 3 attempts to start AudioRecord
On Android 11, a fake popup must be briefly opened to make the system
think that the shell app is in the foreground so that audio may be
recorded.

Making the shell app foreground may take some time depending on the
device, so make 3 attempts, waiting 100ms before each.

Fixes #3796 <https://github.com/Genymobile/scrcpy/issues/3796>
2023-03-17 21:30:04 +01:00
Romain Vimont
a3871130cc List available encoders on failure
When the creation of an encoder fails, log an explicit error message
with the list of available encoders.
2023-03-17 21:29:45 +01:00
Romain Vimont
d7841664f4 Simplify logic in setScreenPowerMode()
Refs <f2dee20a20 (r104417398)>

Suggested-by: brunoais <brunoaiss@gmail.com>
2023-03-15 19:53:58 +01:00
Romain Vimont
6ba99a62ff Split workarounds to fix audio on some devices
There were several workarounds applied in a single method. Some of them
are specific to Meizu phones, but cause issues on other devices.

Split the method to be able to only fill the app context for audio
capture without applying the Meizu workarounds.

Fixes #3801 <https://github.com/Genymobile/scrcpy/issues/3801>
2023-03-14 23:23:57 +01:00
Romain Vimont
337d6c2fd3 Fail on empty AudioRecord read()
If read() returns 0, then there is no data. According to the
documentation, it happens if the buffer is not a direct buffer:
<https://developer.android.com/reference/android/media/AudioRecord#read(java.nio.ByteBuffer,%20int)>

Refs #3812 <https://github.com/Genymobile/scrcpy/issues/3812>
2023-03-14 19:27:11 +01:00
Romain Vimont
2380879376 Remove unused IOException
IOException may not be thrown from this method.
2023-03-12 02:04:58 +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
aa1efbc35c Rename sendCodecId to sendCodecMeta
This will allow the codec header to contain more than the codec id.
2023-03-11 15:57:25 +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
bb56472d4e Print server logs and newline in one call
System.out.println() first prints the message, then the new line.
Between these two calls, the client might print a message, breaking
formatting.

Instead, call System.out.print() with '\n' appended to the message.
2023-03-10 22:22:15 +01:00
Romain Vimont
66b6c06443 Add raw audio recorder
Add an alternative AudioRecorder to stream raw packets without encoding.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
dc228eaad0 Extract async processor interface
On the server side, several components are started, stopped and joined.
Extract an interface to handle them generically.

This will help to support both encoded and raw audio stream, because
they will be two different concrete components, but implementing the
same interface.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
65cc9d765d Extract audio capture
The audio capture was implemented in AudioEncoder.

In order to reuse it without encoding, extract it to a separate class.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Simon Chan
de40cac6ad Add workaround to capture audio on Android 11
On Android 11, it is possible to start the capture only when the running
app is in foreground. But scrcpy is not an app, it's a Java application
started from shell.

As a workaround, start an existing Android shell existing activity just
to start the capture, then close it immediately.

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
a205ff6c8b Log display sizes in display list
This is more convenient than just the display id alone.
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
2596ca02f0 Move log message helpers to LogUtils
This class will also contain other log helpers.
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
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
6f332a2bc7 Extract unknown encoder error message
This will allow to reuse the same code for audio encoder selection.

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
58cf8e5401 Extract application of codec options
This will allow to reuse the same code for audio codec options.

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
8e640dc90f Disable MethodLength checkstyle on createOptions()
This method will grow as needed to initialize options.

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
80c0780b77 Disable audio before Android 11
The permission "android.permission.RECORD_AUDIO" has been added for
shell in Android 11.

Moreover, on lower versions, it may make the server segfault on the
device (happened on a Nexus 5 with Android 6.0.1).

Refs <4feeee8891%5E%21/>
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
15556d1f3b Extract OPUS extradata
For OPUS codec, FFmpeg expects the raw extradata, but MediaCodec wraps
it in some structure.

Fix the config packet to send only the raw extradata.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00
Romain Vimont
7cf5cf5875 Use a streamer to send the audio stream
Send each encoded audio packet using a streamer.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
2023-03-10 22:22:15 +01:00