Better logic for choosing the display mode (#1039)

## Description
This PR improves the logic used to choose a display mode when refresh
rate and resolution switching are enabled.

As before, matching the refresh rate is prioritized over picking the
resolution. For example, with the display modes of 1080@30 & 720@60 for
a 720@30 video, 1080@30 is used because the frame rate exactly matches.

### Related issues
Fixes #1036

### Testing
Unit tests, added test cases for more situations

## Screenshots
N/A

## AI or LLM usage
None
This commit is contained in:
Ray 2026-03-04 19:30:14 -05:00 committed by GitHub
parent 354577e2e8
commit 014bed1bf3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 188 additions and 15 deletions

View file

@ -158,33 +158,58 @@ class RefreshRateService
if (refreshRateSwitch) {
displayModes
.filterNot { it.physicalHeight < streamHeight || it.physicalWidth < streamWidth }
.filter {
it.refreshRateRounded % streamRate == 0 || // Exact multiple
it.refreshRateRounded == (streamRate * 2.5).roundToInt() // eg 24 & 60fps
}
.filter { frameRateMatches(it.refreshRateRounded, streamRate) }
} else {
displayModes
.filterNot { it.physicalHeight < streamHeight || it.physicalWidth < streamWidth }
}
// Timber.v("display modes candidates: %s", candidates.joinToString("\n"))
return if (!resolutionSwitch) {
candidates.maxByOrNull { it.physicalWidth * it.physicalHeight }
candidates
.filter { it.refreshRateRounded == streamRate }
.maxByOrNull { it.physicalWidth * it.physicalHeight }
?: candidates.maxByOrNull { it.physicalWidth * it.physicalHeight }
} else {
// Exact resolution & frame rate
candidates.firstOrNull {
it.physicalWidth == streamWidth &&
it.physicalHeight == streamHeight &&
it.refreshRateRounded == streamRate
}
?: candidates.firstOrNull {
it.physicalWidth == streamWidth &&
// Next highest resolution, exact frame rate
?: candidates.lastOrNull {
it.physicalWidth >= streamWidth &&
it.physicalHeight >= streamHeight &&
it.refreshRateRounded == streamRate
}
// Exact resolution, acceptable frame rate
?: candidates.lastOrNull {
it.physicalWidth == streamWidth &&
it.physicalHeight == streamHeight &&
frameRateMatches(it.refreshRateRounded, streamRate)
}
// Next highest resolution, acceptable frame rate
?: candidates.lastOrNull {
it.physicalWidth >= streamWidth &&
it.physicalHeight >= streamHeight &&
frameRateMatches(it.refreshRateRounded, streamRate)
}
// Fall back to largest resolution, exact frame rate
?: candidates
.filter { it.refreshRateRounded == streamRate }
.maxByOrNull { it.physicalWidth * it.physicalHeight }
// Finally, just the highest resolution
?: candidates.maxByOrNull { it.physicalWidth * it.physicalHeight }
}
}
fun frameRateMatches(
refreshRateRounded: Int,
streamRate: Int,
): Boolean {
return refreshRateRounded % streamRate == 0 || // Exact multiple
refreshRateRounded == (streamRate * 2.5).roundToInt() // eg 24 & 60fps
}
}
}