Commit graph

789 commits

Author SHA1 Message Date
Romain Vimont
6034110140 Fix build_without_gradle script
Changes missing from b38ba2f687.
2026-04-16 21:45:28 +02:00
Romain Vimont
266e2eaf14 Align the virtual display size
When the virtual display size is not aligned, a resize filter may be
inserted to compensate for small dimension mismatches, increasing
processing and resulting in a blurry image.

PR #6771 <https://github.com/Genymobile/scrcpy/pull/6771>
2026-04-16 19:40:21 +02:00
Romain Vimont
965d0e6856 Fix comment wording
For clarity and grammar.
2026-04-16 19:15:22 +02:00
Romain Vimont
03878083fb Reset capture on rotation (fix square displays)
`DisplayMonitor` previously only triggered a capture reset when the
display size changed. In most cases, rotation also changes dimensions,
so the behavior was correct… except for square displays where width and
height remain unchanged.

However, rotation still requires a capture reset even when dimensions do
not change, to ensure the orientation filter is applied so virtual
displays are rendered correctly.

To reproduce the issue:

    scrcpy --new-display=600x600 --start-app=com.android.settings

Then press Alt+r to rotate the Settings app.

PR #6770 <https://github.com/Genymobile/scrcpy/pull/6770>
2026-04-16 19:06:27 +02:00
Romain Vimont
b38ba2f687 Reorganize server packages
Move existing classes into newly created `display` and `model` packages.
2026-04-15 10:01:27 +02:00
Romain Vimont
69578f1200 Remove overwritten assignment
The `videoSize` field is always reassigned to `filter.getOutputSize()`.
2026-04-14 22:56:28 +02:00
Romain Vimont
fe9450afcc Remove unnecessary synchronization
The `videoSize` field is never written while holding the mutex, and is
only accessed from the same thread.
2026-04-14 22:56:28 +02:00
Romain Vimont
66005e8889 Respect encoder minimum size constraint
Encoders require a minimum video size.

Use video capabilities to constrain a given size by the declared minimum
size of the selected encoder.

Contrary to the maximum size constraints (but like the alignment
constraint), use the same value in both directions for simplicity and so
that rotating the device does not change the shape of the video.

PR #6766 <https://github.com/Genymobile/scrcpy/pull/6766>
2026-04-14 22:52:10 +02:00
Romain Vimont
33b1bc6209 Respect encoder maximum size constraint
Encoders cannot encode at any resolution.

Use video capabilities to constrain a given size by the limits of the
selected encoder.

These video capabilities describe the range of supported widths and
heights, as well as the supported heights for a given width (and
vice-versa). Use this information to compute the maximum portrait size
and the maximum landscape size.

PR #6766 <https://github.com/Genymobile/scrcpy/pull/6766>
2026-04-14 22:51:48 +02:00
Romain Vimont
809718ed25 Extract method to create VideoConstraints
As more constraints are added, this avoids polluting the
`streamCapture()` method.

PR #6766 <https://github.com/Genymobile/scrcpy/pull/6766>
2026-04-14 22:51:36 +02:00
Romain Vimont
a1d1d95404 Move max size into VideoConstraints
Make the requested max size part of `VideoConstraints`.

PR #6766 <https://github.com/Genymobile/scrcpy/pull/6766>
2026-04-14 22:51:02 +02:00
Romain Vimont
5b6e2cfdd4 Introduce VideoConstraints
Group video constraints into a dedicated class. For now it only contains
the `alignment` field; additional constraints will be added in further
commits.

PR #6766 <https://github.com/Genymobile/scrcpy/pull/6766>
2026-04-14 22:50:36 +02:00
Romain Vimont
3c3cfe8cc6 Constraint size and alignment simultaneously
Previously, the size was scaled to fit the requested maximum size and
then aligned. If the maximum size was not a multiple of the alignment,
the resulting size was suboptimal as it preserved the aspect ratio less
accurately.

This also prepares for additional video constraints.

