diff --git a/cmd/camera.c b/cmd/camera.c index 98e95fa..b8b2a09 100644 --- a/cmd/camera.c +++ b/cmd/camera.c @@ -58,6 +58,11 @@ camera_t *camera_open(camera_options_t *options) } camera->camera->capture_list->do_timestamps = true; + if (camera->options.fps > 0) { + camera->camera->capture_list->fmt_interval_us = 1000 * 1000 / camera->options.fps; + printf("buffer_lock.c: frame interval: %d\n", camera->camera->capture_list->fmt_interval_us); + } + switch (camera->camera->capture_list->fmt_format) { case V4L2_PIX_FMT_YUYV: if (camera_configure_direct(camera) < 0) { diff --git a/hw/buffer_list.h b/hw/buffer_list.h index ef01e24..40d1510 100644 --- a/hw/buffer_list.h +++ b/hw/buffer_list.h @@ -15,9 +15,11 @@ typedef struct buffer_list_s { bool do_dma; bool do_capture; - unsigned fmt_width, fmt_height, fmt_format, fmt_bytesperline; + unsigned fmt_width, fmt_height, fmt_format, fmt_bytesperline, fmt_interval_us; bool do_timestamps; + uint64_t last_dequeued_us; + bool streaming; int frames; } buffer_list_t; diff --git a/hw/buffer_queue.c b/hw/buffer_queue.c index 5cb5c2a..cece078 100644 --- a/hw/buffer_queue.c +++ b/hw/buffer_queue.c @@ -180,6 +180,7 @@ buffer_t *buffer_list_dequeue(buffer_list_t *buf_list) } buf->v4l2_buffer.flags = v4l2_buf.flags; buf->v4l2_buffer.timestamp = v4l2_buf.timestamp; + buf_list->last_dequeued_us = get_monotonic_time_us(NULL, NULL); if (buf->mmap_reflinks > 0) { E_LOG_PERROR(buf, "Buffer appears to be enqueued? (links=%d)", buf->mmap_reflinks); diff --git a/hw/links.c b/hw/links.c index 24b3d42..631eca4 100644 --- a/hw/links.c +++ b/hw/links.c @@ -5,9 +5,10 @@ #define N_FDS 50 -int _build_fds(link_t *all_links, struct pollfd *fds, link_t **links, buffer_list_t **buf_lists, int max_n) +int _build_fds(link_t *all_links, struct pollfd *fds, link_t **links, buffer_list_t **buf_lists, int max_n, int *max_timeout_ms) { int n = 0, nlinks = 0; + uint64_t now_us = get_monotonic_time_us(NULL, NULL); for (nlinks = 0; all_links[nlinks].source; nlinks++); @@ -67,9 +68,20 @@ int _build_fds(link_t *all_links, struct pollfd *fds, link_t **links, buffer_lis int count_enqueued = buffer_list_count_enqueued(source); + bool can_dequeue = count_enqueued > 0; + int64_t since_last_us = now_us - source->last_dequeued_us; + if (since_last_us < source->fmt_interval_us) { + can_dequeue = false; + + int64_t since_last_ms = since_last_us / 1000; + if (since_last_ms < *max_timeout_ms) { + *max_timeout_ms = since_last_ms; + } + } + fds[n].fd = source->device->fd; fds[n].events = POLLHUP; - if (count_enqueued > 0) + if (can_dequeue) fds[n].events |= POLLIN; fds[n].revents = 0; buf_lists[n] = source; @@ -132,16 +144,16 @@ void print_pollfds(struct pollfd *fds, int n) printf("pollfds = %d\n", n); } -int links_step(link_t *all_links, int timeout) +int links_step(link_t *all_links, int timeout_ms) { struct pollfd fds[N_FDS] = {0}; link_t *links[N_FDS]; buffer_list_t *buf_lists[N_FDS]; buffer_t *buf; - int n = _build_fds(all_links, fds, links, buf_lists, N_FDS); + int n = _build_fds(all_links, fds, links, buf_lists, N_FDS, &timeout_ms); print_pollfds(fds, n); - int ret = poll(fds, n, timeout); + int ret = poll(fds, n, timeout_ms); print_pollfds(fds, n); if (ret < 0 && errno != EINTR) {