diff --git a/device/buffer.h b/device/buffer.h index 85418f2..f1e0b70 100644 --- a/device/buffer.h +++ b/device/buffer.h @@ -19,6 +19,7 @@ typedef struct buffer_s { int dma_fd; struct { + bool is_keyed : 1; bool is_keyframe : 1; bool is_last : 1; } flags; diff --git a/device/buffer_list.c b/device/buffer_list.c index 595334f..284bf5b 100644 --- a/device/buffer_list.c +++ b/device/buffer_list.c @@ -100,11 +100,7 @@ int buffer_list_set_stream(buffer_list_t *buf_list, bool do_on) buf_list->streaming = do_on; if (!do_on) { - ARRAY_FOREACH(buffer_t*, queued_buf, buf_list->queued_bufs, buf_list->n_queued_bufs) { - buffer_consumed(*queued_buf, "stream stop"); - *queued_buf = NULL; - } - buf_list->n_queued_bufs = 0; + buffer_list_clear_queue(buf_list); } int enqueued = buffer_list_count_enqueued(buf_list); diff --git a/device/buffer_list.h b/device/buffer_list.h index e6e37e3..bfb03e7 100644 --- a/device/buffer_list.h +++ b/device/buffer_list.h @@ -26,7 +26,7 @@ typedef struct buffer_stats_s { int frames, dropped; } buffer_stats_t; -#define MAX_BUFFER_QUEUE 1 +#define MAX_BUFFER_QUEUE 4 typedef struct buffer_list_s { char *name; @@ -64,5 +64,6 @@ buffer_t *buffer_list_find_slot(buffer_list_t *buf_list); buffer_t *buffer_list_dequeue(buffer_list_t *buf_list); int buffer_list_count_enqueued(buffer_list_t *buf_list); int buffer_list_enqueue(buffer_list_t *buf_list, buffer_t *dma_buf); -bool buffer_list_push_to_queue(buffer_list_t *buf_list, buffer_t *dma_buf); +void buffer_list_clear_queue(buffer_list_t *buf_list); +bool buffer_list_push_to_queue(buffer_list_t *buf_list, buffer_t *dma_buf, int max_bufs); buffer_t *buffer_list_pop_from_queue(buffer_list_t *buf_list); diff --git a/device/buffer_queue.c b/device/buffer_queue.c index d1f92bf..e3f4337 100644 --- a/device/buffer_queue.c +++ b/device/buffer_queue.c @@ -197,6 +197,9 @@ buffer_t *buffer_list_dequeue(buffer_list_t *buf_list) if (buf_list->fmt.format == V4L2_PIX_FMT_H264) { buffer_update_h264_key_frame(buf); + buf->flags.is_keyed = true; + } else { + buf->flags.is_keyed = false; } buf_list->stats.frames++; @@ -211,11 +214,22 @@ int buffer_list_pollfd(buffer_list_t *buf_list, struct pollfd *pollfd, bool can_ return buf_list->dev->hw->buffer_list_pollfd(buf_list, pollfd, can_dequeue); } -bool buffer_list_push_to_queue(buffer_list_t *buf_list, buffer_t *dma_buf) +void buffer_list_clear_queue(buffer_list_t *buf_list) { + ARRAY_FOREACH(buffer_t*, queued_buf, buf_list->queued_bufs, buf_list->n_queued_bufs) { + buffer_consumed(*queued_buf, "clear queue"); + *queued_buf = NULL; + } + buf_list->n_queued_bufs = 0; +} + +bool buffer_list_push_to_queue(buffer_list_t *buf_list, buffer_t *dma_buf, int max_bufs) +{ + max_bufs = MIN(max_bufs ? max_bufs : MAX_BUFFER_QUEUE, MAX_BUFFER_QUEUE); + if (buf_list->dev->paused) return true; - if (buf_list->n_queued_bufs >= MAX_BUFFER_QUEUE) + if (buf_list->n_queued_bufs >= max_bufs) return false; buffer_use(dma_buf); diff --git a/device/links.c b/device/links.c index cc8052b..2721d6f 100644 --- a/device/links.c +++ b/device/links.c @@ -11,6 +11,8 @@ #define CAPTURE_TIMEOUT_US (1000*1000) #define N_FDS 50 +#define MAX_QUEUED_ON_KEYED MAX_BUFFER_QUEUE +#define MAX_QUEUED_ON_NON_KEYED 1 #define MAX_CAPTURED_ON_CAMERA 2 #define MAX_CAPTURED_ON_M2M 2 @@ -252,11 +254,16 @@ static int links_enqueue_from_capture_list(buffer_list_t *capture_list, link_t * bool dropped = false; + int max_bufs_queued = buf->flags.is_keyed ? MAX_QUEUED_ON_KEYED : MAX_QUEUED_ON_NON_KEYED; + for (int j = 0; j < link->n_output_lists; j++) { if (link->output_lists[j]->dev->paused) { continue; } - if (!buffer_list_push_to_queue(link->output_lists[j], buf)) { + if (buf->flags.is_keyframe) { + buffer_list_clear_queue(link->output_lists[j]); + } + if (!buffer_list_push_to_queue(link->output_lists[j], buf, max_bufs_queued)) { dropped = true; } }