mirror of
https://github.com/pikvm/ustreamer.git
synced 2026-05-28 08:16:14 +00:00
separate hw_buffer_t size and allocated
This commit is contained in:
34
src/device.c
34
src/device.c
@@ -177,8 +177,8 @@ void device_close(struct device_t *dev) {
|
|||||||
for (unsigned index = 0; index < dev->run->n_buffers; ++index) {
|
for (unsigned index = 0; index < dev->run->n_buffers; ++index) {
|
||||||
# define HW_BUFFER(_next) dev->run->hw_buffers[index]._next
|
# define HW_BUFFER(_next) dev->run->hw_buffers[index]._next
|
||||||
|
|
||||||
if (HW_BUFFER(size) > 0 && HW_BUFFER(data) != MAP_FAILED) {
|
if (HW_BUFFER(allocated) > 0 && HW_BUFFER(data) != MAP_FAILED) {
|
||||||
if (munmap(HW_BUFFER(data), HW_BUFFER(size)) < 0) {
|
if (munmap(HW_BUFFER(data), HW_BUFFER(allocated)) < 0) {
|
||||||
LOG_PERROR("Can't unmap device buffer %u", index);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int device_grab_buffer(struct device_t *dev, struct v4l2_buffer *buf_info) {
|
int device_grab_buffer(struct device_t *dev) {
|
||||||
MEMSET_ZERO_PTR(buf_info);
|
struct v4l2_buffer buf_info;
|
||||||
buf_info->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
|
||||||
buf_info->memory = V4L2_MEMORY_MMAP;
|
MEMSET_ZERO(buf_info);
|
||||||
|
buf_info.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
|
buf_info.memory = V4L2_MEMORY_MMAP;
|
||||||
|
|
||||||
LOG_DEBUG("Calling ioctl(VIDIOC_DQBUF) ...");
|
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");
|
LOG_PERROR("Unable to dequeue buffer");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG("Got a new frame in buffer index=%u; bytesused=%u", buf_info->index, buf_info->bytesused);
|
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) {
|
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_ERROR("Got invalid buffer index=%u; nbuffers=%u", buf_info.index, dev->run->n_buffers);
|
||||||
return -1;
|
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) ...");
|
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");
|
LOG_PERROR("Unable to requeue buffer");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
dev->run->hw_buffers[index].size = 0;
|
||||||
return 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);
|
LOG_PERROR("Can't map device buffer %u", dev->run->n_buffers);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
HW_BUFFER(size) = buf_info.length;
|
HW_BUFFER(allocated) = buf_info.length;
|
||||||
|
|
||||||
# undef HW_BUFFER
|
# undef HW_BUFFER
|
||||||
}
|
}
|
||||||
|
|||||||
10
src/device.h
10
src/device.h
@@ -42,8 +42,10 @@
|
|||||||
|
|
||||||
|
|
||||||
struct hw_buffer_t {
|
struct hw_buffer_t {
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
size_t allocated;
|
||||||
|
struct v4l2_buffer buf_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct picture_t {
|
struct picture_t {
|
||||||
@@ -118,6 +120,6 @@ int device_open(struct device_t *dev);
|
|||||||
void device_close(struct device_t *dev);
|
void device_close(struct device_t *dev);
|
||||||
|
|
||||||
int device_switch_capturing(struct device_t *dev, bool enable);
|
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_grab_buffer(struct device_t *dev);
|
||||||
int device_release_buffer(struct device_t *dev, struct v4l2_buffer *buf_info);
|
int device_release_buffer(struct device_t *dev, unsigned index);
|
||||||
int device_consume_event(struct device_t *dev);
|
int device_consume_event(struct device_t *dev);
|
||||||
|
|||||||
20
src/stream.c
20
src/stream.c
@@ -186,22 +186,23 @@ void stream_loop(struct stream_t *stream) {
|
|||||||
if (FD_ISSET(stream->dev->run->fd, &read_fds)) {
|
if (FD_ISSET(stream->dev->run->fd, &read_fds)) {
|
||||||
LOG_DEBUG("Frame is ready");
|
LOG_DEBUG("Frame is ready");
|
||||||
|
|
||||||
struct v4l2_buffer buf_info;
|
int buf_index;
|
||||||
long double now = get_now_monotonic();
|
long double now = get_now_monotonic();
|
||||||
long long now_second = floor_ms(now);
|
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;
|
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:
|
// Workaround for broken, corrupted frames:
|
||||||
// Under low light conditions corrupted frames may get captured.
|
// Under low light conditions corrupted frames may get captured.
|
||||||
// The good thing is such frames are quite small compared to the regular pictures.
|
// 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,
|
// For example a VGA (640x480) webcam picture is normally >= 8kByte large,
|
||||||
// corrupted frames are smaller.
|
// corrupted frames are smaller.
|
||||||
if (buf_info.bytesused < stream->dev->min_frame_size) {
|
if (stream->dev->run->hw_buffers[buf_index].size < stream->dev->min_frame_size) {
|
||||||
LOG_DEBUG("Dropping too small frame sized %u bytes, assuming it as broken", buf_info.bytesused);
|
LOG_DEBUG("Dropping too small frame sized %zu bytes, assuming it as broken",
|
||||||
|
stream->dev->run->hw_buffers[buf_index].size);
|
||||||
goto pass_frame;
|
goto pass_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,8 +230,7 @@ void stream_loop(struct stream_t *stream) {
|
|||||||
|
|
||||||
# define FREE_WORKER(_next) pool.workers[free_worker_number]._next
|
# define FREE_WORKER(_next) pool.workers[free_worker_number]._next
|
||||||
|
|
||||||
LOG_DEBUG("Grabbed a new frame to buffer %u", buf_info.index);
|
LOG_DEBUG("Grabbed a new frame to buffer %u", buf_index);
|
||||||
FREE_WORKER(buf_info) = buf_info;
|
|
||||||
|
|
||||||
if (!oldest_worker) {
|
if (!oldest_worker) {
|
||||||
oldest_worker = &pool.workers[free_worker_number];
|
oldest_worker = &pool.workers[free_worker_number];
|
||||||
@@ -249,7 +249,7 @@ void stream_loop(struct stream_t *stream) {
|
|||||||
last_worker->order_next = NULL;
|
last_worker->order_next = NULL;
|
||||||
|
|
||||||
A_MUTEX_LOCK(&FREE_WORKER(has_job_mutex));
|
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);
|
atomic_store(&FREE_WORKER(has_job), true);
|
||||||
A_MUTEX_UNLOCK(&FREE_WORKER(has_job_mutex));
|
A_MUTEX_UNLOCK(&FREE_WORKER(has_job_mutex));
|
||||||
A_COND_SIGNAL(&FREE_WORKER(has_job_cond));
|
A_COND_SIGNAL(&FREE_WORKER(has_job_cond));
|
||||||
@@ -264,7 +264,7 @@ void stream_loop(struct stream_t *stream) {
|
|||||||
|
|
||||||
pass_frame:
|
pass_frame:
|
||||||
|
|
||||||
if (device_release_buffer(stream->dev, &buf_info) < 0) {
|
if (device_release_buffer(stream->dev, buf_index) < 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -457,7 +457,7 @@ static void *_stream_worker_thread(void *v_worker) {
|
|||||||
}
|
}
|
||||||
PICTURE(encode_end_time) = get_now_monotonic();
|
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);
|
worker->job_start_time = PICTURE(encode_begin_time);
|
||||||
atomic_store(&worker->has_job, false);
|
atomic_store(&worker->has_job, false);
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ struct worker_t {
|
|||||||
|
|
||||||
pthread_mutex_t has_job_mutex;
|
pthread_mutex_t has_job_mutex;
|
||||||
int buf_index;
|
int buf_index;
|
||||||
struct v4l2_buffer buf_info;
|
|
||||||
atomic_bool has_job;
|
atomic_bool has_job;
|
||||||
bool job_failed;
|
bool job_failed;
|
||||||
long double job_start_time;
|
long double job_start_time;
|
||||||
|
|||||||
@@ -51,7 +51,6 @@
|
|||||||
#define A_CALLOC(_dest, _nmemb) assert((_dest = calloc(_nmemb, sizeof(*(_dest)))))
|
#define A_CALLOC(_dest, _nmemb) assert((_dest = calloc(_nmemb, sizeof(*(_dest)))))
|
||||||
#define A_REALLOC(_dest, _nmemb) assert((_dest = realloc(_dest, _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(_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]))
|
#define ARRAY_LEN(_array) (sizeof(_array) / sizeof(_array[0]))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user