diff --git a/device/buffer_list.c b/device/buffer_list.c index 284bf5b..3caf213 100644 --- a/device/buffer_list.c +++ b/device/buffer_list.c @@ -99,7 +99,9 @@ int buffer_list_set_stream(buffer_list_t *buf_list, bool do_on) } buf_list->streaming = do_on; - if (!do_on) { + if (do_on) { + buf_list->last_enqueued_us = get_monotonic_time_us(NULL, NULL); + } else { buffer_list_clear_queue(buf_list); } diff --git a/device/links.c b/device/links.c index 2721d6f..511cddf 100644 --- a/device/links.c +++ b/device/links.c @@ -9,6 +9,7 @@ #include #define CAPTURE_TIMEOUT_US (1000*1000) +#define STALE_TIMEOUT_US (1000*1000*1000) #define N_FDS 50 #define MAX_QUEUED_ON_KEYED MAX_BUFFER_QUEUE @@ -93,14 +94,19 @@ static void links_process_paused(link_t *all_links, bool force_active) static bool links_enqueue_capture_buffers(buffer_list_t *capture_list, int *timeout_next_ms) { buffer_t *capture_buf = NULL; + uint64_t now_us = get_monotonic_time_us(NULL, NULL); + + if (now_us - capture_list->last_enqueued_us > STALE_TIMEOUT_US && capture_list->dev->output_list == NULL) { + LOG_INFO(capture_list, "Stale detected. Restarting streaming..."); + buffer_list_set_stream(capture_list, false); + buffer_list_set_stream(capture_list, true); + } // skip if all enqueued capture_buf = buffer_list_find_slot(capture_list); if (capture_buf == NULL) return false; - uint64_t now_us = get_monotonic_time_us(NULL, NULL); - // skip if trying to enqueue to fast if (capture_list->fmt.interval_us > 0 && now_us - capture_list->last_enqueued_us < capture_list->fmt.interval_us) { *timeout_next_ms = MIN(*timeout_next_ms, (capture_list->last_enqueued_us + capture_list->fmt.interval_us - now_us) / 1000); diff --git a/device/v4l2/buffer.c b/device/v4l2/buffer.c index 0e29bef..5de5efa 100644 --- a/device/v4l2/buffer.c +++ b/device/v4l2/buffer.c @@ -181,3 +181,35 @@ int v4l2_buffer_list_pollfd(buffer_list_t *buf_list, struct pollfd *pollfd, bool pollfd->revents = 0; return 0; } + +void v4l2_buffer_list_check_buffer(buffer_t *buf) +{ + struct v4l2_buffer v4l2_buf = {0}; + struct v4l2_plane v4l2_plane = {0}; + + v4l2_buf.type = buf->buf_list->v4l2->type; + v4l2_buf.index = buf->index; + v4l2_buf.flags = 0; + + if (buf->buf_list->v4l2->do_mplanes) { + v4l2_buf.length = 1; + v4l2_buf.m.planes = &v4l2_plane; + v4l2_plane.data_offset = 0; + } + + ERR_IOCTL(buf, buf->buf_list->v4l2->dev_fd, VIDIOC_QUERYBUF, &v4l2_buf, "Can't query buffer"); + + LOG_INFO(buf, "Buffer queried. Queued=%d/%d", + (v4l2_buf.flags & V4L2_BUF_FLAG_QUEUED) != 0, + buf->enqueued + ); + +error:; +} + +void v4l2_buffer_list_check_buffers(buffer_list_t *buf_list) +{ + ARRAY_FOREACH(buffer_t*, buf, buf_list->bufs, buf_list->nbufs) { + v4l2_buffer_list_check_buffer(*buf); + } +}