Browse Source

Expose non-destructive jitter buffer diagnostic snapshots

master
evgeny 6 days ago
parent
commit
e53ea2e04a
  1. 11
      src/call/call_audio.c
  2. 15
      src/call/call_jitter.cpp
  3. 5
      src/call/call_jitter.h

11
src/call/call_audio.c

@ -571,7 +571,7 @@ int call_audio_get_stats(uint64_t call_id, int* buffer_ms, int* tempo_x100,
pthread_mutex_lock(&g_mtx); pthread_mutex_lock(&g_mtx);
if (g_active && call_id == g_call_id && g_vj) { if (g_active && call_id == g_call_id && g_vj) {
call_jitter_get_stats(g_vj, buffer_ms, tempo_x100, dropped, underruns, range); call_jitter_get_stats(g_vj, buffer_ms, tempo_x100, dropped, underruns, range);
call_jitter_take_diagnostics(g_vj, &diagnostics); call_jitter_get_diagnostics(g_vj, &diagnostics, 1);
speex_aec_get_stats(g_aec, &aec_over, &aec_under); speex_aec_get_stats(g_aec, &aec_over, &aec_under);
aec_changed = aec_over != g_aec_reported_over || aec_under != g_aec_reported_under; aec_changed = aec_over != g_aec_reported_over || aec_under != g_aec_reported_under;
g_aec_reported_over = aec_over; g_aec_reported_under = aec_under; g_aec_reported_over = aec_over; g_aec_reported_under = aec_under;
@ -592,8 +592,11 @@ int call_audio_get_stats(uint64_t call_id, int* buffer_ms, int* tempo_x100,
diagnostics.decode_errors, diagnostics.error_result, diagnostics.error_len, diagnostics.budget_hits, diagnostics.depth_ms); diagnostics.decode_errors, diagnostics.error_result, diagnostics.error_len, diagnostics.budget_hits, diagnostics.depth_ms);
if (events) DEBUG_INFO(DEBUG_CATEGORY_CALL, "%s: PCM first=%d resumed=%d gap=%d tone_started=%d tone_stopped=%d", CALL_AUDIO_ID, if (events) DEBUG_INFO(DEBUG_CATEGORY_CALL, "%s: PCM first=%d resumed=%d gap=%d tone_started=%d tone_stopped=%d", CALL_AUDIO_ID,
!!(events & 1), !!(events & 2), !!(events & 4), !!(events & 16), !!(events & 8)); !!(events & 1), !!(events & 2), !!(events & 4), !!(events & 16), !!(events & 8));
if (ok) DEBUG_DEBUG(DEBUG_CATEGORY_CALL, "call_jitter: depth=%dms reserve=%dms tempo=%d waiting=%d catching_up=%d resumed=%d", if (ok) DEBUG_DEBUG(DEBUG_CATEGORY_CALL,
diagnostics.depth_ms, diagnostics.reserve_ms, diagnostics.tempo_x100, diagnostics.waiting, "call_jitter: call=%llu depth=%dms reserve=%dms encoded=%dms processing=%dms spread=%lldms pcm=%d "
diagnostics.catching_up, diagnostics.resumed); "tempo=%d waiting=%d catching_up=%d resumed=%d underruns=%u",
(unsigned long long)call_id, diagnostics.depth_ms, diagnostics.reserve_ms, diagnostics.encoded_ms,
diagnostics.processing_ms, (long long)diagnostics.arrival_spread_ms, diagnostics.pcm_samples,
diagnostics.tempo_x100, diagnostics.waiting, diagnostics.catching_up, diagnostics.resumed, diagnostics.underruns);
return ok ? 0 : -1; return ok ? 0 : -1;
} }

15
src/call/call_jitter.cpp

