Browse Source

Observe actual silent device intervals when adapting playback history

master
evgeny 5 days ago
parent
commit
e1abcb5d69
  1. 11
      src/stream/stream_playback_audio.cpp
  2. 1
      src/stream/stream_playback_audio.h
  3. 5
      tools/chatgui-android/jni_bridge/android_stream_jni.c
  4. 5
      tools/chatgui-android/libutun_lite/stream_bridge.c

11
src/stream/stream_playback_audio.cpp

@ -212,6 +212,17 @@ int64_t stream_playback_audio_pending_gain(struct stream_playback_audio* a, uint
uint64_t stream_playback_audio_written(const struct stream_playback_audio* a) { return a ? a->written : 0; }
int stream_playback_audio_starved(const struct stream_playback_audio* a, uint64_t played) {
if (!a || a->finished) return 0;
if (played >= a->written || !a->outputCount) return 1;
for (unsigned i = 0; i < a->outputCount; i++) {
const auto& span = a->output[(a->outputHead + i) % mapCapacity];
if (span.last <= played) continue;
return span.ptsLast == span.ptsFirst;
}
return 1;
}
void stream_playback_audio_finish(struct stream_playback_audio* a) {
if (!a || a->finished) return;
a->finished = true; a->stretch.flush();

1
src/stream/stream_playback_audio.h

@ -26,6 +26,7 @@ int stream_playback_audio_pull(struct stream_playback_audio *audio, int16_t *pcm
void stream_playback_audio_silence(struct stream_playback_audio *audio, unsigned frames);
int64_t stream_playback_audio_position(struct stream_playback_audio *audio, uint64_t played_frames);
int64_t stream_playback_audio_pending_gain(struct stream_playback_audio *audio, uint64_t played_frames);
int stream_playback_audio_starved(const struct stream_playback_audio *audio, uint64_t played_frames);
uint64_t stream_playback_audio_written(const struct stream_playback_audio *audio);
void stream_playback_audio_finish(struct stream_playback_audio *audio);
int stream_playback_audio_empty(const struct stream_playback_audio *audio);

5
tools/chatgui-android/jni_bridge/android_stream_jni.c

@ -10,6 +10,7 @@
#include "../../../lib/audio_compressor.h"
#include "../libutun_lite/stream_bridge.h"
#include "../../../src/stream/stream_media.h"
#include "../../../src/stream/stream_media_buffer.h"
#include "../../../src/stream/stream_playback_clock.h"
#include "../../../src/stream/stream_playback_audio.h"
@ -88,6 +89,7 @@ struct android_stream_playback {
struct stream_playback_state state;
struct stream_playback_audio *audio;
int64_t position, time_us;
int finished;
};
JNIEXPORT jlong JNICALL Java_com_utun_chat_data_NativeLib_nativeStreamPlaybackCreate(
@ -136,6 +138,7 @@ JNIEXPORT jlongArray JNICALL Java_com_utun_chat_data_NativeLib_nativeStreamPlayb
if (p->audio) {
p->position = stream_playback_audio_position(p->audio, (uint64_t)played);
pending = stream_playback_audio_pending_gain(p->audio, (uint64_t)played);
if (!p->finished && stream_playback_audio_starved(p->audio, (uint64_t)played)) starved = JNI_TRUE;
} else if (p->time_us >= 0 && !starved) {
int64_t elapsed = now - p->time_us;
if (elapsed < 0) { DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "JNI playback wall clock regressed"); return NULL; }
@ -157,7 +160,7 @@ JNIEXPORT jlongArray JNICALL Java_com_utun_chat_data_NativeLib_nativeStreamPlayb
JNIEXPORT void JNICALL Java_com_utun_chat_data_NativeLib_nativeStreamPlaybackFinish(JNIEnv *env, jobject obj, jlong handle) {
(void)env; (void)obj; struct android_stream_playback *p = (struct android_stream_playback *)(intptr_t)handle;
if (p) stream_playback_audio_finish(p->audio);
if (p) { p->finished = 1; stream_playback_audio_finish(p->audio); }
}
JNIEXPORT jboolean JNICALL Java_com_utun_chat_data_NativeLib_nativeStreamPlaybackEmpty(JNIEnv *env, jobject obj, jlong handle) {

5
tools/chatgui-android/libutun_lite/stream_bridge.c

@ -264,6 +264,9 @@ static void media_process(void *arg) {
if (packet.kind == STREAM_MEDIA_READ_END) media_close(&viewer, 5);
else media_frame(&viewer, &packet.format, packet.kind == STREAM_MEDIA_READ_VIDEO ? &packet.video : NULL,
packet.kind == STREAM_MEDIA_READ_AUDIO ? &packet.audio : NULL);
} else if (result == STREAM_MORE) {
viewer.want_read = 1;
if (media_schedule() < 0) DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "Android media assembly scheduling failed");
} else if (result == STREAM_WAIT) viewer.waiting = 1;
else if (result == STREAM_GAP || result == STREAM_EXPIRED) {
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "Android playback resync id=%llu result=%d", (unsigned long long)viewer.id, result);
@ -296,7 +299,7 @@ static void media_process(void *arg) {
}
}
if (publisher.finished && now >= publisher.drain_until) media_close(&publisher, 5);
if (video_queue.head || audio_queue.head || publisher.finished) {
if (!media_post && (video_queue.head || audio_queue.head || publisher.finished)) {
media_timer = uasync_set_timeout(media_inst->ua, publisher.finished ? 200 : 50, NULL, media_process, "android_stream");
if (!media_timer) { DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "Android media timer allocation failed"); media_close(&publisher, 6); }
}

Loading…
Cancel
Save