mirror of
https://github.com/Genymobile/scrcpy.git
synced 2026-04-21 01:33:36 +00:00
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.
This commit is contained in:
parent
3e7da96a57
commit
2151760f28
4 changed files with 86 additions and 5 deletions
|
|
@ -97,8 +97,8 @@ public class DisplayMonitor {
|
|||
}
|
||||
}
|
||||
|
||||
public void setSessionDisplayProperties(DisplayProperties props) {
|
||||
tracker.setCurrent(props);
|
||||
public void expectChange(DisplayProperties props) {
|
||||
tracker.expectChange(props);
|
||||
}
|
||||
|
||||
private void checkDisplayPropertiesChanged() {
|
||||
|
|
|
|||
|
|
@ -2,10 +2,33 @@ package com.genymobile.scrcpy.display;
|
|||
|
||||
import com.genymobile.scrcpy.util.Ln;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class DisplayPropertiesTracker {
|
||||
|
||||
private static class PendingChange {
|
||||
private final DisplayProperties props;
|
||||
private final long timestamp;
|
||||
|
||||
PendingChange(DisplayProperties props, long timestamp) {
|
||||
this.props = props;
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
private static final long PENDING_CACHE_DURATION = 2000; // ms
|
||||
private final List<PendingChange> pending = new ArrayList<>();
|
||||
|
||||
private DisplayProperties props;
|
||||
|
||||
public synchronized void setCurrent(DisplayProperties props) {
|
||||
private static long nowMs() {
|
||||
return System.nanoTime() / 1000000;
|
||||
}
|
||||
|
||||
public synchronized void expectChange(DisplayProperties props) {
|
||||
long now = nowMs();
|
||||
pending.add(new PendingChange(props, now));
|
||||
this.props = props;
|
||||
}
|
||||
|
||||
|
|
@ -27,6 +50,13 @@ public final class DisplayPropertiesTracker {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (consumeExpectedChange(props)) {
|
||||
if (Ln.isEnabled(Ln.Level.VERBOSE)) {
|
||||
Ln.v(getClass().getSimpleName() + ": " + prev + " -> " + props + " (ignored)");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (props.equals(prev)) {
|
||||
if (Ln.isEnabled(Ln.Level.VERBOSE)) {
|
||||
Ln.v(getClass().getSimpleName() + ": " + props + " (unchanged)");
|
||||
|
|
@ -40,4 +70,55 @@ public final class DisplayPropertiesTracker {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean consumeExpectedChange(DisplayProperties props) {
|
||||
cleanExpired();
|
||||
int index = getMatchingPendingIndex(props);
|
||||
if (index == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove all pending changes up to (and including) the matching one
|
||||
pending.subList(0, index+1).clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
private int getMatchingPendingIndex(DisplayProperties props) {
|
||||
for (int i = 0; i < pending.size(); ++i) {
|
||||
if (pending.get(i).props.equals(props)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private int getFirstNonExpiredIndex() {
|
||||
long now = nowMs();
|
||||
for (int i = 0; i < pending.size(); ++i) {
|
||||
if (pending.get(i).timestamp + PENDING_CACHE_DURATION >= now) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private void cleanExpired() {
|
||||
if (pending.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int firstNonExpiredIndex = getFirstNonExpiredIndex();
|
||||
if (firstNonExpiredIndex == 0) {
|
||||
// All items are fresh
|
||||
return;
|
||||
}
|
||||
|
||||
if (firstNonExpiredIndex == -1) {
|
||||
// All items have expired
|
||||
pending.clear();
|
||||
} else {
|
||||
// Remove all the items up to the first non-expired index
|
||||
pending.subList(0, firstNonExpiredIndex).clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ public class NewDisplayCapture extends SurfaceCapture {
|
|||
|
||||
displayRotation = 0;
|
||||
// Set the current display properties to avoid an unnecessary capture reset
|
||||
displayMonitor.setSessionDisplayProperties(new DisplayProperties(displaySize, displayRotation));
|
||||
displayMonitor.expectChange(new DisplayProperties(displaySize, displayRotation));
|
||||
} else {
|
||||
DisplayInfo displayInfo = ServiceManager.getDisplayManager().getDisplayInfo(virtualDisplay.getDisplay().getDisplayId());
|
||||
dpi = displayInfo.getDpi();
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ public class ScreenCapture extends SurfaceCapture {
|
|||
|
||||
Size displaySize = displayInfo.getSize();
|
||||
int displayRotation = displayInfo.getRotation();
|
||||
displayMonitor.setSessionDisplayProperties(new DisplayProperties(displaySize, displayRotation));
|
||||
displayMonitor.expectChange(new DisplayProperties(displaySize, displayRotation));
|
||||
|
||||
if (captureOrientationLock == Orientation.Lock.LockedInitial) {
|
||||
// The user requested to lock the video orientation to the current orientation
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue