|
|
|
|
@ -63,6 +63,8 @@ class CallVideoEngine(private val context: Context, private val id: Long) {
|
|
|
|
|
private var reportAt = 0L |
|
|
|
|
private var encodedBytes = 0L |
|
|
|
|
private var encodedFrames = 0 |
|
|
|
|
private var rejectedGeneration = 0L |
|
|
|
|
private var excluded = emptySet<Int>() |
|
|
|
|
|
|
|
|
|
init { |
|
|
|
|
handler.post { |
|
|
|
|
@ -96,7 +98,7 @@ class CallVideoEngine(private val context: Context, private val id: Long) {
|
|
|
|
|
|
|
|
|
|
fun surface(surface: Surface?) = player.surface(surface) |
|
|
|
|
fun select(settings: CallVideoSettings) { handler.post { |
|
|
|
|
if (!stopped) { wanted = settings; mutable.value = mutable.value.copy(settings = settings) } |
|
|
|
|
if (!stopped) { wanted = settings; excluded = emptySet(); mutable.value = mutable.value.copy(settings = settings) } |
|
|
|
|
} } |
|
|
|
|
fun range(value: CallVideoBitrateRange) { handler.post { |
|
|
|
|
if (CallVideoNative.range(id, value.minimum * 1000, value.maximum * 1000)) mutable.value = mutable.value.copy(range = value) |
|
|
|
|
@ -119,11 +121,25 @@ class CallVideoEngine(private val context: Context, private val id: Long) {
|
|
|
|
|
val s = CallVideoNative.status(id) ?: return |
|
|
|
|
if (s[6] >= 300000 && s[7] >= s[6]) mutable.value = mutable.value.copy(range = CallVideoBitrateRange((s[6] / 1000).toInt(), (s[7] / 1000).toInt())) |
|
|
|
|
if (keySerial != s[0]) { keySerial = s[0]; needKey = true } |
|
|
|
|
val current = format |
|
|
|
|
if (current != null && s[8] == current.generation && s[9] == 0L && rejectedGeneration != s[8]) { |
|
|
|
|
rejectedGeneration = s[8]; excluded = excluded + current.codec |
|
|
|
|
if (wanted.codec == 0) { |
|
|
|
|
report("Receiver rejected video; selecting fallback") |
|
|
|
|
val peer = CallVideoNative.peer(id) |
|
|
|
|
if (peer != null) change(peer) |
|
|
|
|
} else fail("Receiver cannot decode selected codec") |
|
|
|
|
} |
|
|
|
|
if (s[1] == format?.generation && s[2] > request) { |
|
|
|
|
request = s[2]; pendingRequest = request; pendingRate = s[3].toInt() |
|
|
|
|
} |
|
|
|
|
if (!wanted.enabled) { |
|
|
|
|
if (active != null) { closeCamera(); encoder?.close(); encoder = null; active = null; report("Video off") } |
|
|
|
|
if (active != null) { |
|
|
|
|
val pending = if (confirmingRequest != 0L) confirmingRequest else pendingRequest |
|
|
|
|
if (pending != 0L) CallVideoNative.applied(id, format?.generation ?: 0, pending, 0) |
|
|
|
|
confirmingRequest = 0; pendingRequest = 0 |
|
|
|
|
closeCamera(); encoder?.close(); encoder = null; active = null; report("Video off") |
|
|
|
|
} |
|
|
|
|
} else if (wanted != active && !opening && !closing && (lastKey < 0 || System.nanoTime() / 1000 - lastKey >= 1_000_000)) { |
|
|
|
|
val peer = CallVideoNative.peer(id) |
|
|
|
|
if (peer != null) change(peer) |
|
|
|
|
@ -141,6 +157,7 @@ class CallVideoEngine(private val context: Context, private val id: Long) {
|
|
|
|
|
val previousName = previous?.name; val previousRate = previous?.bitrate |
|
|
|
|
previous?.close(); encoder = null |
|
|
|
|
for (codec in if (wanted.codec == 0) listOf(2, 1) else listOf(wanted.codec)) { |
|
|
|
|
if (codec in excluded) continue |
|
|
|
|
val implementation = encoders[codec] ?: continue |
|
|
|
|
val selected = CallVideoNative.choose(caps, peer, desired.copy(codec = codec).array()) ?: continue |
|
|
|
|
var candidate: CallVideoCodec? = null |
|
|
|
|
@ -160,7 +177,7 @@ class CallVideoEngine(private val context: Context, private val id: Long) {
|
|
|
|
|
LogManager.addLog("WARN", "call", "video mode rejected codec=$codec name=${implementation.name}: ${e.message}") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (previousFormat != null && previousSettings != null && previousName != null && previousRate != null) { |
|
|
|
|
if (previousFormat != null && previousFormat.codec !in excluded && previousSettings != null && previousName != null && previousRate != null) { |
|
|
|
|
encoder = CallVideoCodec(previousFormat, previousRate, previousName).also { it.prepare(); check(it.format == previousFormat) } |
|
|
|
|
wanted = previousSettings; needKey = true |
|
|
|
|
mutable.value = mutable.value.copy(settings = wanted) |
|
|
|
|
|