Validate bitrate ceilings and recovery without requiring filler data

This commit is contained in:
evgeny committed 2026-10-15 01:29:20 +02:00
1 parent eeb3ca5927
commit 1376f9f059
1 file changed
+12 -2
@@ -10,7 +10,11 @@ import android.os.Bundle
/** Запускается только явно через adb am instrument; камера и реальные звонки не затрагиваются. */ /** Запускается только явно через adb am instrument; камера и реальные звонки не затрагиваются. */
class CallVideoProbe : Instrumentation() { class CallVideoProbe : Instrumentation() {
private var remote: String? = null private var remote: String? = null
override fun onCreate(arguments: Bundle?) { remote = arguments?.getString("remote"); super.onCreate(arguments); start() } private var selectedCodec = 0
override fun onCreate(arguments: Bundle?) {
remote = arguments?.getString("remote"); selectedCodec = arguments?.getString("codec")?.toIntOrNull() ?: 0
super.onCreate(arguments); start()
}
override fun onStart() { override fun onStart() {
try { try {
val decoders = CallVideoCodec.probeDecoders() val decoders = CallVideoCodec.probeDecoders()
@@ -28,7 +32,9 @@ class CallVideoProbe : Instrumentation() {
} }
val codecs = CallVideoCodec.probe() val codecs = CallVideoCodec.probe()
check(codecs.isNotEmpty() && decoders.isNotEmpty()) { "No verified encoders or decoders" } check(codecs.isNotEmpty() && decoders.isNotEmpty()) { "No verified encoders or decoders" }
check(selectedCodec == 0 || selectedCodec in codecs) { "Requested codec unavailable: $selectedCodec" }
for ((codec, entry) in codecs) { for ((codec, entry) in codecs) {
if (selectedCodec != 0 && selectedCodec != codec) continue
val f = CallVideoFormat(1, 640, 480, codec = codec, level = entry.level, profile = entry.profile) val f = CallVideoFormat(1, 640, 480, codec = codec, level = entry.level, profile = entry.profile)
verifyRateChanges(f, entry.name) verifyRateChanges(f, entry.name)
CallVideoCodec(f, 1_000_000, entry.name).use { encoder -> CallVideoCodec(f, 1_000_000, entry.name).use { encoder ->
@@ -80,7 +86,11 @@ class CallVideoProbe : Instrumentation() {
"elapsed_ms=${(System.nanoTime() - started) / 1_000_000}" "elapsed_ms=${(System.nanoTime() - started) / 1_000_000}"
android.util.Log.i("CallVideoProbe", "rate check $result") android.util.Log.i("CallVideoProbe", "rate check $result")
check(input == 120 && output == 120 && key) { "Incomplete rate check: $result" } check(input == 120 && output == 120 && key) { "Incomplete rate check: $result" }
check(measured > rate / 2 && measured < rate.toLong() * 3 / 2) { "Bitrate change ineffective: $result" } // При сильной квантизации шум исчезает: low-rate кадр может занять меньше целевой полосы.
// Игнорирование команды ловит верхний предел, возврат к 4M — нижний предел high-rate фаз.
check(measured > 0 && measured < rate.toLong() * 3 / 2 && (rate == 300_000 || measured > rate / 2)) {
"Bitrate change ineffective: $result"
}
} }
} }
} }