PR #6766 <https://github.com/Genymobile/scrcpy/pull/6766>
2026-04-14 22:50:28 +02:00
Romain Vimont
4f97e2e30b Disable retry capture at lower resolution
A mechanism was introduced to retry capture at a lower resolution to
support devices unable to encode at the device screen resolution.

While useful, this approach is inherently limited and will not be able
to handle the dynamic resizing required for resizable virtual displays.

Disable this mechanism entirely. Further commits will add support for
adjusting the size in advance according to video encoder capabilities.

Refs #2947 <https://github.com/Genymobile/scrcpy/pull/2947>
PR #6766 <https://github.com/Genymobile/scrcpy/pull/6766>
2026-04-14 22:50:28 +02:00
Romain Vimont
3b00032a01 Make field final
The `displayImePolicy` field may be `final`.

PR #6766 <https://github.com/Genymobile/scrcpy/pull/6766>
2026-04-14 22:50:22 +02:00
Romain Vimont
f54cf8b336 Move MediaFormat creation
For code clarity.

PR #6766 <https://github.com/Genymobile/scrcpy/pull/6766>
2026-04-14 22:50:03 +02:00
Romain Vimont
ae13c77c5e Add option to force size alignment
Add --min-size-alignment to force a minimal size alignment.

This is a power-of-2 value (1, 2, 4, 8 or 16) that the video width and
height must be multiples of.

The actual alignment will be the maximum of this value and the video
codec's alignment requirement.

PR #6746 <https://github.com/Genymobile/scrcpy/pull/6746>
2026-04-07 19:47:11 +02:00
Romain Vimont
ae8ecb1d0e Use optimal size alignment
The video was always constrained to use a size that is a multiple of 8.
This was sometimes not necessary (recent codecs only require a video
size that is a multiple of 2 or even 1) and sometimes insufficient (some
codecs require a size that is multiple of 16).

Use the size alignment required by the codec.

Fixes #4949 <https://github.com/Genymobile/scrcpy/issues/4949>
Fixes #6236 <https://github.com/Genymobile/scrcpy/issues/6236>
PR #6746 <https://github.com/Genymobile/scrcpy/pull/6746>
2026-04-07 19:47:00 +02:00
Romain Vimont
df91514112 Fix camera failure handling
The camera capture must be closed on error (isClosed() returns the value
of the disconnected flag).
2026-03-31 20:03:46 +02:00
Romain Vimont
a6c16180ee Fix display size monitor synchronization
Do not unlock the mutex between reading and writing to
sessionDisplaySize.
2026-03-31 20:03:44 +02:00
Romain Vimont
57a40917d4 Remove trailing comma
Fix typo.
2026-03-31 19:54:46 +02:00
Romain Vimont
edc81b4a1c Do not fallback to main display
If the virtual display is not initialized yet, do not send events to the
main display.
2026-03-31 19:54:13 +02:00
Romain Vimont
1c68d79eea Upgrade AGP (9.1.0) and Gradle (9.3.1) 2026-03-24 20:56:19 +01:00
Romain Vimont
89b63f081f Set latency only for API >= 26
Contrary to what the previous commit message says, KEY_LATENCY was
introduced in API 26, not 23.
2026-03-24 20:55:14 +01:00
Romain Vimont
72d1aedcaa Set priority and latency only for API level >= 23
The KEY_PRIORITY and KEY_LATENCY constants were introduced in Android
API level 23.
2026-03-20 17:52:12 +01:00
Romain Vimont
90d11810e3 Set MediaCodec KEY_LATENCY to the minimum value
The encoder must output a frame as soon as one frame is queued.