@ -133,6 +133,7 @@ int call_jitter_pull(struct call_jitter* j, int16_t* out, int max_samples) {
std::lock_guard<std::mutex> lock(j->mtx); std::lock_guard<std::mutex> lock(j->mtx);
j->diagnostics.depth_ms = (int)depth; j->diagnostics.reserve_ms = reserve; j->diagnostics.depth_ms = (int)depth; j->diagnostics.reserve_ms = reserve;
j->diagnostics.tempo_x100 = j->tempo_x100; j->diagnostics.waiting = 1; j->diagnostics.tempo_x100 = j->tempo_x100; j->diagnostics.waiting = 1;
j->diagnostics.pcm_samples = 0;
return 0; return 0;
} }
j->primed = true; j->primed = true;
@ -198,6 +199,7 @@ int call_jitter_pull(struct call_jitter* j, int16_t* out, int max_samples) {
j->diagnostics.resumed |= resumed; j->diagnostics.resumed |= resumed;
j->diagnostics.catching_up = catching; j->diagnostics.catching_up = catching;
j->diagnostics.waiting = n < max_samples; j->diagnostics.waiting = n < max_samples;
j->diagnostics.pcm_samples = n;
} }
if (n < max_samples) { if (n < max_samples) {
j->primed = false; j->primed = false;
@ -205,11 +207,18 @@ int call_jitter_pull(struct call_jitter* j, int16_t* out, int max_samples) {
return n; return n;
} }
void call_jitter_take_diagnostics(struct call_jitter* j, struct call_jitter_diagnostics* out) { void call_jitter_get_diagnostics(struct call_jitter* j, struct call_jitter_diagnostics* out, int reset_events) {
std::lock_guard<std::mutex> lock(j->mtx); std::lock_guard<std::mutex> lock(j->mtx);
*out = j->diagnostics; *out = j->diagnostics;
j->diagnostics.decode_errors = j->diagnostics.budget_hits = 0; out->encoded_ms = j->count * CALL_JITTER_FRAME_MS;
j->diagnostics.resumed = 0; out->processing_ms = j->processing_ms;
out->reserve_ms = j->arrival_window.reserve;
out->arrival_spread_ms = j->arrival_window.high - j->arrival_window.low;
out->underruns = j->underruns;
if (reset_events) {
j->diagnostics.decode_errors = j->diagnostics.budget_hits = 0;
j->diagnostics.resumed = 0;
}
} }
void call_jitter_silence(struct call_jitter* j, unsigned samples) { void call_jitter_silence(struct call_jitter* j, unsigned samples) {

5
src/call/call_jitter.h

@ -20,9 +20,12 @@ struct call_jitter_diagnostics {
int depth_ms, reserve_ms, tempo_x100, error_result, error_len; int depth_ms, reserve_ms, tempo_x100, error_result, error_len;
uint32_t decode_errors, budget_hits; uint32_t decode_errors, budget_hits;
int resumed, catching_up, waiting; int resumed, catching_up, waiting;
int encoded_ms, processing_ms, pcm_samples;
int64_t arrival_spread_ms;
uint32_t underruns;
}; };
/* Снимок и сброс событий под mutex; логировать после выхода из mutex голосового стека. */ /* Снимок и сброс событий под mutex; логировать после выхода из mutex голосового стека. */
void call_jitter_take_diagnostics(struct call_jitter*, struct call_jitter_diagnostics*); void call_jitter_get_diagnostics(struct call_jitter*, struct call_jitter_diagnostics*, int reset_events);
struct call_jitter* call_jitter_create(call_jitter_decode_fn decode, void* arg, int max_reserve_ms); struct call_jitter* call_jitter_create(call_jitter_decode_fn decode, void* arg, int max_reserve_ms);
void call_jitter_destroy(struct call_jitter* j); void call_jitter_destroy(struct call_jitter* j);
/* sent_ms — timestamp кадра на проводе (uint32 с переполнением), received_ms — локальные монотонные часы. /* sent_ms — timestamp кадра на проводе (uint32 с переполнением), received_ms — локальные монотонные часы.

Loading…
Cancel
Save