Commit graph

3037 commits

Author SHA1 Message Date
Romain Vimont
b505b16392 Document render fit 2026-04-19 14:05:24 +02:00
Romain Vimont
05f2ee4fbd Add --render-fit=stretched
Add an option to fit the window without preserving the aspect ratio.
2026-04-19 14:02:54 +02:00
Romain Vimont
95d6658b4e Document flex display 2026-04-19 14:02:40 +02:00
Romain Vimont
f409eed4ff Add resizable virtual display feature
Introduce `--flex-display` to continuously resize the virtual display
to match the window.
2026-04-19 14:02:40 +02:00
Romain Vimont
c28c35137a Add --render-fit feature
Add an option to configure how the rendering fits the window.

The default, `--render-fit=letterbox`, preserves the aspect ratio
and fits the window as best as possible, adding black bars at
the top/bottom or left/right if needed. This has been the only behavior
scrcpy supported so far.

Another mode, `--render-fit=disabled`, renders the display at the
top-left corner without scaling. This mode will be useful for virtual
display resizing.
2026-04-19 14:02:38 +02:00
Romain Vimont
3b068b669e Signal client resize in session packets
So far, scrcpy always resized the window whenever a frame with a new
size was received. However, with the upcoming "flex display" feature,
the size of the virtual display can change either on its own (e.g.,
due to app rotation) or as a result of a client window resize.

Track the cause of each resize and signal it in the session metadata.

Resize the window only if the change was not triggered by a client
request to prevent resize loops and stuttering.
2026-04-19 12:20:38 +02:00
Romain Vimont
160a378719 Remove frame buffer internal mutex
Let the caller handle locking as needed, allowing them to perform other
actions under the same lock.
2026-04-19 12:20:38 +02:00
Romain Vimont
2151760f28 Ignore expected display properties changes
After initialization or an explicit display resize, a specific display
event is expected and must be ignored to avoid triggering a capture
reset.

A capture reset should occur only when the display size changes
independently, for example on app rotation.
2026-04-19 12:20:38 +02:00
Romain Vimont
3e7da96a57 Extract display properties tracker
`DisplayMonitor` listens for system display events. Move the
event-handling logic into a separate class (`DisplayPropertiesTracker`),
as it will become more complex in the following commit.
2026-04-19 12:20:38 +02:00
Romain Vimont
4f7e3d165e Provide reason for capture reset
Add flags to indicate why a capture was reset.

This paves the way for properly handling virtual display resize
requests.
2026-04-19 12:20:38 +02:00
Romain Vimont
b4ab0f62ab Refactor CaptureReset into CaptureControl
Expose `CaptureControl` directly in `SurfaceCapture` to remove a layer
of indirection (`CaptureListener`).

This will make it easier to expose other methods without boilerplate.
2026-04-19 12:20:38 +02:00
Romain Vimont
fcdd3091ae Expose specific resize_display() control
Store resize display events separately so that only the most recent
pending value is sent.
2026-04-19 12:20:38 +02:00
Romain Vimont
5b8025cb96 Add RESIZE_DISPLAY control message
Add a new control message type to request a resize of the virtual
display.
2026-04-19 12:20:38 +02:00
Romain Vimont
4b2cb2da57 Move control messages logging
Log a control message when they are sent, not when they are pushed to
the message queue.
2026-04-19 12:20:38 +02:00
Romain Vimont
ccfd3269d4 Update protocol documentation
The protocol changed in commit 78cba1b7c2.

Update the documentation accordingly.

Refs #6159 <https://github.com/Genymobile/scrcpy/pull/6159>
PR #6776 <https://github.com/Genymobile/scrcpy/pull/6776>
2026-04-19 12:18:56 +02:00
Romain Vimont
b5b3db5888 Replace v2.0 with 2.0 in doc
Refs #6776 comment <https://github.com/Genymobile/scrcpy/pull/6776#discussion_r3105660913>
2026-04-19 11:24:40 +02:00
Padraic Slattery
3f7ecafc53 Update outdated GitHub Actions versions
PR #6610 <https://github.com/Genymobile/scrcpy/pull/6610>

Signed-off-by: Romain Vimont <rom@rom1v.com>
2026-04-17 22:06:44 +02:00
Romain Vimont
b5cc6f2be5 Set default audio-output-buffer to 10ms
Change the default value of `--audio-output-buffer` from 5ms to 10ms.

In practice, the audio output backends do not support values below 10ms.
When the setting is set to 5ms, several successive calls are made every
10ms or more.

Additionally, a 5ms output buffer can cause audio glitches on some
computers.

