Browse Source

Preserve bitrate bounds on format changes and discard late desktop pictures

master
evgeny 4 days ago
parent
commit
5f16c79559
  1. 7
      tools/chatgui-android/app/src/main/java/com/utun/chat/data/CallVideoEngine.kt
  2. 9
      tools/chatgui/src/call_video_engine.cpp

7
tools/chatgui-android/app/src/main/java/com/utun/chat/data/CallVideoEngine.kt

@ -155,6 +155,8 @@ class CallVideoEngine(private val context: Context, private val id: Long) {
val desired = CallVideoFormat(++generation, wanted.width, wanted.height, rotation = rotation, codec = wanted.codec)
val previous = encoder; val previousFormat = format; val previousSettings = active
val previousName = previous?.name; val previousRate = previous?.bitrate
val range = mutable.value.range
val initialRate = (previousRate ?: 1_000_000).coerceIn(range.minimum * 1000, range.maximum * 1000)
previous?.close(); encoder = null
for (codec in if (wanted.codec == 0) listOf(2, 1) else listOf(wanted.codec)) {
if (codec in excluded) continue
@ -162,7 +164,7 @@ class CallVideoEngine(private val context: Context, private val id: Long) {
val selected = CallVideoNative.choose(caps, peer, desired.copy(codec = codec).array()) ?: continue
var candidate: CallVideoCodec? = null
try {
candidate = CallVideoCodec(CallVideoFormat.from(selected), 1_000_000, implementation.name)
candidate = CallVideoCodec(CallVideoFormat.from(selected), initialRate, implementation.name)
candidate.prepare()
val next = candidate.format
check(CallVideoNative.supported(caps, peer, next.array())) { "Actual encoder format exceeds peer capabilities: $next" }
@ -178,7 +180,8 @@ class CallVideoEngine(private val context: Context, private val id: Long) {
}
}
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) }
encoder = CallVideoCodec(previousFormat, previousRate, previousName)
encoder!!.prepare(); check(encoder!!.format == previousFormat)
wanted = previousSettings; needKey = true
mutable.value = mutable.value.copy(settings = wanted)
report("Selected mode unavailable; previous video restored")

9
tools/chatgui/src/call_video_engine.cpp

@ -179,10 +179,13 @@ void CallVideoEngine::transmit() {
if (lastKey >= 0 && pts - lastKey < 1000000) { idle(); continue; }
call_video_format next{format.generation + 1, (uint16_t)width, (uint16_t)height, 30, 0, (uint8_t)codec, 0, 4000000, 0};
bool opened = false;
uint32_t minimum = state.minimum_bps ? state.minimum_bps : 300000;
uint32_t maximum = state.maximum_bps ? state.maximum_bps : 4000000;
uint32_t initialRate = std::max(minimum, std::min(maximum, encoder.bitrate() ? encoder.bitrate() : 1000000));
for (int candidate = 2; candidate >= 1; --candidate) {
if ((codec && codec != candidate) || (excluded & (1u << candidate))) continue;
next.codec = candidate; next.level = next.profile = 0;
if (call_video_choose(&caps, &state.peer, &next) > 0 && encoder.open(next, 1000000)) { opened = true; break; }
if (call_video_choose(&caps, &state.peer, &next) > 0 && encoder.open(next, initialRate)) { opened = true; break; }
}
if (!opened) {
m->report(tr("Selected video mode is unavailable to the peer"));
@ -240,7 +243,9 @@ void CallVideoEngine::receive() {
sourceEpoch = clock.source_epoch;
QImage selected;
while (!pictures.empty() && pictures.front().pts <= clock.pts_us) {
if (pictures.front().pts > lastShown) { selected = pictures.front().image; lastShown = pictures.front().pts; }
if (pictures.front().pts > lastShown && pictures.front().pts >= clock.pts_us - 500000) {
selected = pictures.front().image; lastShown = pictures.front().pts;
}
pictures.pop_front();
}
if (!selected.isNull()) { std::lock_guard<std::mutex> guard(m->lock); m->shown = selected; ++m->shownSerial; ++shown; }

Loading…
Cancel
Save