mirror of
https://github.com/twinksoftware/Gearslip.git
synced 2026-11-11 08:12:26 +01:00
screen size auto negotiation
This commit is contained in:
1 parent
f21df41506
commit
c52a6c32b7
2 files changed
+33
-7
No files matched your search
@@ -631,15 +631,11 @@ class GearslipRunner(
|
|||||||
"configuration_indices=$indices",
|
"configuration_indices=$indices",
|
||||||
)
|
)
|
||||||
if (maxUnackedFromConfig != null) maxUnacked = maxOf(1, maxUnackedFromConfig)
|
if (maxUnackedFromConfig != null) maxUnacked = maxOf(1, maxUnackedFromConfig)
|
||||||
// Prefer the smallest offered resolution for the first attempt: fewer pixels,
|
|
||||||
// fewer ways for a first encode to go wrong.
|
|
||||||
val offered = indices.map { it.toInt() }
|
val offered = indices.map { it.toInt() }
|
||||||
val preferred = vehicleProfile?.resolution?.let { want ->
|
val preferred = vehicleProfile?.resolution?.let { want ->
|
||||||
offered.firstOrNull { videoConfigs.getOrNull(it)?.resolutionName == want }
|
offered.firstOrNull { videoConfigs.getOrNull(it)?.resolutionName == want }
|
||||||
}
|
}
|
||||||
selectedConfigIndex = preferred ?: offered.minByOrNull { idx ->
|
selectedConfigIndex = preferred ?: fitToScreen(offered) ?: offered.firstOrNull()
|
||||||
videoConfigs.getOrNull(idx)?.pixelCount() ?: Int.MAX_VALUE
|
|
||||||
} ?: offered.firstOrNull()
|
|
||||||
log.i("selected config index $selectedConfigIndex from offered $offered")
|
log.i("selected config index $selectedConfigIndex from offered $offered")
|
||||||
SessionReport.video(
|
SessionReport.video(
|
||||||
"${videoConfigs.getOrNull(selectedConfigIndex ?: -1)?.resolutionName ?: "?"} " +
|
"${videoConfigs.getOrNull(selectedConfigIndex ?: -1)?.resolutionName ?: "?"} " +
|
||||||
@@ -685,6 +681,20 @@ class GearslipRunner(
|
|||||||
// -> Data (8-byte big-endian timestamp, then the H.264 access unit)
|
// -> Data (8-byte big-endian timestamp, then the H.264 access unit)
|
||||||
// <- Ack { session_id, ack } - at most max_unacked frames may be outstanding
|
// <- Ack { session_id, ack } - at most max_unacked frames may be outstanding
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The offered config that best fills the car's screen: the smallest whose visible width
|
||||||
|
* reaches most of the touchscreen's, else the largest there is. Always taking the smallest
|
||||||
|
* put 800x480 on a 1540x720 Audi screen and stretched it. With no touchscreen size to go
|
||||||
|
* by, the smallest is still the safe choice.
|
||||||
|
*/
|
||||||
|
private fun fitToScreen(offered: List<Int>): Int? {
|
||||||
|
val known = offered.filter { videoConfigs.getOrNull(it)?.pixelSize() != null }
|
||||||
|
fun pixels(idx: Int) = videoConfigs[idx].pixelCount()
|
||||||
|
if (touchWidth <= 0) return known.minByOrNull(::pixels)
|
||||||
|
val wide = known.filter { (videoConfigs[it].visibleSize()?.first ?: 0) >= touchWidth * 8 / 10 }
|
||||||
|
return wide.minByOrNull(::pixels) ?: known.maxByOrNull(::pixels)
|
||||||
|
}
|
||||||
|
|
||||||
private fun startVideoSource() {
|
private fun startVideoSource() {
|
||||||
lastKeyframeSentAt = System.currentTimeMillis() // frame #1 is always a keyframe
|
lastKeyframeSentAt = System.currentTimeMillis() // frame #1 is always a keyframe
|
||||||
val index = selectedConfigIndex ?: 0
|
val index = selectedConfigIndex ?: 0
|
||||||
@@ -702,6 +712,13 @@ class GearslipRunner(
|
|||||||
Protobuf.varintField(2, index.toLong())
|
Protobuf.varintField(2, index.toLong())
|
||||||
send(MSG_MEDIA_START, start, encrypted = true, channel = videoChannelId)
|
send(MSG_MEDIA_START, start, encrypted = true, channel = videoChannelId)
|
||||||
log.i("-> Start(session_id=$SESSION_ID, configuration_index=$index -> $config)")
|
log.i("-> Start(session_id=$SESSION_ID, configuration_index=$index -> $config)")
|
||||||
|
// The car crops its margins off the frame, so keep the UI out of them unless a vehicle
|
||||||
|
// profile has its own tuned insets.
|
||||||
|
if (vehicleProfile?.insets.let { it == null || it == Insets.NONE }) {
|
||||||
|
val insets = config.marginInsets()
|
||||||
|
CarEnvironment.setInsets(insets)
|
||||||
|
if (insets != Insets.NONE) log.i("keeping the UI clear of the car's margins: $insets")
|
||||||
|
}
|
||||||
|
|
||||||
val useProjection = projection != null
|
val useProjection = projection != null
|
||||||
videoSource = VideoSource(
|
videoSource = VideoSource(
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ object ServiceDiscovery {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* [widthMargin]/[heightMargin] are the head unit's own numbers (VideoConfiguration fields 3
|
* [widthMargin]/[heightMargin] are the head unit's own numbers (VideoConfiguration fields 3
|
||||||
* and 4): pixels of the frame it does not treat as usable UI. Logged, and available to a
|
* and 4): pixels of the frame it crops away, split evenly between the two edges, to fit the
|
||||||
* vehicle profile, but not applied automatically - what they mean varies by unit.
|
* frame to a screen of a different shape. A matched vehicle profile's insets override them.
|
||||||
*/
|
*/
|
||||||
class VideoConfig(
|
class VideoConfig(
|
||||||
val resolution: Int,
|
val resolution: Int,
|
||||||
@@ -38,6 +38,15 @@ object ServiceDiscovery {
|
|||||||
|
|
||||||
fun pixelCount(): Int = pixelSize()?.let { it.first * it.second } ?: Int.MAX_VALUE
|
fun pixelCount(): Int = pixelSize()?.let { it.first * it.second } ?: Int.MAX_VALUE
|
||||||
|
|
||||||
|
/** What's left on the car's screen once the margins are cropped off. */
|
||||||
|
fun visibleSize(): Pair<Int, Int>? = pixelSize()?.let { (w, h) -> (w - widthMargin) to (h - heightMargin) }
|
||||||
|
|
||||||
|
/** The margins as the strips of the frame the car UI keeps clear. */
|
||||||
|
fun marginInsets(): Insets = Insets(
|
||||||
|
top = heightMargin / 2, bottom = heightMargin - heightMargin / 2,
|
||||||
|
left = widthMargin / 2, right = widthMargin - widthMargin / 2,
|
||||||
|
)
|
||||||
|
|
||||||
override fun toString() =
|
override fun toString() =
|
||||||
"$resolutionName @ $frameRateName, density=$density, margin=${widthMargin}x$heightMargin"
|
"$resolutionName @ $frameRateName, density=$density, margin=${widthMargin}x$heightMargin"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user