diff --git a/RELEASE.md b/RELEASE.md index 11720b6..ba4da8e 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -7,6 +7,7 @@ - libcamera: do not expose some options that should not be made configurable - http: add `/control` to provide simple JS interface to live edit camera settings - http: change `/option` to accept `device=`, `key=`, and `value=` +- device: show stddev estimates to measure frame pacing ## Variants diff --git a/device/buffer_list.h b/device/buffer_list.h index 22fe9d7..26dc950 100644 --- a/device/buffer_list.h +++ b/device/buffer_list.h @@ -24,6 +24,11 @@ typedef struct buffer_format_s { typedef struct buffer_stats_s { int frames, dropped; + + int frames_since_reset; + uint64_t max_dequeued_us; + float avg_dequeued_us; + float stddev_dequeued_us; } buffer_stats_t; #define MAX_BUFFER_QUEUE 4 diff --git a/device/buffer_queue.c b/device/buffer_queue.c index e3f4337..06f0a4b 100644 --- a/device/buffer_queue.c +++ b/device/buffer_queue.c @@ -171,6 +171,10 @@ buffer_t *buffer_list_dequeue(buffer_list_t *buf_list) goto error; } + uint64_t dequeued_us = 0; + if (buf_list->last_dequeued_us > 0) + dequeued_us = get_monotonic_time_us(NULL, NULL) - buf_list->last_dequeued_us; + buf_list->last_dequeued_us = get_monotonic_time_us(NULL, NULL); buf_list->last_capture_time_us = buf_list->last_dequeued_us - buf->captured_time_us; buf_list->last_in_queue_time_us = buf_list->last_dequeued_us - buf->enqueue_time_us; @@ -203,6 +207,18 @@ buffer_t *buffer_list_dequeue(buffer_list_t *buf_list) } buf_list->stats.frames++; + + float old_average = buf_list->stats.avg_dequeued_us; + float old_sum = buf_list->stats.avg_dequeued_us * buf_list->stats.frames_since_reset; + float old_stddev_sum = buf_list->stats.stddev_dequeued_us * buf_list->stats.stddev_dequeued_us * buf_list->stats.frames_since_reset; + + buf_list->stats.frames_since_reset++; + if (dequeued_us > buf_list->stats.max_dequeued_us) + buf_list->stats.max_dequeued_us = dequeued_us; + buf_list->stats.avg_dequeued_us = (float)(old_sum + dequeued_us) / buf_list->stats.frames_since_reset; + buf_list->stats.stddev_dequeued_us = sqrt( + ( old_stddev_sum + (dequeued_us - old_average) * (dequeued_us - buf_list->stats.avg_dequeued_us) + ) / buf_list->stats.frames_since_reset); return buf; error: diff --git a/device/links.c b/device/links.c index 511cddf..31f47cd 100644 --- a/device/links.c +++ b/device/links.c @@ -425,12 +425,15 @@ static void links_refresh_stats(link_t *all_links, uint64_t *last_refresh_us) buffer_stats_t *now = &capture_list->stats; buffer_stats_t *prev = &capture_list->stats_last; - printf(" [%8s %2d FPS/%2d D/%3dms/%3dms/%c/Q%d:O%d:C%d]", + printf(" [%8s %2d FPS/%2d D/%3dms/%3dms/Dev%3.fms/%c/Q%d:O%d:C%d]", capture_list->dev->name, (now->frames - prev->frames) / log_options.stats, (now->dropped - prev->dropped) / log_options.stats, capture_list->last_capture_time_us > 0 ? capture_list->last_capture_time_us / 1000 : -1, capture_list->last_in_queue_time_us > 0 ? capture_list->last_in_queue_time_us / 1000 : -1, + // (float)(now->max_dequeued_us / 1000), + // (float)(now->avg_dequeued_us / 1000), + (float)(now->stddev_dequeued_us / 1000), capture_list->streaming ? (capture_list->dev->paused ? 'P' : 'S') : 'X', capture_list->dev->output_list ? capture_list->dev->output_list->n_queued_bufs : 0, capture_list->dev->output_list ? buffer_list_count_enqueued(capture_list->dev->output_list) : 0, @@ -446,6 +449,11 @@ static void links_refresh_stats(link_t *all_links, uint64_t *last_refresh_us) buffer_list_t *capture_list = all_links[i].capture_list; capture_list->stats_last = capture_list->stats; + capture_list->stats.max_dequeued_us = 0; + capture_list->stats.avg_dequeued_us = 0; + capture_list->stats.stddev_dequeued_us = 0; + capture_list->stats.frames_since_reset = 0; + if (now_us - capture_list->last_dequeued_us > 1000) { capture_list->last_capture_time_us = 0; capture_list->last_in_queue_time_us = 0;