Refs <https://developer.android.com/reference/android/media/MediaFormat#KEY_LATENCY>
Refs #6238 comment <https://github.com/Genymobile/scrcpy/issues/6238#issuecomment-3828402687>
PR #6670 <https://github.com/Genymobile/scrcpy/pull/6670>
2026-02-21 12:21:54 +01:00
Romain Vimont
1f19ec4aec Set MediaCodec KEY_PRIORITY to real-time (0)
Refs <https://developer.android.com/reference/android/media/MediaFormat#KEY_PRIORITY>
Refs #6238 comment <https://github.com/Genymobile/scrcpy/issues/6238#issuecomment-3828402687>
PR #6670 <https://github.com/Genymobile/scrcpy/pull/6670>
2026-02-21 12:21:44 +01:00
Romain Vimont
23710e04c1 Disable audio stream with fatal error Throwable
Only an AudioCaptureException should disable the audio stream without
making scrcpy exit (it is not a fatal error).

A ConfigurationException or any other Throwable must be considered a
fatal error.

                               BEFORE      AFTER
  AudioCaptureException:    non-fatal  non-fatal
  ConfigurationException:       fatal      fatal
  any other Throwable:      non-fatal      fatal

Refs #6600 comment <https://github.com/Genymobile/scrcpy/issues/6600#issuecomment-3744934826>
2026-02-12 20:20:52 +01:00
Tommie
8ac04d39f4 Add shortcuts to change the camera zoom
MOD+up and MOD+zoom change the camera zoom.

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

Signed-off-by: Romain Vimont <rom@rom1v.com>
2026-01-13 20:40:58 +01:00
Tommie
af355804ef Add option to specify the camera zoom
Add --camera-zoom to specify the camera zoom.

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

Signed-off-by: Romain Vimont <rom@rom1v.com>
2026-01-13 20:37:42 +01:00
Romain Vimont
1018f3e9be Display fps set with '{}'
Replace "fps=[15, 30, 60]" with "fps={15, 30, 60}".

The default toString() implementation for a SortedSet uses '[]', but
it is more correct to use '{}' to denote a set.

PR #6243 <https://github.com/Genymobile/scrcpy/pull/6243>
2026-01-13 20:36:33 +01:00
Romain Vimont
48fcfdd104 Add shortcuts to switch the camera torch
MOD+t turns on the camera torch, MOD+Shift+t turns it off.

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

Co-authored-by: Tommie <teh420@gmail.com>
2026-01-13 20:35:52 +01:00
Tommie
553813e97d Add option to turn on the camera torch
Add --camera-torch to turn on the camera torch when the camera starts.

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

Signed-off-by: Romain Vimont <rom@rom1v.com>
2026-01-13 20:32:06 +01:00
Romain Vimont
968f178205 Simplify camera startup code
Avoid multiple back-and-forths between the caller thread and the camera
thread.

PR #6243 <https://github.com/Genymobile/scrcpy/pull/6243>
2026-01-13 20:28:32 +01:00
Romain Vimont
1b13d0a22d Enable "reset video" shortcut for camera
Make the existing "reset video" feature (MOD+Shift+R) also work for a
camera video source.

PR #6243 <https://github.com/Genymobile/scrcpy/pull/6243>
2026-01-13 20:27:53 +01:00
Romain Vimont
078565d40b Enable controls for camera video source
This will allow the implementation of camera-specific shortcuts.

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

Co-authored-by: Tommie <teh420@gmail.com>
2026-01-13 20:27:33 +01:00
Romain Vimont
cc7c07d4a3 Report control protocol errors
All IOExceptions were ignored to avoid an error on close, but protocol
exceptions must be reported.

PR #6243 <https://github.com/Genymobile/scrcpy/pull/6243>
2026-01-13 20:18:36 +01:00
Romain Vimont
24b46f11a5 Throw error on unexpected control message type
PR #6243 <https://github.com/Genymobile/scrcpy/pull/6243>
2026-01-13 20:15:37 +01:00
Romain Vimont
f8846aa76d Simplify capture invalidation
Remove the unnecessary requestInvalidate() indirection. Use a single
invalidate() method instead.

PR #6243 <https://github.com/Genymobile/scrcpy/pull/6243>
2026-01-13 20:10:30 +01:00
Romain Vimont
78cba1b7c2 Add session metadata for the video stream
Introduce a new packet type, a "session" packet, containing metadata
about the encoding session. It is used only for the video stream and
currently includes the video resolution.

