diff --git a/buffer_lock.c b/buffer_lock.c index 4f55494..5ba2438 100644 --- a/buffer_lock.c +++ b/buffer_lock.c @@ -1,5 +1,43 @@ #include "buffer_lock.h" +bool buffer_lock_is_used(buffer_lock_t *buf_lock) +{ + int refs = 0; + + pthread_mutex_lock(&buf_lock->lock); + refs = buf_lock->refs; + pthread_mutex_unlock(&buf_lock->lock); + + return refs; +} + +void buffer_lock_use(buffer_lock_t *buf_lock, int ref) +{ + pthread_mutex_lock(&buf_lock->lock); + buf_lock->refs += ref; + pthread_mutex_unlock(&buf_lock->lock); +} + +bool buffer_lock_needs_buffer(buffer_lock_t *buf_lock) +{ + struct timeval now; + gettimeofday(&now, NULL); + bool needs_buffer = false; + + pthread_mutex_lock(&buf_lock->lock); + if (now.tv_sec - buf_lock->buf_time.tv_sec > 1) { + buffer_consumed(buf_lock->buf); + buf_lock->buf = NULL; + needs_buffer = true; + } + if (buf_lock->refs > 0) { + needs_buffer = true; + } + pthread_mutex_unlock(&buf_lock->lock); + + return needs_buffer; +} + void buffer_lock_capture(buffer_lock_t *buf_lock, buffer_t *buf) { pthread_mutex_lock(&buf_lock->lock); @@ -7,6 +45,7 @@ void buffer_lock_capture(buffer_lock_t *buf_lock, buffer_t *buf) buffer_use(buf); buf_lock->buf = buf; buf_lock->counter++; + gettimeofday(&buf_lock->buf_time, NULL); E_LOG_DEBUG(buf_lock, "Captured HTTP snapshot: %d", buf_lock->counter); pthread_cond_broadcast(&buf_lock->cond_wait); pthread_mutex_unlock(&buf_lock->lock); @@ -22,7 +61,7 @@ buffer_t *buffer_lock_get(buffer_lock_t *buf_lock, int timeout_s, int *counter) timeout.tv_sec = now.tv_sec + timeout_s; pthread_mutex_lock(&buf_lock->lock); - if (*counter == buf_lock->counter && timeout_s > 0) { + if (*counter == buf_lock->counter || !buf_lock->buf) { int ret = pthread_cond_timedwait(&buf_lock->cond_wait, &buf_lock->lock, &timeout); if (ret == ETIMEDOUT) { goto ret; diff --git a/buffer_lock.h b/buffer_lock.h index e95f65e..acb7857 100644 --- a/buffer_lock.h +++ b/buffer_lock.h @@ -9,10 +9,15 @@ typedef struct buffer_lock_s { pthread_mutex_t lock; pthread_cond_t cond_wait; buffer_t *buf; + struct timeval buf_time; int counter; + int refs; } buffer_lock_t; #define DEFINE_BUFFER_LOCK(name) static buffer_lock_t name = { #name, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, NULL, 0 }; void buffer_lock_capture(buffer_lock_t *buf_lock, buffer_t *buf); buffer_t *buffer_lock_get(buffer_lock_t *buf_lock, int timeout_s, int *counter); +bool buffer_lock_needs_buffer(buffer_lock_t *buf_lock); +void buffer_lock_use(buffer_lock_t *buf_lock, int ref); +bool buffer_lock_is_used(buffer_lock_t *buf_lock); diff --git a/http.h b/http.h index e609834..6a5dc71 100644 --- a/http.h +++ b/http.h @@ -36,7 +36,10 @@ void http_404(http_worker_t *worker, FILE *stream); void http_snapshot(http_worker_t *worker, FILE *stream); void http_stream(http_worker_t *worker, FILE *stream); void http_jpeg_capture(struct buffer_s *buf); +bool http_jpeg_needs_buffer(); // H264 void http_h264_capture(buffer_t *buf); void http_video(http_worker_t *worker, FILE *stream); +bool http_h264_needs_buffer(); + diff --git a/http_h264.c b/http_h264.c index 30360e0..efe0ae6 100644 --- a/http_h264.c +++ b/http_h264.c @@ -20,6 +20,11 @@ void http_h264_capture(buffer_t *buf) buffer_lock_capture(&http_h264, buf); } +bool http_h264_needs_buffer() +{ + return buffer_lock_needs_buffer(&http_h264); +} + void http_video(http_worker_t *worker, FILE *stream) { bool had_key_frame = false; diff --git a/http_jpeg.c b/http_jpeg.c index c9a9c60..8309575 100644 --- a/http_jpeg.c +++ b/http_jpeg.c @@ -29,6 +29,10 @@ static const char *const STREAM_PART = "Content-Type: " CONTENT_TYPE "\r\n" CONT static const char *const STREAM_BOUNDARY = "\r\n" "--" PART_BOUNDARY "\r\n"; +bool http_jpeg_needs_buffer() +{ + return buffer_lock_needs_buffer(&http_jpeg); +} void http_jpeg_capture(buffer_t *buf) { diff --git a/main.c b/main.c index 5dcce7f..d471b02 100644 --- a/main.c +++ b/main.c @@ -100,7 +100,7 @@ int open_camera() bool check_streaming() { - return true; + return http_jpeg_needs_buffer() || http_h264_needs_buffer(); } void write_h264(buffer_t *buf) @@ -117,7 +117,7 @@ int main(int argc, char *argv[]) { camera, { isp_srgb }, - { NULL, NULL } + { NULL, check_streaming } }, { isp_yuuv, @@ -138,12 +138,12 @@ int main(int argc, char *argv[]) { codec_jpeg, { }, - { http_jpeg_capture, check_streaming } + { http_jpeg_capture, http_jpeg_needs_buffer } }, { codec_h264, { }, - { http_h264_capture, check_streaming } + { http_h264_capture, http_h264_needs_buffer } }, { NULL } };