diff --git a/device/buffer_lock.c b/device/buffer_lock.c index a028af2..cccae11 100644 --- a/device/buffer_lock.c +++ b/device/buffer_lock.c @@ -42,7 +42,6 @@ bool buffer_lock_needs_buffer(buffer_lock_t *buf_lock) void buffer_lock_capture(buffer_lock_t *buf_lock, buffer_t *buf) { uint64_t now = get_monotonic_time_us(NULL, NULL); - uint64_t captured_time_us = buf ? get_time_us(CLOCK_FROM_PARAMS, NULL, &buf->v4l2_buffer.timestamp, 0) : 0; pthread_mutex_lock(&buf_lock->lock); if (!buf) { @@ -55,7 +54,7 @@ void buffer_lock_capture(buffer_lock_t *buf_lock, buffer_t *buf) E_LOG_DEBUG(buf_lock, "Dropped buffer %s (refs=%d), frame=%d/%d, frame_ms=%.1f", dev_name(buf), buf ? buf->mmap_reflinks : 0, buf_lock->counter, buf_lock->dropped, - (now - captured_time_us) / 1000.0f); + (now - buf->captured_time_us) / 1000.0f); } else { buffer_consumed(buf_lock->buf, buf_lock->name); buffer_use(buf); @@ -64,7 +63,7 @@ void buffer_lock_capture(buffer_lock_t *buf_lock, buffer_t *buf) E_LOG_DEBUG(buf_lock, "Captured buffer %s (refs=%d), frame=%d/%d, processing_ms=%.1f, frame_ms=%.1f", dev_name(buf), buf ? buf->mmap_reflinks : 0, buf_lock->counter, buf_lock->dropped, - (now - captured_time_us) / 1000.0f, + (now - buf->captured_time_us) / 1000.0f, (now - buf_lock->buf_time_us) / 1000.0f); buf_lock->buf_time_us = now; pthread_cond_broadcast(&buf_lock->cond_wait); diff --git a/device/hw/buffer.c b/device/hw/buffer.c index 1218e49..bdc8029 100644 --- a/device/hw/buffer.c +++ b/device/hw/buffer.c @@ -14,33 +14,38 @@ buffer_t *buffer_open(const char *name, buffer_list_t *buf_list, int index) { buf->mmap_reflinks = 1; buf->used = 0; - buf->v4l2_buffer.type = buf_list->v4l2.type; - buf->v4l2_buffer.index = index; + struct v4l2_buffer v4l2_buf = {0}; + struct v4l2_plane v4l2_plane = {0}; + + v4l2_buf.type = buf_list->v4l2.type; + v4l2_buf.index = index; if (buf_list->v4l2.do_mplanes) { - buf->v4l2_buffer.length = 1; - buf->v4l2_buffer.m.planes = &buf->v4l2_plane; - buf->v4l2_plane.data_offset = 0; + v4l2_buf.length = 1; + v4l2_buf.m.planes = &v4l2_plane; + v4l2_plane.data_offset = 0; } if (buf_list->do_mmap) { - buf->v4l2_buffer.memory = V4L2_MEMORY_MMAP; + v4l2_buf.memory = V4L2_MEMORY_MMAP; } else { - buf->v4l2_buffer.memory = V4L2_MEMORY_DMABUF; + v4l2_buf.memory = V4L2_MEMORY_DMABUF; } - E_XIOCTL(buf_list, dev->fd, VIDIOC_QUERYBUF, &buf->v4l2_buffer, "Cannot query buffer %d", index); + E_XIOCTL(buf_list, dev->fd, VIDIOC_QUERYBUF, &v4l2_buf, "Cannot query buffer %d", index); + + uint64_t mem_offset = 0; if (buf_list->v4l2.do_mplanes) { - buf->offset = buf->v4l2_plane.m.mem_offset; - buf->length = buf->v4l2_plane.length; + mem_offset = v4l2_plane.m.mem_offset; + buf->length = v4l2_plane.length; } else { - buf->offset = buf->v4l2_buffer.m.offset; - buf->length = buf->v4l2_buffer.length; + mem_offset = v4l2_buf.m.offset; + buf->length = v4l2_buf.length; } if (buf_list->do_mmap) { - buf->start = mmap(NULL, buf->length, PROT_READ | PROT_WRITE, MAP_SHARED, dev->fd, buf->offset); + buf->start = mmap(NULL, buf->length, PROT_READ | PROT_WRITE, MAP_SHARED, dev->fd, mem_offset); if (buf->start == MAP_FAILED) { goto error; } @@ -48,7 +53,7 @@ buffer_t *buffer_open(const char *name, buffer_list_t *buf_list, int index) { if (buf_list->do_dma) { struct v4l2_exportbuffer v4l2_exp = {0}; - v4l2_exp.type = buf_list->v4l2.type; + v4l2_exp.type = v4l2_buf.type; v4l2_exp.index = index; v4l2_exp.plane = 0; E_XIOCTL(buf_list, dev->fd, VIDIOC_EXPBUF, &v4l2_exp, "Can't export queue buffer=%u to DMA", index); diff --git a/device/hw/buffer.h b/device/hw/buffer.h index 9b40d6f..4505746 100644 --- a/device/hw/buffer.h +++ b/device/hw/buffer.h @@ -12,18 +12,22 @@ typedef struct buffer_s { char *name; struct buffer_list_s *buf_list; int index; + + // Mapped memory (with DMA) void *start; - size_t offset; size_t used; size_t length; - struct v4l2_buffer v4l2_buffer; - struct v4l2_plane v4l2_plane; int dma_fd; + struct { + unsigned flags; + } v4l2; + + // State int mmap_reflinks; - buffer_t *mmap_source; + buffer_t *dma_source; bool enqueued; - uint64_t enqueue_time_us; + uint64_t enqueue_time_us, captured_time_us; } buffer_t; buffer_t *buffer_open(const char *name, buffer_list_t *buf_list, int buffer); diff --git a/device/hw/buffer_list.c b/device/hw/buffer_list.c index 3c4f758..6e961d7 100644 --- a/device/hw/buffer_list.c +++ b/device/hw/buffer_list.c @@ -229,37 +229,3 @@ int buffer_list_set_stream(buffer_list_t *buf_list, bool do_on) error: return -1; } - -int buffer_list_refresh_states(buffer_list_t *buf_list) -{ - if (!buf_list) { - return -1; - } - - struct v4l2_buffer v4l2_buf = {0}; - struct v4l2_plane v4l2_plane = {0}; - - v4l2_buf.type = buf_list->v4l2.type; - - if (buf_list->v4l2.do_mplanes) { - v4l2_buf.length = 1; - v4l2_buf.m.planes = &v4l2_plane; - } - - if (buf_list->do_mmap) { - v4l2_buf.memory = V4L2_MEMORY_MMAP; - } else { - v4l2_buf.memory = V4L2_MEMORY_DMABUF; - } - - for (int i = 0; i < buf_list->nbufs; i++) { - v4l2_buf.index = i; - - E_XIOCTL(buf_list, buf_list->device->fd, VIDIOC_QUERYBUF, &v4l2_buf, "Can't query buffer (flags=%08x)", i); - E_LOG_INFO(buf_list, "Buffer: %d, Flags: %08x. Offset: %d", i, v4l2_buf.flags, - buf_list->v4l2.do_mplanes ? v4l2_plane.m.mem_offset : v4l2_buf.m.offset); - } - -error: - return -1; -} \ No newline at end of file diff --git a/device/hw/buffer_list.h b/device/hw/buffer_list.h index c9da521..8d0541e 100644 --- a/device/hw/buffer_list.h +++ b/device/hw/buffer_list.h @@ -42,4 +42,3 @@ 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); -int buffer_list_refresh_states(buffer_list_t *buf_list); diff --git a/device/hw/buffer_queue.c b/device/hw/buffer_queue.c index c555f86..fb99723 100644 --- a/device/hw/buffer_queue.c +++ b/device/hw/buffer_queue.c @@ -37,26 +37,57 @@ bool buffer_consumed(buffer_t *buf, const char *who) buf->mmap_reflinks--; if (!buf->enqueued && buf->mmap_reflinks == 0) { + 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 = buf->v4l2.flags; + + if (buf->buf_list->do_mmap) { + assert(buf->dma_source == NULL); + v4l2_buf.memory = V4L2_MEMORY_MMAP; + } else { + assert(buf->dma_source != NULL); + v4l2_buf.memory = V4L2_MEMORY_DMABUF; + } + // update used bytes if (buf->buf_list->v4l2.do_mplanes) { - buf->v4l2_plane.bytesused = buf->used; - buf->v4l2_plane.length = buf->length; - buf->v4l2_plane.data_offset = 0; + v4l2_buf.length = 1; + v4l2_buf.m.planes = &v4l2_plane; + v4l2_plane.bytesused = buf->used; + v4l2_plane.length = buf->length; + v4l2_plane.data_offset = 0; + + if (buf->dma_source) { + assert(!buf->buf_list->do_mmap); + v4l2_plane.m.fd = buf->dma_source->dma_fd; + } } else { - buf->v4l2_buffer.bytesused = buf->used; + v4l2_buf.bytesused = buf->used; + + if (buf->dma_source) { + assert(!buf->buf_list->do_mmap); + v4l2_buf.m.fd = buf->dma_source->dma_fd; + } } E_LOG_DEBUG(buf, "Queuing buffer... used=%zu length=%zu (linked=%s) by %s", buf->used, buf->length, - buf->mmap_source ? buf->mmap_source->name : NULL, + buf->dma_source ? buf->dma_source->name : NULL, who); + // Assign or clone timestamp if (buf->buf_list->do_timestamps) { - get_monotonic_time_us(NULL, &buf->v4l2_buffer.timestamp); + get_monotonic_time_us(NULL, &v4l2_buf.timestamp); + } else { + v4l2_buf.timestamp.tv_sec = buf->captured_time_us / (1000LL * 1000LL); + v4l2_buf.timestamp.tv_usec = buf->captured_time_us % (1000LL * 1000LL); } - E_XIOCTL(buf, buf->buf_list->device->fd, VIDIOC_QBUF, &buf->v4l2_buffer, "Can't queue buffer."); + E_XIOCTL(buf, buf->buf_list->device->fd, VIDIOC_QBUF, &v4l2_buf, "Can't queue buffer."); buf->enqueued = true; buf->enqueue_time_us = buf->buf_list->last_enqueued_us = get_monotonic_time_us(NULL, NULL); } @@ -66,13 +97,13 @@ bool buffer_consumed(buffer_t *buf, const char *who) error: { - buffer_t *mmap_source = buf->mmap_source; - buf->mmap_source = NULL; + buffer_t *dma_source = buf->dma_source; + buf->dma_source = NULL; buf->mmap_reflinks++; pthread_mutex_unlock(&buffer_lock); - if (mmap_source) { - buffer_consumed(mmap_source, who); + if (dma_source) { + buffer_consumed(dma_source, who); } } @@ -117,11 +148,10 @@ int buffer_list_enqueue(buffer_list_t *buf_list, buffer_t *dma_buf) return 0; } - // V4L2_BUF_FLAG_LAST - buf->v4l2_buffer.flags = 0; - buf->v4l2_buffer.flags &= ~V4L2_BUF_FLAG_KEYFRAME; - buf->v4l2_buffer.flags |= dma_buf->v4l2_buffer.flags & V4L2_BUF_FLAG_KEYFRAME; - buf->v4l2_buffer.timestamp = dma_buf->v4l2_buffer.timestamp; + buf->v4l2.flags = 0; + buf->v4l2.flags &= ~V4L2_BUF_FLAG_KEYFRAME; + buf->v4l2.flags |= dma_buf->v4l2.flags & V4L2_BUF_FLAG_KEYFRAME; + buf->captured_time_us = dma_buf->captured_time_us; if (buf_list->do_mmap) { if (dma_buf->used > buf->length) { @@ -137,16 +167,10 @@ int buffer_list_enqueue(buffer_list_t *buf_list, buffer_t *dma_buf) E_LOG_DEBUG(buf, "mmap copy: dest=%p, src=%p (%s), size=%zu, space=%zu, time=%dllus", buf->start, dma_buf->start, dma_buf->name, dma_buf->used, buf->length, after-before); } else { - if (buf_list->v4l2.do_mplanes) { - buf->v4l2_plane.m.fd = dma_buf->dma_fd; - } else { - buf->v4l2_buffer.m.fd = dma_buf->dma_fd; - } - E_LOG_DEBUG(buf, "dmabuf copy: dest=%p, src=%p (%s, dma_fd=%d), size=%zu", buf->start, dma_buf->start, dma_buf->name, dma_buf->dma_fd, dma_buf->used); - buf->mmap_source = dma_buf; + buf->dma_source = dma_buf; buf->length = dma_buf->length; dma_buf->mmap_reflinks++; } @@ -179,8 +203,9 @@ buffer_t *buffer_list_dequeue(buffer_list_t *buf_list) } else { buf->used = v4l2_buf.bytesused; } - buf->v4l2_buffer.flags = v4l2_buf.flags; - buf->v4l2_buffer.timestamp = v4l2_buf.timestamp; + // TODO: Copy flags + buf->v4l2.flags = v4l2_buf.flags; + buf->captured_time_us = get_time_us(CLOCK_FROM_PARAMS, NULL, &v4l2_buf.timestamp, 0); buf_list->last_dequeued_us = get_monotonic_time_us(NULL, NULL); if (buf->mmap_reflinks > 0) { @@ -195,13 +220,13 @@ buffer_t *buffer_list_dequeue(buffer_list_t *buf_list) buf->length, buf->used, buf_list->frames, - buf->mmap_source ? buf->mmap_source->name : NULL, - buf->v4l2_buffer.flags); + buf->dma_source ? buf->dma_source->name : NULL, + buf->v4l2.flags); - if (buf->mmap_source) { - buf->mmap_source->used = 0; - buffer_consumed(buf->mmap_source, "mmap-dequeued"); - buf->mmap_source = NULL; + if (buf->dma_source) { + buf->dma_source->used = 0; + buffer_consumed(buf->dma_source, "mmap-dequeued"); + buf->dma_source = NULL; } buf_list->frames++; @@ -218,11 +243,12 @@ int buffer_list_pollfd(buffer_list_t *buf_list, struct pollfd *pollfd, bool can_ // Can something be dequeued? pollfd->fd = buf_list->device->fd; pollfd->events = POLLHUP; - if (count_enqueued > 0 && can_dequeue) + if (count_enqueued > 0 && can_dequeue) { if (buf_list->do_capture) pollfd->events |= POLLIN; else pollfd->events |= POLLOUT; + } pollfd->revents = 0; return 0; } diff --git a/device/v4l2/buffer.c b/device/v4l2/buffer.c new file mode 100644 index 0000000..d5e7f97 --- /dev/null +++ b/device/v4l2/buffer.c @@ -0,0 +1,38 @@ +#include "device/v4l2/v4l2.h" +#include "device/hw/v4l2.h" +#include "device/hw/buffer_list.h" +#include "device/hw/device.h" + +int buffer_list_v4l2_refresh_states(buffer_list_t *buf_list) +{ + if (!buf_list) { + return -1; + } + + struct v4l2_buffer v4l2_buf = {0}; + struct v4l2_plane v4l2_plane = {0}; + + v4l2_buf.type = buf_list->v4l2.type; + + if (buf_list->v4l2.do_mplanes) { + v4l2_buf.length = 1; + v4l2_buf.m.planes = &v4l2_plane; + } + + if (buf_list->do_mmap) { + v4l2_buf.memory = V4L2_MEMORY_MMAP; + } else { + v4l2_buf.memory = V4L2_MEMORY_DMABUF; + } + + for (int i = 0; i < buf_list->nbufs; i++) { + v4l2_buf.index = i; + + E_XIOCTL(buf_list, buf_list->device->fd, VIDIOC_QUERYBUF, &v4l2_buf, "Can't query buffer (flags=%08x)", i); + E_LOG_INFO(buf_list, "Buffer: %d, Flags: %08x. Offset: %d", i, v4l2_buf.flags, + buf_list->v4l2.do_mplanes ? v4l2_plane.m.mem_offset : v4l2_buf.m.offset); + } + +error: + return -1; +} diff --git a/device/v4l2/v4l2.h b/device/v4l2/v4l2.h new file mode 100644 index 0000000..d2b7667 --- /dev/null +++ b/device/v4l2/v4l2.h @@ -0,0 +1,5 @@ +#pragma once + +typedef struct buffer_list_s buffer_list_t; + +int buffer_list_v4l2_refresh_states(buffer_list_t *buf_list); diff --git a/http/http_h264.c b/http/http_h264.c index 9dacbc5..57eae72 100644 --- a/http/http_h264.c +++ b/http/http_h264.c @@ -53,7 +53,7 @@ bool h264_is_key_frame(buffer_t *buf) unsigned char *data = buf->start; device_t *camera = buf->buf_list->device; - if (buf->v4l2_buffer.flags & V4L2_BUF_FLAG_KEYFRAME) { + if (buf->v4l2.flags & V4L2_BUF_FLAG_KEYFRAME) { E_LOG_DEBUG(buf, "Got key frame (from V4L2)!"); return true; } else if (buf->used >= 5 && (data[4] & 0x1F) == 0x07) {