For illustration, here is a sequence of packets on the video stream:

                                        device rotation
                                        v
    CODEC | SESSION | MEDIA | MEDIA | … | SESSION | MEDIA | MEDIA | …
           1920x1080 <-----------------> 1080x1920 <------------------
                      encoding session 1            encoding session 2

This metadata is not strictly necessary, since the video resolution can
be determined after decoding. However, it allows detection of cases
where the encoder does not respect the requested size (and logs a
warning), even without decoding (e.g., when there is no video playback).

Additional metadata could be added later if necessary, for example the
actual device rotation.

Refs #5918 <https://github.com/Genymobile/scrcpy/pull/5918>
Refs #5894 <https://github.com/Genymobile/scrcpy/pull/5894>
PR #6159 <https://github.com/Genymobile/scrcpy/pull/6159>

Co-authored-by: gz0119 <liyong2@4399.com>
2026-01-10 11:53:22 +01:00
Romain Vimont
1015b42e53 Rename "codec meta" to "stream meta"
The stream metadata will contain both:
 - the codec ID at the start of the stream
 - the session metadata (video width and height) at the start of each
   "session" (typically on rotation)

PR #6159 <https://github.com/Genymobile/scrcpy/pull/6159>
2026-01-10 11:53:22 +01:00
Romain Vimont
cda4387058 Add missing break statement
Refs #6439 comment <https://github.com/Genymobile/scrcpy/pull/6439#issuecomment-3705283406>
2026-01-02 14:47:28 +01:00
Romain Vimont
42632d3f53 Drop root privileges on startup
On rooted devices, switch to user 2000 during startup.

Copy-paste does not work as root (user 0), so switching to 2000 fixes
the issue.

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

Suggested-by: Simon Chan <1330321+yume-chan@users.noreply.github.com>
2025-12-30 14:40:53 +01:00
Romain Vimont
06fd3b4786 Bump version to 3.3.4 2025-12-17 19:57:50 +01:00
Romain Vimont
5b51396a8c Fix permission denial error after Android upgrade
Assign the FakeContext instance to ActivityManager.mContext to avoid a
permission error:

    Permission Denial: package=android does not belong to uid=2000

Fixes #6523 <https://github.com/Genymobile/scrcpy/issues/6523>
2025-12-09 20:24:42 +01:00
Romain Vimont
7e66062086 Extract function to execute code on a handler
Extract function to synchronously execute code on a handler, waiting for
the execution to complete.
2025-11-28 22:42:17 +01:00
Romain Vimont
9cfa5b197a Create Application instance via instrumentation
This fixes an issue on certain Meizu devices.

Fixes #6480 <https://github.com/Genymobile/scrcpy/issues/6480>
2025-11-23 15:56:31 +01:00
valord577
7dd9bcaf60 Prevent error log interleaving
Between the calls to CONSOLE_ERR.print() and
printStackTrace(CONSOLE_ERR), logs from other threads may be inserted.

Synchronizing access to CONSOLE_ERR ensures that logs from different
threads do not mix.

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

Signed-off-by: valord577 <valord577@gmail.com>
Signed-off-by: Romain Vimont <rom@rom1v.com>
2025-11-18 11:17:17 +01:00
Romain Vimont
3530851071 Fix uncaught exception handler
The default handler was mistakenly retrieved after our custom handler
was set, causing it to reference itself. As a result, this led to
infinite recursion.

Bug introduced by eee3f24739.
2025-11-04 20:35:39 +01:00
Romain Vimont
d0047b2110 Do not fail when uniqueId field is missing
On some devices, DisplayInfo does not have a "uniqueId" field. This
field is only used for correct UHID behavior on virtual displays, so its
absence should not prevent scrcpy from working.

Refs #6009 <https://github.com/Genymobile/scrcpy/pull/6009>
Fixes #6461 <https://github.com/Genymobile/scrcpy/issues/6461>
2025-11-01 00:34:20 +01:00