From 6c628cfe720a3508f59862fba112692cc6bc3045 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 4 Apr 2022 22:52:31 +0200 Subject: [PATCH] Fix buffer re-use on short streaming --- buffer.c | 4 ---- buffer_list.c | 22 +++++++++++++++++++++- http_h264.c | 7 ++++++- http_jpeg.c | 21 +++++++++++++++++---- 4 files changed, 44 insertions(+), 10 deletions(-) diff --git a/buffer.c b/buffer.c index dd57b4c..12e42c7 100644 --- a/buffer.c +++ b/buffer.c @@ -53,10 +53,6 @@ buffer_t *buffer_open(const char *name, buffer_list_t *buf_list, int index) { buf->dma_fd = v4l2_exp.fd; } - if (buf_list->do_capture) { - buffer_consumed(buf); - } - return buf; error: diff --git a/buffer_list.c b/buffer_list.c index 85f5a67..7e061e4 100644 --- a/buffer_list.c +++ b/buffer_list.c @@ -167,8 +167,28 @@ int buffer_list_stream(buffer_list_t *buf_list, bool do_on) E_XIOCTL(buf_list, buf_list->device->fd, do_on ? VIDIOC_STREAMON : VIDIOC_STREAMOFF, &type, "Cannot set streaming state"); buf_list->streaming = do_on; - E_LOG_DEBUG(buf_list, "Streaming %s...", do_on ? "started" : "stopped"); + for (int i = 0; i < buf_list->nbufs; i++) { + buffer_t *buf = buf_list->bufs[i]; + // dequeue buffers (when stream off) + if (buf->enqueued) { + if (buf->mmap_source) { + buf->mmap_source->used = 0; + buffer_consumed(buf->mmap_source); + buf->mmap_source = NULL; + } + + buf->enqueued = false; + buf->mmap_reflinks = 1; + } + + // re-enqueue buffers on stream start + if (buf_list->streaming && buf_list->do_capture && !buf->enqueued && buf->mmap_reflinks == 1) { + buffer_consumed(buf); + } + } + + E_LOG_DEBUG(buf_list, "Streaming %s...", do_on ? "started" : "stopped"); return 0; error: diff --git a/http_h264.c b/http_h264.c index efe0ae6..b5e2e8a 100644 --- a/http_h264.c +++ b/http_h264.c @@ -32,10 +32,12 @@ void http_video(http_worker_t *worker, FILE *stream) int counter = 0; fprintf(stream, VIDEO_HEADER); + buffer_lock_use(&http_h264, 1); + while (!feof(stream)) { buffer_t *buf = buffer_lock_get(&http_h264, 3, &counter); if (!buf) { - return; + goto error; } if (buf->v4l2_buffer.flags & V4L2_BUF_FLAG_KEYFRAME) { @@ -51,4 +53,7 @@ void http_video(http_worker_t *worker, FILE *stream) } buffer_consumed(buf); } + +error: + buffer_lock_use(&http_h264, -1); } diff --git a/http_jpeg.c b/http_jpeg.c index 8309575..cd166e7 100644 --- a/http_jpeg.c +++ b/http_jpeg.c @@ -42,6 +42,7 @@ void http_jpeg_capture(buffer_t *buf) void http_snapshot(http_worker_t *worker, FILE *stream) { int counter = 0; + buffer_lock_use(&http_jpeg, 1); buffer_t *buf = buffer_lock_get(&http_jpeg, 1, &counter); if (!buf) { @@ -56,25 +57,37 @@ void http_snapshot(http_worker_t *worker, FILE *stream) fprintf(stream, "\r\n"); fwrite(buf->start, buf->used, 1, stream); buffer_consumed(buf); +error: + buffer_lock_use(&http_jpeg, -1); } void http_stream(http_worker_t *worker, FILE *stream) { int counter = 0; fprintf(stream, STREAM_HEADER); + buffer_lock_use(&http_jpeg, 1); while (!feof(stream)) { buffer_t *buf = buffer_lock_get(&http_jpeg, 3, &counter); if (!buf) { fprintf(stream, STREAM_ERROR, -1, "No frames."); - return; + goto error; } - fprintf(stream, STREAM_PART, buf->used); - fwrite(buf->start, buf->used, 1, stream); - fprintf(stream, STREAM_BOUNDARY); + if (!fprintf(stream, STREAM_PART, buf->used)) { + goto error; + } + if (!fwrite(buf->start, buf->used, 1, stream)) { + goto error; + } + if (!fprintf(stream, STREAM_BOUNDARY)) { + goto error; + } buffer_consumed(buf); } + +error: + buffer_lock_use(&http_jpeg, -1); }