video: adaptive bitrate is an experimental feature, off until it's been tried in a car

This commit is contained in:
Seb3thehacker committed 2026-10-24 16:25:58 -07:00
1 parent e920093fa8
commit dc7018f394
3 files changed
+28 -2

No files matched your search

@@ -1094,6 +1094,8 @@ class GearslipRunner(
smoothWindows = 0
lastCut = null
decoderBound = false
adaptiveVideo = CarSettings.experimentalFeaturesEnabled.value && CarSettings.adaptiveVideoEnabled.value
if (adaptiveVideo) log.i("video: adaptive bitrate on (experimental)")
videoSource = VideoSource(
width = width,
height = height,
@@ -1407,6 +1409,8 @@ class GearslipRunner(
private var smoothWindows = 0
/** The bitrate and frame rate before the last cut, to see whether cutting helped. */
private var lastCut: Pair<Int, Double>? = null
/** Experimental: read once per stream, so flipping the switch mid-drive changes nothing. */
@Volatile private var adaptiveVideo = false
/** Set once a cut didn't help: this car's decoder, not the link, sets the pace. */
private var decoderBound = false
@@ -1417,6 +1421,7 @@ class GearslipRunner(
* where the stream started. A still screen (few frames, no waiting) changes nothing.
*/
private fun adaptBitRate(fps: Double, waitedMs: Long) {
if (!adaptiveVideo) return
val source = videoSource ?: return
val target = videoFrameRate.toDouble()
val behind = waitedMs > ADAPT_WINDOW_MS / 2 && fps < target * 0.8
@@ -71,6 +71,7 @@ private const val KEY_LOCATION_WARNING = "car_location_warning"
private const val KEY_EXPERIMENTAL_FEATURES = "car_experimental_features"
private const val KEY_SYSTEM_SPEECH = "car_system_speech"
private const val KEY_CAR_SENSORS = "car_sensors_enabled"
private const val KEY_ADAPTIVE_VIDEO = "adaptive_video_enabled"
private const val KEY_SEEN_SAFETY_WARNING = "car_seen_safety_warning"
private const val KEY_UNITS = "car_units"
private const val KEY_NAV_BAR = "car_nav_bar"
@@ -113,6 +114,7 @@ private const val KEY_LOCATION_WARNING = "car_location_warning"
private val experimentalFeaturesFlow = MutableStateFlow(false)
private val systemSpeechFlow = MutableStateFlow(false)
private val carSensorsFlow = MutableStateFlow(false)
private val adaptiveVideoFlow = MutableStateFlow(false)
private val seenSafetyWarningFlow = MutableStateFlow(false)
private val unitsFlow = MutableStateFlow(Units.AUTO)
@@ -272,6 +274,12 @@ private const val KEY_LOCATION_WARNING = "car_location_warning"
*/
val carSensorsEnabled: StateFlow<Boolean> = carSensorsFlow
/**
* Video bitrate that backs off when the car, or the Wi-Fi to it, falls behind. Takes effect
* only while [experimentalFeaturesEnabled] is on too; untested in a car so far.
*/
val adaptiveVideoEnabled: StateFlow<Boolean> = adaptiveVideoFlow
/**
* Whether the car screen's own "drive safely" warning has already been shown and dismissed
* once, from this same install. Separate from the phone side's own compat/safety dialogs -
@@ -314,6 +322,7 @@ private const val KEY_LOCATION_WARNING = "car_location_warning"
experimentalFeaturesFlow.value = AppSettings.getString(app, KEY_EXPERIMENTAL_FEATURES, "false") == "true"
systemSpeechFlow.value = AppSettings.getString(app, KEY_SYSTEM_SPEECH, "false") == "true"
carSensorsFlow.value = AppSettings.getString(app, KEY_CAR_SENSORS, "false") == "true"
adaptiveVideoFlow.value = AppSettings.getString(app, KEY_ADAPTIVE_VIDEO, "false") == "true"
seenSafetyWarningFlow.value = AppSettings.getString(app, KEY_SEEN_SAFETY_WARNING, "false") == "true"
unitsFlow.value = runCatching {
Units.valueOf(AppSettings.getString(app, KEY_UNITS, Units.AUTO.name))
@@ -416,6 +425,11 @@ private const val KEY_LOCATION_WARNING = "car_location_warning"
AppSettings.putString(app, KEY_SYSTEM_SPEECH, on.toString())
}
fun setAdaptiveVideoEnabled(on: Boolean) {
adaptiveVideoFlow.value = on
AppSettings.putString(app, KEY_ADAPTIVE_VIDEO, on.toString())
}
fun setCarSensorsEnabled(on: Boolean) {
carSensorsFlow.value = on
AppSettings.putString(app, KEY_CAR_SENSORS, on.toString())
@@ -69,6 +69,7 @@ fun CarSettingsScreen() {
val uiTheme by CarSettings.uiTheme.collectAsState()
val experimentalFeatures by CarSettings.experimentalFeaturesEnabled.collectAsState()
val carSensors by CarSettings.carSensorsEnabled.collectAsState()
val adaptiveVideo by CarSettings.adaptiveVideoEnabled.collectAsState()
val systemSpeech by CarSettings.systemSpeech.collectAsState()
val display by CarEnvironment.display.collectAsState()
val vehicle by CarEnvironment.vehicle.collectAsState()
@@ -278,7 +279,7 @@ fun CarSettingsScreen() {
}
if (experimentalFeatures) item {
ExperimentalFeaturesList(carSensors)
ExperimentalFeaturesList(carSensors, adaptiveVideo)
}
item {
@@ -368,7 +369,7 @@ private fun <T> ChoiceButtons(options: List<Pair<T, String>>, selected: T, onSel
* so the list reads fine whether there's one entry or several.
*/
@Composable
private fun ExperimentalFeaturesList(carSensors: Boolean) {
private fun ExperimentalFeaturesList(carSensors: Boolean, adaptiveVideo: Boolean) {
Column(
Modifier.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(10.dp),
@@ -381,6 +382,12 @@ private fun ExperimentalFeaturesList(carSensors: Boolean) {
"guess, not a fact, until you've watched one change for yourself.",
checked = carSensors,
) { CarSettings.setCarSensorsEnabled(it) }
ExperimentalFeatureRow(
title = "Adaptive video quality",
description = "Lowers the picture's quality when the car, or its Wi-Fi, can't keep " +
"up, and raises it again once it can. Takes effect on the next connection.",
checked = adaptiveVideo,
) { CarSettings.setAdaptiveVideoEnabled(it) }
}
}