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 smoothWindows = 0
lastCut = null lastCut = null
decoderBound = false decoderBound = false
adaptiveVideo = CarSettings.experimentalFeaturesEnabled.value && CarSettings.adaptiveVideoEnabled.value
if (adaptiveVideo) log.i("video: adaptive bitrate on (experimental)")
videoSource = VideoSource( videoSource = VideoSource(
width = width, width = width,
height = height, height = height,
@@ -1407,6 +1409,8 @@ class GearslipRunner(
private var smoothWindows = 0 private var smoothWindows = 0
/** The bitrate and frame rate before the last cut, to see whether cutting helped. */ /** The bitrate and frame rate before the last cut, to see whether cutting helped. */
private var lastCut: Pair<Int, Double>? = null 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. */ /** Set once a cut didn't help: this car's decoder, not the link, sets the pace. */
private var decoderBound = false private var decoderBound = false
@@ -1417,6 +1421,7 @@ class GearslipRunner(
* where the stream started. A still screen (few frames, no waiting) changes nothing. * where the stream started. A still screen (few frames, no waiting) changes nothing.
*/ */
private fun adaptBitRate(fps: Double, waitedMs: Long) { private fun adaptBitRate(fps: Double, waitedMs: Long) {
if (!adaptiveVideo) return
val source = videoSource ?: return val source = videoSource ?: return
val target = videoFrameRate.toDouble() val target = videoFrameRate.toDouble()
val behind = waitedMs > ADAPT_WINDOW_MS / 2 && fps < target * 0.8 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_EXPERIMENTAL_FEATURES = "car_experimental_features"
private const val KEY_SYSTEM_SPEECH = "car_system_speech" private const val KEY_SYSTEM_SPEECH = "car_system_speech"
private const val KEY_CAR_SENSORS = "car_sensors_enabled" 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_SEEN_SAFETY_WARNING = "car_seen_safety_warning"
private const val KEY_UNITS = "car_units" private const val KEY_UNITS = "car_units"
private const val KEY_NAV_BAR = "car_nav_bar" 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 experimentalFeaturesFlow = MutableStateFlow(false)
private val systemSpeechFlow = MutableStateFlow(false) private val systemSpeechFlow = MutableStateFlow(false)
private val carSensorsFlow = MutableStateFlow(false) private val carSensorsFlow = MutableStateFlow(false)
private val adaptiveVideoFlow = MutableStateFlow(false)
private val seenSafetyWarningFlow = MutableStateFlow(false) private val seenSafetyWarningFlow = MutableStateFlow(false)
private val unitsFlow = MutableStateFlow(Units.AUTO) private val unitsFlow = MutableStateFlow(Units.AUTO)
@@ -272,6 +274,12 @@ private const val KEY_LOCATION_WARNING = "car_location_warning"
*/ */
val carSensorsEnabled: StateFlow<Boolean> = carSensorsFlow 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 * 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 - * 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" experimentalFeaturesFlow.value = AppSettings.getString(app, KEY_EXPERIMENTAL_FEATURES, "false") == "true"
systemSpeechFlow.value = AppSettings.getString(app, KEY_SYSTEM_SPEECH, "false") == "true" systemSpeechFlow.value = AppSettings.getString(app, KEY_SYSTEM_SPEECH, "false") == "true"
carSensorsFlow.value = AppSettings.getString(app, KEY_CAR_SENSORS, "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" seenSafetyWarningFlow.value = AppSettings.getString(app, KEY_SEEN_SAFETY_WARNING, "false") == "true"
unitsFlow.value = runCatching { unitsFlow.value = runCatching {
Units.valueOf(AppSettings.getString(app, KEY_UNITS, Units.AUTO.name)) 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()) 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) { fun setCarSensorsEnabled(on: Boolean) {
carSensorsFlow.value = on carSensorsFlow.value = on
AppSettings.putString(app, KEY_CAR_SENSORS, on.toString()) AppSettings.putString(app, KEY_CAR_SENSORS, on.toString())
@@ -69,6 +69,7 @@ fun CarSettingsScreen() {
val uiTheme by CarSettings.uiTheme.collectAsState() val uiTheme by CarSettings.uiTheme.collectAsState()
val experimentalFeatures by CarSettings.experimentalFeaturesEnabled.collectAsState() val experimentalFeatures by CarSettings.experimentalFeaturesEnabled.collectAsState()
val carSensors by CarSettings.carSensorsEnabled.collectAsState() val carSensors by CarSettings.carSensorsEnabled.collectAsState()
val adaptiveVideo by CarSettings.adaptiveVideoEnabled.collectAsState()
val systemSpeech by CarSettings.systemSpeech.collectAsState() val systemSpeech by CarSettings.systemSpeech.collectAsState()
val display by CarEnvironment.display.collectAsState() val display by CarEnvironment.display.collectAsState()
val vehicle by CarEnvironment.vehicle.collectAsState() val vehicle by CarEnvironment.vehicle.collectAsState()
@@ -278,7 +279,7 @@ fun CarSettingsScreen() {
} }
if (experimentalFeatures) item { if (experimentalFeatures) item {
ExperimentalFeaturesList(carSensors) ExperimentalFeaturesList(carSensors, adaptiveVideo)
} }
item { 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. * so the list reads fine whether there's one entry or several.
*/ */
@Composable @Composable
private fun ExperimentalFeaturesList(carSensors: Boolean) { private fun ExperimentalFeaturesList(carSensors: Boolean, adaptiveVideo: Boolean) {
Column( Column(
Modifier.fillMaxWidth(), Modifier.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(10.dp), 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.", "guess, not a fact, until you've watched one change for yourself.",
checked = carSensors, checked = carSensors,
) { CarSettings.setCarSensorsEnabled(it) } ) { 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) }
} }
} }