Browse Source

Apply capture gap recovery cadence consistently on Android

stream-multiview
evgeny 6 days ago
parent
commit
47033718ad
  1. 2
      tools/chatgui-android/app/src/main/java/com/utun/chat/data/CallVideoNative.kt
  2. 6
      tools/chatgui-android/app/src/main/java/com/utun/chat/data/CallVideoPlayer.kt
  3. 4
      tools/chatgui-android/jni_bridge/android_call_video_jni.c

2
tools/chatgui-android/app/src/main/java/com/utun/chat/data/CallVideoNative.kt

@ -17,7 +17,7 @@ internal object CallVideoNative {
external fun playoutReset(handle: Long)
/** >0: ждать микросекунды; 0: показать; <0: пропустить только показ. */
external fun playoutStep(handle: Long, pts: Long, received: Long, nextPts: Long, nextReceived: Long,
now: Long): Long
now: Long, intervalUs: Int): Long
external fun requestKey(id: Long)
external fun range(id: Long, minimum: Int, maximum: Int): Boolean
external fun inspect(codec: Int, bytes: ByteArray): LongArray?

6
tools/chatgui-android/app/src/main/java/com/utun/chat/data/CallVideoPlayer.kt

@ -35,7 +35,7 @@ internal class CallVideoPlayer(private val id: Long, private val failure: (Strin
fun stop() { synchronized(this) { running = false }; worker.join() }
private fun loop() {
data class Timing(val pts: Long, val received: Long)
data class Timing(val pts: Long, val received: Long, val interval: Int)
data class Picture(val index: Int, val timing: Timing)
val playout = CallVideoNative.playoutCreate(id)
if (playout == 0L) { failure("Video playout allocation failed"); return }
@ -100,7 +100,7 @@ internal class CallVideoPlayer(private val id: Long, private val failure: (Strin
val first = if (awaitingPts < 0) pictures.peekFirst() else null
val nextPicture = if (first != null && pictures.size > 1) pictures.peekLast() else null
val decision = CallVideoNative.playoutStep(playout, first?.timing?.pts ?: -1, first?.timing?.received ?: 0,
nextPicture?.timing?.pts ?: -1, nextPicture?.timing?.received ?: 0, now / 1000)
nextPicture?.timing?.pts ?: -1, nextPicture?.timing?.received ?: 0, now / 1000, first?.timing?.interval ?: 0)
if (decision > 0) wakeUs = now / 1000 + decision
else if (first != null) {
val render = decision == 0L
@ -153,7 +153,7 @@ internal class CallVideoPlayer(private val id: Long, private val failure: (Strin
} else data
val buffer = checkNotNull(decoder!!.getInputBuffer(index)); check(bytes.size <= buffer.capacity())
buffer.put(bytes); decoder!!.queueInputBuffer(index, 0, bytes.size, meta[10], 0)
inputs.addLast(Timing(meta[10], meta[12])); pending = null; queued++; worked = true
inputs.addLast(Timing(meta[10], meta[12], 1000000 / next.fps)); pending = null; queued++; worked = true
}
}
} else if (data != null && surface == null) { pending = null; CallVideoNative.requestKey(id) }

4
tools/chatgui-android/jni_bridge/android_call_video_jni.c

@ -110,10 +110,10 @@ JNIEXPORT void JNICALL Java_com_utun_chat_data_CallVideoNative_playoutReset(JNIE
call_video_playout_init(p, p->call_id);
}
JNIEXPORT jlong JNICALL Java_com_utun_chat_data_CallVideoNative_playoutStep(JNIEnv *e, jobject o, jlong handle,
jlong pts, jlong received, jlong next_pts, jlong next_received, jlong now) {
jlong pts, jlong received, jlong next_pts, jlong next_received, jlong now, jint interval_us) {
(void)e; (void)o; struct call_video_playout *p = (void *)(uintptr_t)handle;
if (!p) { DEBUG_ERROR(DEBUG_CATEGORY_CALL, "video playout poll without handle"); return 5000; }
struct call_video_playout_frame f = {pts, received}, next = {next_pts, next_received};
struct call_video_playout_frame f = {pts, received, interval_us}, next = {next_pts, next_received, interval_us};
struct call_clock_snapshot clock = {0}; call_audio_get_clock(p->call_id, now, &clock);
int action = call_video_playout_poll(p, pts >= 0 ? &f : NULL, next_pts >= 0 ? &next : NULL, now, &clock);
if (action == CALL_VIDEO_PLAYOUT_SHOW) return 0;

Loading…
Cancel
Save