From c05457ce2f485f4bc0ec5cf56cc52b3a736752b2 Mon Sep 17 00:00:00 2001 From: Devaev Maxim Date: Sun, 17 Mar 2019 19:33:56 +0300 Subject: [PATCH] separate hw_buffer_t size and allocated --- src/device.c | 34 ++++++++++++++++++++-------------- src/device.h | 10 ++++++---- src/stream.c | 20 ++++++++++---------- src/stream.h | 1 - src/tools.h | 1 - 5 files changed, 36 insertions(+), 30 deletions(-) diff --git a/src/device.c b/src/device.c index a28667e..4c075b8 100644 --- a/src/device.c +++ b/src/device.c @@ -177,8 +177,8 @@ void device_close(struct device_t *dev) { for (unsigned index = 0; index < dev->run->n_buffers; ++index) { # define HW_BUFFER(_next) dev->run->hw_buffers[index]._next - if (HW_BUFFER(size) > 0 && HW_BUFFER(data) != MAP_FAILED) { - if (munmap(HW_BUFFER(data), HW_BUFFER(size)) < 0) { + if (HW_BUFFER(allocated) > 0 && HW_BUFFER(data) != MAP_FAILED) { + if (munmap(HW_BUFFER(data), HW_BUFFER(allocated)) < 0) { LOG_PERROR("Can't unmap device buffer %u", index); } } @@ -219,31 +219,37 @@ int device_switch_capturing(struct device_t *dev, bool enable) { return 0; } -int device_grab_buffer(struct device_t *dev, struct v4l2_buffer *buf_info) { - MEMSET_ZERO_PTR(buf_info); - buf_info->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf_info->memory = V4L2_MEMORY_MMAP; +int device_grab_buffer(struct device_t *dev) { + struct v4l2_buffer buf_info; + + MEMSET_ZERO(buf_info); + buf_info.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf_info.memory = V4L2_MEMORY_MMAP; LOG_DEBUG("Calling ioctl(VIDIOC_DQBUF) ..."); - if (xioctl(dev->run->fd, VIDIOC_DQBUF, buf_info) < 0) { + if (xioctl(dev->run->fd, VIDIOC_DQBUF, &buf_info) < 0) { LOG_PERROR("Unable to dequeue buffer"); return -1; } - LOG_DEBUG("Got a new frame in buffer index=%u; bytesused=%u", buf_info->index, buf_info->bytesused); - if (buf_info->index >= dev->run->n_buffers) { - LOG_ERROR("Got invalid buffer index=%u; nbuffers=%u", buf_info->index, dev->run->n_buffers); + LOG_DEBUG("Got a new frame in buffer index=%u; bytesused=%u", buf_info.index, buf_info.bytesused); + if (buf_info.index >= dev->run->n_buffers) { + LOG_ERROR("Got invalid buffer index=%u; nbuffers=%u", buf_info.index, dev->run->n_buffers); return -1; } - return 0; + + dev->run->hw_buffers[buf_info.index].size = buf_info.bytesused; + memcpy(&dev->run->hw_buffers[buf_info.index].buf_info, &buf_info, sizeof(struct v4l2_buffer)); + return buf_info.index; } -int device_release_buffer(struct device_t *dev, struct v4l2_buffer *buf_info) { +int device_release_buffer(struct device_t *dev, unsigned index) { LOG_DEBUG("Calling ioctl(VIDIOC_QBUF) ..."); - if (xioctl(dev->run->fd, VIDIOC_QBUF, buf_info) < 0) { + if (xioctl(dev->run->fd, VIDIOC_QBUF, &dev->run->hw_buffers[index].buf_info) < 0) { LOG_PERROR("Unable to requeue buffer"); return -1; } + dev->run->hw_buffers[index].size = 0; return 0; } @@ -462,7 +468,7 @@ static int _device_open_mmap(struct device_t *dev) { LOG_PERROR("Can't map device buffer %u", dev->run->n_buffers); return -1; } - HW_BUFFER(size) = buf_info.length; + HW_BUFFER(allocated) = buf_info.length; # undef HW_BUFFER } diff --git a/src/device.h b/src/device.h index 1d16284..966b8c0 100644 --- a/src/device.h +++ b/src/device.h @@ -42,8 +42,10 @@ struct hw_buffer_t { - unsigned char *data; - size_t size; + unsigned char *data; + size_t size; + size_t allocated; + struct v4l2_buffer buf_info; }; struct picture_t { @@ -118,6 +120,6 @@ int device_open(struct device_t *dev); void device_close(struct device_t *dev); int device_switch_capturing(struct device_t *dev, bool enable); -int device_grab_buffer(struct device_t *dev, struct v4l2_buffer *buf_info); -int device_release_buffer(struct device_t *dev, struct v4l2_buffer *buf_info); +int device_grab_buffer(struct device_t *dev); +int device_release_buffer(struct device_t *dev, unsigned index); int device_consume_event(struct device_t *dev); diff --git a/src/stream.c b/src/stream.c index c29a6fc..6fd5585 100644 --- a/src/stream.c +++ b/src/stream.c @@ -186,22 +186,23 @@ void stream_loop(struct stream_t *stream) { if (FD_ISSET(stream->dev->run->fd, &read_fds)) { LOG_DEBUG("Frame is ready"); - struct v4l2_buffer buf_info; + int buf_index; long double now = get_now_monotonic(); long long now_second = floor_ms(now); - if (device_grab_buffer(stream->dev, &buf_info) < 0) { + if ((buf_index = device_grab_buffer(stream->dev)) < 0) { break; } - stream->dev->run->pictures[buf_info.index].grab_time = now; + stream->dev->run->pictures[buf_index].grab_time = now; // Workaround for broken, corrupted frames: // Under low light conditions corrupted frames may get captured. // The good thing is such frames are quite small compared to the regular pictures. // For example a VGA (640x480) webcam picture is normally >= 8kByte large, // corrupted frames are smaller. - if (buf_info.bytesused < stream->dev->min_frame_size) { - LOG_DEBUG("Dropping too small frame sized %u bytes, assuming it as broken", buf_info.bytesused); + if (stream->dev->run->hw_buffers[buf_index].size < stream->dev->min_frame_size) { + LOG_DEBUG("Dropping too small frame sized %zu bytes, assuming it as broken", + stream->dev->run->hw_buffers[buf_index].size); goto pass_frame; } @@ -229,8 +230,7 @@ void stream_loop(struct stream_t *stream) { # define FREE_WORKER(_next) pool.workers[free_worker_number]._next - LOG_DEBUG("Grabbed a new frame to buffer %u", buf_info.index); - FREE_WORKER(buf_info) = buf_info; + LOG_DEBUG("Grabbed a new frame to buffer %u", buf_index); if (!oldest_worker) { oldest_worker = &pool.workers[free_worker_number]; @@ -249,7 +249,7 @@ void stream_loop(struct stream_t *stream) { last_worker->order_next = NULL; A_MUTEX_LOCK(&FREE_WORKER(has_job_mutex)); - FREE_WORKER(buf_index) = buf_info.index; + FREE_WORKER(buf_index) = buf_index; atomic_store(&FREE_WORKER(has_job), true); A_MUTEX_UNLOCK(&FREE_WORKER(has_job_mutex)); A_COND_SIGNAL(&FREE_WORKER(has_job_cond)); @@ -264,7 +264,7 @@ void stream_loop(struct stream_t *stream) { pass_frame: - if (device_release_buffer(stream->dev, &buf_info) < 0) { + if (device_release_buffer(stream->dev, buf_index) < 0) { break; } } @@ -457,7 +457,7 @@ static void *_stream_worker_thread(void *v_worker) { } PICTURE(encode_end_time) = get_now_monotonic(); - if (device_release_buffer(worker->dev, &worker->buf_info) == 0) { + if (device_release_buffer(worker->dev, worker->buf_index) == 0) { worker->job_start_time = PICTURE(encode_begin_time); atomic_store(&worker->has_job, false); diff --git a/src/stream.h b/src/stream.h index 5f98b63..5503c5d 100644 --- a/src/stream.h +++ b/src/stream.h @@ -42,7 +42,6 @@ struct worker_t { pthread_mutex_t has_job_mutex; int buf_index; - struct v4l2_buffer buf_info; atomic_bool has_job; bool job_failed; long double job_start_time; diff --git a/src/tools.h b/src/tools.h index 9e75dbf..68812e3 100644 --- a/src/tools.h +++ b/src/tools.h @@ -51,7 +51,6 @@ #define A_CALLOC(_dest, _nmemb) assert((_dest = calloc(_nmemb, sizeof(*(_dest))))) #define A_REALLOC(_dest, _nmemb) assert((_dest = realloc(_dest, _nmemb * sizeof(*(_dest))))) #define MEMSET_ZERO(_obj) memset(&(_obj), 0, sizeof(_obj)) -#define MEMSET_ZERO_PTR(_ptr) memset(_ptr, 0, sizeof(*(_ptr))) #define ARRAY_LEN(_array) (sizeof(_array) / sizeof(_array[0]))