Refs SDL/#13319 <https://github.com/libsdl-org/SDL/issues/13319>
Refs SDL/#13397 <https://github.com/libsdl-org/SDL/issues/13397>
Fixes #3793 <https://github.com/Genymobile/scrcpy/issues/3793>
PR #6775 <https://github.com/Genymobile/scrcpy/pull/6775>
2026-04-17 21:34:18 +02:00
Romain Vimont
f4a872bef4 Fix aspect ratio accuracy
The window aspect ratio was previously enforced by calling
`SDL_SetWindowAspectRatio()` before explicitly setting the window size,
using the width/height ratio of the new size.

However, this size may already be a scaled version of the actual content
size, subject to integer rounding. Using this derived size instead of
the actual content size could result in an inaccurate ratio, causing a
mismatch between the content and window aspect ratios, which may result
in a thin row or column of black pixels.

To avoid this issue, always set the aspect ratio based on the content
size.

Refs 1b4fd67286
Refs #6761 <https://github.com/Genymobile/scrcpy/pull/6761>
PR #6774 <https://github.com/Genymobile/scrcpy/pull/6774>
2026-04-17 18:30:25 +02:00
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
fd6536b34a Fix incorrect assertion in recording
It was assumed that the video packet immediately following a config
packet was a non-config packet. This is not necessarily true: for
example, if the capture is reset (due to resizing or rotation) before
the first frame is produced.
2026-04-11 14:54:52 +02:00
Romain Vimont
f669c81b94 Replace assertion with a runtime check
The length is provided by the device, treat invalid values as a runtime
error.
2026-04-11 13:51:25 +02:00
Romain Vimont
ebb47b55c8 Fail on demuxer error
Add missing error handling.
2026-04-11 13:50:54 +02:00
Tech-Tac
65153a09c3 Add option to disable window aspect ratio lock
By default, the window aspect ratio is preserved when resizing.

Add `--no-window-aspect-ratio-lock` to disable this behavior.

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

Signed-off-by: Romain Vimont <rom@rom1v.com>
2026-04-10 19:35:43 +02:00
Tech-Tac
1b4fd67286 Enforce window aspect ratio
Preserve the aspect ratio when resizing the window, so that the window
always matches the device content.

Fixes #2317 <https://github.com/Genymobile/scrcpy/issues/2317>
Fixes #2387 <https://github.com/Genymobile/scrcpy/issues/2387>
Fixes #3460 <https://github.com/Genymobile/scrcpy/issues/3460>
PR #6761 <https://github.com/Genymobile/scrcpy/pull/6761>

Signed-off-by: Romain Vimont <rom@rom1v.com>
2026-04-10 19:34:02 +02:00
Romain Vimont
829da1477d Fix typo in error message 2026-04-10 19:33:00 +02:00
Romain Vimont
a007c038ca Add missing --no-window shell completion 2026-04-10 19:32:05 +02:00
Romain Vimont
064635e1af Remove deprecated options
The next release will be a major version.
2026-04-10 19:29:40 +02:00
Romain Vimont
7bd18fcda8 Remove references to --rotation
This option was removed a long time ago.
2026-04-10 19:29:40 +02:00
Romain Vimont
d5158dac69 Fix man page OTG documentation
The description was updated only in `cli.c`, but the old version was
left in the man page.
2026-04-10 19:29:40 +02:00
Romain Vimont
523c820bfa Avoid double-rendering on resize
On Windows and macOS, resizing the window with the mouse blocks the
event loop until the click is released. To keep rendering during
resizing, an event watcher is registered to handle resize events.

Avoid handling resize events twice by ensuring
`SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED` is processed only once.

PR #6758 <https://github.com/Genymobile/scrcpy/pull/6758>
2026-04-10 19:27:13 +02:00
Romain Vimont
8983023457 Factorize resize event handling
Reuse the same code to handle resize events from the event loop or the
event watcher.

PR #6758 <https://github.com/Genymobile/scrcpy/pull/6758>
2026-04-10 19:27:13 +02:00
Romain Vimont
07f8eb0ec6 Move Ctrl+C handler configuration
The function `sdl_configure()` now only sets the Ctrl+C handler on
Windows. Define it only on Windows, and call it earlier.

Refs #6754 <https://github.com/Genymobile/scrcpy/pull/6754>
2026-04-07 19:51:20 +02:00
Romain Vimont
c527bc76de Enable screensaver using hints
SDL disables the screensaver by default. It can be configured via a
hint instead of explicitly calling `SDL_EnableScreenSaver()`.

Refs #6754 <https://github.com/Genymobile/scrcpy/pull/6754>
2026-04-07 19:50:48 +02:00
Romain Vimont
003616bd2c Always set hints
Some hints can be useful even when window is dsabled.

Refs #6754 <https://github.com/Genymobile/scrcpy/pull/6754>
2026-04-07 19:50:35 +02:00