Apply capture gap recovery cadence consistently on Android
This commit is contained in:
1 parent
526ee5ec8b
commit
47033718ad
3 files changed
+6
-6
No files matched your search
@@ -17,7 +17,7 @@ internal object CallVideoNative {
|
|||||||
external fun playoutReset(handle: Long)
|
external fun playoutReset(handle: Long)
|
||||||
/** >0: ждать микросекунды; 0: показать; <0: пропустить только показ. */
|
/** >0: ждать микросекунды; 0: показать; <0: пропустить только показ. */
|
||||||
external fun playoutStep(handle: Long, pts: Long, received: Long, nextPts: Long, nextReceived: Long,
|
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 requestKey(id: Long)
|
||||||
external fun range(id: Long, minimum: Int, maximum: Int): Boolean
|
external fun range(id: Long, minimum: Int, maximum: Int): Boolean
|
||||||
external fun inspect(codec: Int, bytes: ByteArray): LongArray?
|
external fun inspect(codec: Int, bytes: ByteArray): LongArray?
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ internal class CallVideoPlayer(private val id: Long, private val failure: (Strin
|
|||||||
fun stop() { synchronized(this) { running = false }; worker.join() }
|
fun stop() { synchronized(this) { running = false }; worker.join() }
|
||||||
|
|
||||||
private fun loop() {
|
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)
|
data class Picture(val index: Int, val timing: Timing)
|
||||||
val playout = CallVideoNative.playoutCreate(id)
|
val playout = CallVideoNative.playoutCreate(id)
|
||||||
if (playout == 0L) { failure("Video playout allocation failed"); return }
|
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 first = if (awaitingPts < 0) pictures.peekFirst() else null
|
||||||
val nextPicture = if (first != null && pictures.size > 1) pictures.peekLast() 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,
|
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
|
if (decision > 0) wakeUs = now / 1000 + decision
|
||||||
else if (first != null) {
|
else if (first != null) {
|
||||||
val render = decision == 0L
|
val render = decision == 0L
|
||||||
@@ -153,7 +153,7 @@ internal class CallVideoPlayer(private val id: Long, private val failure: (Strin
|
|||||||
} else data
|
} else data
|
||||||
val buffer = checkNotNull(decoder!!.getInputBuffer(index)); check(bytes.size <= buffer.capacity())
|
val buffer = checkNotNull(decoder!!.getInputBuffer(index)); check(bytes.size <= buffer.capacity())
|
||||||
buffer.put(bytes); decoder!!.queueInputBuffer(index, 0, bytes.size, meta[10], 0)
|
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) }
|
} else if (data != null && surface == null) { pending = null; CallVideoNative.requestKey(id) }
|
||||||
|
|||||||
@@ -110,10 +110,10 @@ JNIEXPORT void JNICALL Java_com_utun_chat_data_CallVideoNative_playoutReset(JNIE
|
|||||||
call_video_playout_init(p, p->call_id);
|
call_video_playout_init(p, p->call_id);
|
||||||
}
|
}
|
||||||
JNIEXPORT jlong JNICALL Java_com_utun_chat_data_CallVideoNative_playoutStep(JNIEnv *e, jobject o, jlong handle,
|
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;
|
(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; }
|
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);
|
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);
|
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;
|
if (action == CALL_VIDEO_PLAYOUT_SHOW) return 0;
|
||||||
|
|||||||
Reference in new issue
Block a user