mirror of
https://github.com/pikvm/ustreamer.git
synced 2026-07-24 04:31:56 +00:00
refactoring
This commit is contained in:
@@ -30,8 +30,8 @@
|
||||
#define US_ARRAY_ITERATE(x_array, x_start, x_item_ptr, ...) { \
|
||||
const int m_len = US_ARRAY_LEN(x_array); \
|
||||
assert(x_start <= m_len); \
|
||||
for (int m_index = x_start; m_index < m_len; ++m_index) { \
|
||||
__typeof__((x_array)[0]) *const x_item_ptr = &x_array[m_index]; \
|
||||
for (int m_i = x_start; m_i < m_len; ++m_i) { \
|
||||
__typeof__((x_array)[0]) *const x_item_ptr = &x_array[m_i]; \
|
||||
__VA_ARGS__ \
|
||||
} \
|
||||
}
|
||||
|
||||
@@ -54,8 +54,8 @@ void us_base64_encode(const u8 *data, uz size, char **encoded, uz *allocated) {
|
||||
}
|
||||
}
|
||||
|
||||
for (uint data_index = 0, encoded_index = 0; data_index < size;) {
|
||||
# define OCTET(_name) uint _name = (data_index < size ? (u8)data[data_index++] : 0)
|
||||
for (uint data_i = 0, encoded_i = 0; data_i < size;) {
|
||||
# define OCTET(_name) uint _name = (data_i < size ? (u8)data[data_i++] : 0)
|
||||
OCTET(octet_a);
|
||||
OCTET(octet_b);
|
||||
OCTET(octet_c);
|
||||
@@ -63,7 +63,7 @@ void us_base64_encode(const u8 *data, uz size, char **encoded, uz *allocated) {
|
||||
|
||||
const uint triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
|
||||
|
||||
# define ENCODE(_offset) (*encoded)[encoded_index++] = _ENCODING_TABLE[(triple >> _offset * 6) & 0x3F]
|
||||
# define ENCODE(_offset) (*encoded)[encoded_i++] = _ENCODING_TABLE[(triple >> _offset * 6) & 0x3F]
|
||||
ENCODE(3);
|
||||
ENCODE(2);
|
||||
ENCODE(1);
|
||||
|
||||
@@ -103,12 +103,21 @@ static int _capture_open_export_to_dma(us_capture_s *cap);
|
||||
static int _capture_apply_resolution(us_capture_s *cap, uint width, uint height, float hz);
|
||||
|
||||
static void _capture_apply_controls(const us_capture_s *cap);
|
||||
|
||||
static int _capture_query_control(
|
||||
const us_capture_s *cap, struct v4l2_queryctrl *query,
|
||||
const char *name, uint cid, bool quiet);
|
||||
const us_capture_s *cap,
|
||||
struct v4l2_queryctrl *query,
|
||||
const char *name,
|
||||
uint cid,
|
||||
bool quiet);
|
||||
|
||||
static void _capture_set_control(
|
||||
const us_capture_s *cap, const struct v4l2_queryctrl *query,
|
||||
const char *name, uint cid, int value, bool quiet);
|
||||
const us_capture_s *cap,
|
||||
const struct v4l2_queryctrl *query,
|
||||
const char *name,
|
||||
uint cid,
|
||||
int value,
|
||||
bool quiet);
|
||||
|
||||
static const char *_format_to_string_nullable(uint format);
|
||||
static const char *_format_to_string_supported(uint format);
|
||||
@@ -306,15 +315,15 @@ void us_capture_close(us_capture_s *cap) {
|
||||
if (run->bufs != NULL) {
|
||||
say = true;
|
||||
_LOG_DEBUG("Releasing HW buffers ...");
|
||||
for (uint index = 0; index < run->n_bufs; ++index) {
|
||||
us_capture_hwbuf_s *hw = &run->bufs[index];
|
||||
for (uint i = 0; i < run->n_bufs; ++i) {
|
||||
us_capture_hwbuf_s *hw = &run->bufs[i];
|
||||
|
||||
US_CLOSE_FD(hw->dma_fd);
|
||||
|
||||
if (cap->io_method == V4L2_MEMORY_MMAP) {
|
||||
if (hw->raw.allocated > 0 && hw->raw.data != NULL) {
|
||||
if (munmap(hw->raw.data, hw->raw.allocated) < 0) {
|
||||
_LOG_PERROR("Can't unmap HW buffer=%u", index);
|
||||
_LOG_PERROR("Can't unmap HW buffer=%u", i);
|
||||
}
|
||||
}
|
||||
} else { // V4L2_MEMORY_USERPTR
|
||||
@@ -451,7 +460,8 @@ int us_capture_hwbuf_grab(us_capture_s *cap, us_capture_hwbuf_s **hw) {
|
||||
(*hw)->raw.grab_end_ts = us_get_now_monotonic();
|
||||
|
||||
_LOG_DEBUG("Grabbed HW buffer=%u: bytesused=%u, grab_begin_ts=%.3Lf, grab_end_ts=%.3Lf, latency=%.3Lf, skipped=%u",
|
||||
buf.index, buf.bytesused,
|
||||
buf.index,
|
||||
buf.bytesused,
|
||||
(*hw)->raw.grab_begin_ts,
|
||||
(*hw)->raw.grab_end_ts,
|
||||
(*hw)->raw.grab_end_ts - (*hw)->raw.grab_begin_ts,
|
||||
@@ -462,14 +472,14 @@ int us_capture_hwbuf_grab(us_capture_s *cap, us_capture_hwbuf_s **hw) {
|
||||
|
||||
int us_capture_hwbuf_release(const us_capture_s *cap, us_capture_hwbuf_s *hw) {
|
||||
assert(atomic_load(&hw->refs) == 0);
|
||||
const uint index = hw->buf.index;
|
||||
_LOG_DEBUG("Releasing HW buffer=%u ...", index);
|
||||
const uint i = hw->buf.index;
|
||||
_LOG_DEBUG("Releasing HW buffer=%u ...", i);
|
||||
if (us_xioctl(cap->run->fd, VIDIOC_QBUF, &hw->buf) < 0) {
|
||||
_LOG_PERROR("Can't release HW buffer=%u", index);
|
||||
_LOG_PERROR("Can't release HW buffer=%u", i);
|
||||
return -1;
|
||||
}
|
||||
hw->grabbed = false;
|
||||
_LOG_DEBUG("HW buffer=%u released", index);
|
||||
_LOG_DEBUG("HW buffer=%u released", i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -850,31 +860,31 @@ static void _capture_open_hw_fps(us_capture_s *cap) { // cppcheck-suppress const
|
||||
return;
|
||||
}
|
||||
|
||||
# define SETFPS_TPF(x_next) setfps.parm.capture.timeperframe.x_next
|
||||
# define TPF(x_next) setfps.parm.capture.timeperframe.x_next
|
||||
|
||||
US_MEMSET_ZERO(setfps);
|
||||
setfps.type = run->capture_type;
|
||||
SETFPS_TPF(numerator) = 1;
|
||||
SETFPS_TPF(denominator) = -1; // Request maximum possible FPS
|
||||
TPF(numerator) = 1;
|
||||
TPF(denominator) = -1; // Request maximum possible FPS
|
||||
|
||||
if (us_xioctl(run->fd, VIDIOC_S_PARM, &setfps) < 0) {
|
||||
_LOG_PERROR("Can't set HW FPS");
|
||||
return;
|
||||
}
|
||||
|
||||
if (SETFPS_TPF(numerator) != 1) {
|
||||
_LOG_ERROR("Invalid HW FPS numerator: %u != 1", SETFPS_TPF(numerator));
|
||||
if (TPF(numerator) != 1) {
|
||||
_LOG_ERROR("Invalid HW FPS numerator: %u != 1", TPF(numerator));
|
||||
return;
|
||||
}
|
||||
|
||||
if (SETFPS_TPF(denominator) == 0) { // Не знаю, бывает ли так, но пускай на всякий случай
|
||||
if (TPF(denominator) == 0) { // Не знаю, бывает ли так, но пускай на всякий случай
|
||||
_LOG_ERROR("Invalid HW FPS denominator: 0");
|
||||
return;
|
||||
}
|
||||
|
||||
_LOG_INFO("Using HW FPS: %u/%u", SETFPS_TPF(numerator), SETFPS_TPF(denominator));
|
||||
_LOG_INFO("Using HW FPS: %u/%u", TPF(numerator), TPF(denominator));
|
||||
|
||||
# undef SETFPS_TPF
|
||||
# undef TPF
|
||||
}
|
||||
|
||||
static void _capture_open_jpeg_quality(us_capture_s *cap) {
|
||||
@@ -1017,12 +1027,12 @@ static int _capture_open_io_method_userptr(us_capture_s *cap) {
|
||||
static int _capture_open_queue_buffers(us_capture_s *cap) {
|
||||
us_capture_runtime_s *const run = cap->run;
|
||||
|
||||
for (uint index = 0; index < run->n_bufs; ++index) {
|
||||
for (uint i = 0; i < run->n_bufs; ++i) {
|
||||
struct v4l2_buffer buf = {0};
|
||||
struct v4l2_plane planes[VIDEO_MAX_PLANES] = {0};
|
||||
buf.type = run->capture_type;
|
||||
buf.memory = cap->io_method;
|
||||
buf.index = index;
|
||||
buf.index = i;
|
||||
if (run->capture_mplane) {
|
||||
buf.m.planes = planes;
|
||||
buf.length = 1;
|
||||
@@ -1031,11 +1041,11 @@ static int _capture_open_queue_buffers(us_capture_s *cap) {
|
||||
if (cap->io_method == V4L2_MEMORY_USERPTR) {
|
||||
// I am not sure, may be this is incorrect for mplane device,
|
||||
// but i don't have one which supports V4L2_MEMORY_USERPTR
|
||||
buf.m.userptr = (unsigned long)run->bufs[index].raw.data;
|
||||
buf.length = run->bufs[index].raw.allocated;
|
||||
buf.m.userptr = (unsigned long)run->bufs[i].raw.data;
|
||||
buf.length = run->bufs[i].raw.allocated;
|
||||
}
|
||||
|
||||
_LOG_DEBUG("Calling us_xioctl(VIDIOC_QBUF) for buffer=%u ...", index);
|
||||
_LOG_DEBUG("Calling us_xioctl(VIDIOC_QBUF) for buffer=%u ...", i);
|
||||
if (us_xioctl(run->fd, VIDIOC_QBUF, &buf) < 0) {
|
||||
_LOG_PERROR("Can't VIDIOC_QBUF");
|
||||
return -1;
|
||||
@@ -1047,23 +1057,23 @@ static int _capture_open_queue_buffers(us_capture_s *cap) {
|
||||
static int _capture_open_export_to_dma(us_capture_s *cap) {
|
||||
us_capture_runtime_s *const run = cap->run;
|
||||
|
||||
for (uint index = 0; index < run->n_bufs; ++index) {
|
||||
for (uint i = 0; i < run->n_bufs; ++i) {
|
||||
struct v4l2_exportbuffer exp = {
|
||||
.type = run->capture_type,
|
||||
.index = index,
|
||||
.index = i,
|
||||
};
|
||||
_LOG_DEBUG("Exporting device buffer=%u to DMA ...", index);
|
||||
_LOG_DEBUG("Exporting device buffer=%u to DMA ...", i);
|
||||
if (us_xioctl(run->fd, VIDIOC_EXPBUF, &exp) < 0) {
|
||||
_LOG_PERROR("Can't export device buffer=%u to DMA", index);
|
||||
_LOG_PERROR("Can't export device buffer=%u to DMA", i);
|
||||
goto error;
|
||||
}
|
||||
run->bufs[index].dma_fd = exp.fd;
|
||||
run->bufs[i].dma_fd = exp.fd;
|
||||
}
|
||||
return 0;
|
||||
|
||||
error:
|
||||
for (uint index = 0; index < run->n_bufs; ++index) {
|
||||
US_CLOSE_FD(run->bufs[index].dma_fd);
|
||||
for (uint i = 0; i < run->n_bufs; ++i) {
|
||||
US_CLOSE_FD(run->bufs[i].dma_fd);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -1142,9 +1152,12 @@ static void _capture_apply_controls(const us_capture_s *cap) {
|
||||
}
|
||||
|
||||
static int _capture_query_control(
|
||||
const us_capture_s *cap, struct v4l2_queryctrl *query,
|
||||
const char *name, uint cid, bool quiet) {
|
||||
|
||||
const us_capture_s *cap,
|
||||
struct v4l2_queryctrl *query,
|
||||
const char *name,
|
||||
uint cid,
|
||||
bool quiet
|
||||
) {
|
||||
// cppcheck-suppress redundantPointerOp
|
||||
US_MEMSET_ZERO(*query);
|
||||
query->id = cid;
|
||||
@@ -1159,9 +1172,13 @@ static int _capture_query_control(
|
||||
}
|
||||
|
||||
static void _capture_set_control(
|
||||
const us_capture_s *cap, const struct v4l2_queryctrl *query,
|
||||
const char *name, uint cid, int value, bool quiet) {
|
||||
|
||||
const us_capture_s *cap,
|
||||
const struct v4l2_queryctrl *query,
|
||||
const char *name,
|
||||
uint cid,
|
||||
int value,
|
||||
bool quiet
|
||||
) {
|
||||
if (value < query->minimum || value > query->maximum || value % query->step != 0) {
|
||||
if (!quiet) {
|
||||
_LOG_ERROR("Invalid value %d of control %s: min=%d, max=%d, default=%d, step=%u",
|
||||
|
||||
@@ -61,11 +61,11 @@ static const char *_connector_type_to_string(u32 type);
|
||||
static float _get_refresh_rate(const drmModeModeInfo *mode);
|
||||
|
||||
|
||||
#define _LOG_ERROR(x_msg, ...) US_LOG_ERROR("DRM: " x_msg, ##__VA_ARGS__)
|
||||
#define _LOG_PERROR(x_msg, ...) US_LOG_PERROR("DRM: " x_msg, ##__VA_ARGS__)
|
||||
#define _LOG_ERROR(x_msg, ...) US_LOG_ERROR("DRM: " x_msg, ##__VA_ARGS__)
|
||||
#define _LOG_PERROR(x_msg, ...) US_LOG_PERROR("DRM: " x_msg, ##__VA_ARGS__)
|
||||
#define _LOG_INFO(x_msg, ...) US_LOG_INFO("DRM: " x_msg, ##__VA_ARGS__)
|
||||
#define _LOG_VERBOSE(x_msg, ...) US_LOG_VERBOSE("DRM: " x_msg, ##__VA_ARGS__)
|
||||
#define _LOG_DEBUG(x_msg, ...) US_LOG_DEBUG("DRM: " x_msg, ##__VA_ARGS__)
|
||||
#define _LOG_DEBUG(x_msg, ...) US_LOG_DEBUG("DRM: " x_msg, ##__VA_ARGS__)
|
||||
|
||||
|
||||
us_drm_s *us_drm_init(void) {
|
||||
@@ -164,7 +164,12 @@ int us_drm_open(us_drm_s *drm, const us_capture_s *cap) {
|
||||
|
||||
run->saved_crtc = drmModeGetCrtc(run->fd, run->crtc_id);
|
||||
_LOG_DEBUG("Setting up CRTC ...");
|
||||
if (drmModeSetCrtc(run->fd, run->crtc_id, run->bufs[0].id, 0, 0, &run->conn_id, 1, &run->mode) < 0) {
|
||||
if (drmModeSetCrtc(
|
||||
run->fd,
|
||||
run->crtc_id, run->bufs[0].id,
|
||||
0, 0, // X, Y
|
||||
&run->conn_id, 1, &run->mode
|
||||
) < 0) {
|
||||
_LOG_PERROR("Can't set CRTC");
|
||||
goto error;
|
||||
}
|
||||
@@ -202,7 +207,8 @@ void us_drm_close(us_drm_s *drm) {
|
||||
|
||||
if (run->saved_crtc != NULL) {
|
||||
_LOG_DEBUG("Restoring CRTC ...");
|
||||
if (drmModeSetCrtc(run->fd,
|
||||
if (drmModeSetCrtc(
|
||||
run->fd,
|
||||
run->saved_crtc->crtc_id, run->saved_crtc->buffer_id,
|
||||
run->saved_crtc->x, run->saved_crtc->y,
|
||||
&run->conn_id, 1, &run->saved_crtc->mode
|
||||
|
||||
@@ -38,7 +38,7 @@ us_fpsi_s *us_fpsi_init(const char *name, bool with_meta) {
|
||||
US_CALLOC(fpsi, 1);
|
||||
fpsi->name = us_strdup(name);
|
||||
fpsi->with_meta = with_meta;
|
||||
atomic_init(&fpsi->state_sec_ts, 0);
|
||||
atomic_init(&fpsi->state_ts, 0);
|
||||
atomic_init(&fpsi->state, 0);
|
||||
return fpsi;
|
||||
}
|
||||
@@ -61,8 +61,8 @@ void us_fpsi_update(us_fpsi_s *fpsi, bool bump, const us_fpsi_meta_s *meta) {
|
||||
assert(!fpsi->with_meta);
|
||||
}
|
||||
|
||||
const sll now_sec_ts = us_floor_ms(us_get_now_monotonic());
|
||||
if (atomic_load(&fpsi->state_sec_ts) != now_sec_ts) {
|
||||
const sll now_ts = us_floor_ms(us_get_now_monotonic());
|
||||
if (atomic_load(&fpsi->state_ts) != now_ts) {
|
||||
US_LOG_PERF_FPS("FPS: %s: %u", fpsi->name, fpsi->accum);
|
||||
|
||||
// Fast mutex-less store method
|
||||
@@ -74,7 +74,7 @@ void us_fpsi_update(us_fpsi_s *fpsi, bool bump, const us_fpsi_meta_s *meta) {
|
||||
state |= (ull)(meta->online ? 1 : 0) << 48;
|
||||
}
|
||||
atomic_store(&fpsi->state, state); // Сначала инфа
|
||||
atomic_store(&fpsi->state_sec_ts, now_sec_ts); // Потом время, это важно
|
||||
atomic_store(&fpsi->state_ts, now_ts); // Потом время, это важно
|
||||
fpsi->accum = 0;
|
||||
}
|
||||
if (bump) {
|
||||
@@ -90,8 +90,8 @@ uint us_fpsi_get(us_fpsi_s *fpsi, us_fpsi_meta_s *meta) {
|
||||
// Между чтением инфы и времени может быть гонка,
|
||||
// но это неважно. Если время свежее, до данные тоже
|
||||
// будут свежмими, обратный случай не так важен.
|
||||
const sll now_sec_ts = us_floor_ms(us_get_now_monotonic());
|
||||
const sll state_sec_ts = atomic_load(&fpsi->state_sec_ts); // Сначала время
|
||||
const sll now_ts = us_floor_ms(us_get_now_monotonic());
|
||||
const sll state_ts = atomic_load(&fpsi->state_ts); // Сначала время
|
||||
const ull state = atomic_load(&fpsi->state); // Потом инфа
|
||||
|
||||
uint current = state & 0xFFFF;
|
||||
@@ -101,7 +101,7 @@ uint us_fpsi_get(us_fpsi_s *fpsi, us_fpsi_meta_s *meta) {
|
||||
meta->online = (state >> 48) & 1;
|
||||
}
|
||||
|
||||
if (state_sec_ts != now_sec_ts && (state_sec_ts + 1) != now_sec_ts) {
|
||||
if (state_ts != now_ts && (state_ts + 1) != now_ts) {
|
||||
// Только текущая или прошлая секунда
|
||||
current = 0;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ typedef struct {
|
||||
char *name;
|
||||
bool with_meta;
|
||||
uint accum;
|
||||
atomic_llong state_sec_ts;
|
||||
atomic_llong state_ts;
|
||||
atomic_ullong state;
|
||||
} us_fpsi_s;
|
||||
|
||||
|
||||
@@ -34,9 +34,12 @@
|
||||
|
||||
|
||||
static void _frametext_draw_line(
|
||||
us_frametext_s *ft, const char *line,
|
||||
uint scale_x, uint scale_y,
|
||||
uint start_x, uint start_y);
|
||||
us_frametext_s *ft,
|
||||
const char *line,
|
||||
uint scale_x,
|
||||
uint scale_y,
|
||||
uint start_x,
|
||||
uint start_y);
|
||||
|
||||
|
||||
us_frametext_s *us_frametext_init(void) {
|
||||
@@ -156,10 +159,13 @@ empty:
|
||||
}
|
||||
|
||||
void _frametext_draw_line(
|
||||
us_frametext_s *ft, const char *line,
|
||||
uint scale_x, uint scale_y,
|
||||
uint start_x, uint start_y) {
|
||||
|
||||
us_frametext_s *ft,
|
||||
const char *line,
|
||||
uint scale_x,
|
||||
uint scale_y,
|
||||
uint start_x,
|
||||
uint start_y
|
||||
) {
|
||||
us_frame_s *const frame = ft->frame;
|
||||
|
||||
const size_t len = strlen(line);
|
||||
|
||||
@@ -75,7 +75,7 @@ extern pthread_mutex_t us_g_log_mutex;
|
||||
|
||||
#define US_SEP_INFO(x_ch) { \
|
||||
US_LOGGING_LOCK; \
|
||||
for (int m_count = 0; m_count < 80; ++m_count) { \
|
||||
for (int m_i = 0; m_i < 80; ++m_i) { \
|
||||
fputc((x_ch), stderr); \
|
||||
} \
|
||||
fputc('\n', stderr); \
|
||||
|
||||
@@ -32,14 +32,14 @@
|
||||
|
||||
void us_build_short_options(const struct option opts[], char *short_opts, uz size) {
|
||||
memset(short_opts, 0, size);
|
||||
for (uint short_index = 0, opt_index = 0; opts[opt_index].name != NULL; ++opt_index) {
|
||||
assert(short_index < size - 3);
|
||||
if (isalpha(opts[opt_index].val)) {
|
||||
short_opts[short_index] = opts[opt_index].val;
|
||||
++short_index;
|
||||
if (opts[opt_index].has_arg == required_argument) {
|
||||
short_opts[short_index] = ':';
|
||||
++short_index;
|
||||
for (uint short_i = 0, opt_i = 0; opts[opt_i].name != NULL; ++opt_i) {
|
||||
assert(short_i < size - 3);
|
||||
if (isalpha(opts[opt_i].val)) {
|
||||
short_opts[short_i] = opts[opt_i].val;
|
||||
++short_i;
|
||||
if (opts[opt_i].has_arg == required_argument) {
|
||||
short_opts[short_i] = ':';
|
||||
++short_i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,13 +71,13 @@ INLINE int us_process_track_parent_death(void) {
|
||||
const pid_t parent = getppid();
|
||||
int signum = SIGTERM;
|
||||
# if defined(__linux__)
|
||||
const int retval = prctl(PR_SET_PDEATHSIG, signum);
|
||||
const int result = prctl(PR_SET_PDEATHSIG, signum);
|
||||
# elif defined(__FreeBSD__)
|
||||
const int retval = procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum);
|
||||
const int result = procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum);
|
||||
# else
|
||||
# error WTF?
|
||||
# endif
|
||||
if (retval < 0) {
|
||||
if (result < 0) {
|
||||
US_LOG_PERROR("Can't set to receive SIGTERM on parent process death");
|
||||
return -1;
|
||||
}
|
||||
@@ -103,15 +103,15 @@ INLINE void us_process_set_name_prefix(int argc, char *argv[], const char *prefi
|
||||
US_REALLOC(cmdline, allocated);
|
||||
cmdline[0] = '\0';
|
||||
|
||||
for (int index = 0; index < argc; ++index) {
|
||||
uz arg_len = strlen(argv[index]);
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
uz arg_len = strlen(argv[i]);
|
||||
if (used + arg_len + 16 >= allocated) {
|
||||
allocated += arg_len + 2048;
|
||||
US_REALLOC(cmdline, allocated); // cppcheck-suppress memleakOnRealloc // False-positive (ok with assert)
|
||||
}
|
||||
|
||||
strcat(cmdline, " ");
|
||||
strcat(cmdline, argv[index]);
|
||||
strcat(cmdline, argv[i]);
|
||||
used = strlen(cmdline); // Не считаем вручную, так надежнее
|
||||
}
|
||||
|
||||
|
||||
@@ -34,27 +34,27 @@
|
||||
|
||||
|
||||
us_queue_s *us_queue_init(uint capacity) {
|
||||
us_queue_s *queue;
|
||||
US_CALLOC(queue, 1);
|
||||
US_CALLOC(queue->items, capacity);
|
||||
queue->capacity = capacity;
|
||||
US_MUTEX_INIT(queue->mutex);
|
||||
us_queue_s *q;
|
||||
US_CALLOC(q, 1);
|
||||
US_CALLOC(q->items, capacity);
|
||||
q->capacity = capacity;
|
||||
US_MUTEX_INIT(q->mutex);
|
||||
|
||||
pthread_condattr_t attrs;
|
||||
assert(!pthread_condattr_init(&attrs));
|
||||
assert(!pthread_condattr_setclock(&attrs, CLOCK_MONOTONIC));
|
||||
assert(!pthread_cond_init(&queue->full_cond, &attrs));
|
||||
assert(!pthread_cond_init(&queue->empty_cond, &attrs));
|
||||
assert(!pthread_cond_init(&q->full_cond, &attrs));
|
||||
assert(!pthread_cond_init(&q->empty_cond, &attrs));
|
||||
assert(!pthread_condattr_destroy(&attrs));
|
||||
return queue;
|
||||
return q;
|
||||
}
|
||||
|
||||
void us_queue_destroy(us_queue_s *queue) {
|
||||
US_COND_DESTROY(queue->empty_cond);
|
||||
US_COND_DESTROY(queue->full_cond);
|
||||
US_MUTEX_DESTROY(queue->mutex);
|
||||
free(queue->items);
|
||||
free(queue);
|
||||
void us_queue_destroy(us_queue_s *q) {
|
||||
US_COND_DESTROY(q->empty_cond);
|
||||
US_COND_DESTROY(q->full_cond);
|
||||
US_MUTEX_DESTROY(q->mutex);
|
||||
free(q->items);
|
||||
free(q);
|
||||
}
|
||||
|
||||
#define _WAIT_OR_UNLOCK(x_var, x_cond) { \
|
||||
@@ -62,51 +62,51 @@ void us_queue_destroy(us_queue_s *queue) {
|
||||
assert(!clock_gettime(CLOCK_MONOTONIC, &m_ts)); \
|
||||
us_ld_to_timespec(us_timespec_to_ld(&m_ts) + timeout, &m_ts); \
|
||||
while (x_var) { \
|
||||
const int err = pthread_cond_timedwait(&(x_cond), &queue->mutex, &m_ts); \
|
||||
const int err = pthread_cond_timedwait(&(x_cond), &q->mutex, &m_ts); \
|
||||
if (err == ETIMEDOUT) { \
|
||||
US_MUTEX_UNLOCK(queue->mutex); \
|
||||
US_MUTEX_UNLOCK(q->mutex); \
|
||||
return -1; \
|
||||
} \
|
||||
assert(!err); \
|
||||
} \
|
||||
}
|
||||
|
||||
int us_queue_put(us_queue_s *queue, void *item, ldf timeout) {
|
||||
US_MUTEX_LOCK(queue->mutex);
|
||||
int us_queue_put(us_queue_s *q, void *item, ldf timeout) {
|
||||
US_MUTEX_LOCK(q->mutex);
|
||||
if (timeout == 0) {
|
||||
if (queue->size == queue->capacity) {
|
||||
US_MUTEX_UNLOCK(queue->mutex);
|
||||
if (q->size == q->capacity) {
|
||||
US_MUTEX_UNLOCK(q->mutex);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
_WAIT_OR_UNLOCK(queue->size == queue->capacity, queue->full_cond);
|
||||
_WAIT_OR_UNLOCK(q->size == q->capacity, q->full_cond);
|
||||
}
|
||||
queue->items[queue->in] = item;
|
||||
++queue->size;
|
||||
++queue->in;
|
||||
queue->in %= queue->capacity;
|
||||
US_MUTEX_UNLOCK(queue->mutex);
|
||||
US_COND_BROADCAST(queue->empty_cond);
|
||||
q->items[q->in] = item;
|
||||
++q->size;
|
||||
++q->in;
|
||||
q->in %= q->capacity;
|
||||
US_MUTEX_UNLOCK(q->mutex);
|
||||
US_COND_BROADCAST(q->empty_cond);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int us_queue_get(us_queue_s *queue, void **item, ldf timeout) {
|
||||
US_MUTEX_LOCK(queue->mutex);
|
||||
_WAIT_OR_UNLOCK(queue->size == 0, queue->empty_cond);
|
||||
*item = queue->items[queue->out];
|
||||
--queue->size;
|
||||
++queue->out;
|
||||
queue->out %= queue->capacity;
|
||||
US_MUTEX_UNLOCK(queue->mutex);
|
||||
US_COND_BROADCAST(queue->full_cond);
|
||||
int us_queue_get(us_queue_s *q, void **item, ldf timeout) {
|
||||
US_MUTEX_LOCK(q->mutex);
|
||||
_WAIT_OR_UNLOCK(q->size == 0, q->empty_cond);
|
||||
*item = q->items[q->out];
|
||||
--q->size;
|
||||
++q->out;
|
||||
q->out %= q->capacity;
|
||||
US_MUTEX_UNLOCK(q->mutex);
|
||||
US_COND_BROADCAST(q->full_cond);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef _WAIT_OR_UNLOCK
|
||||
|
||||
bool us_queue_is_empty(us_queue_s *queue) {
|
||||
US_MUTEX_LOCK(queue->mutex);
|
||||
const uint size = queue->size;
|
||||
US_MUTEX_UNLOCK(queue->mutex);
|
||||
return (bool)(queue->capacity - size);
|
||||
bool us_queue_is_empty(us_queue_s *q) {
|
||||
US_MUTEX_LOCK(q->mutex);
|
||||
const uint size = q->size;
|
||||
US_MUTEX_UNLOCK(q->mutex);
|
||||
return (bool)(q->capacity - size);
|
||||
}
|
||||
|
||||
@@ -43,22 +43,22 @@ typedef struct {
|
||||
} us_queue_s;
|
||||
|
||||
|
||||
#define US_QUEUE_DELETE_WITH_ITEMS(x_queue, x_free_item) { \
|
||||
if (x_queue) { \
|
||||
while (!us_queue_is_empty(x_queue)) { \
|
||||
#define US_QUEUE_DELETE_WITH_ITEMS(x_q, x_free_item) { \
|
||||
if (x_q) { \
|
||||
while (!us_queue_is_empty(x_q)) { \
|
||||
void *m_ptr; \
|
||||
if (!us_queue_get(x_queue, &m_ptr, 0)) { \
|
||||
if (!us_queue_get(x_q, &m_ptr, 0)) { \
|
||||
US_DELETE(m_ptr, x_free_item); \
|
||||
} \
|
||||
} \
|
||||
us_queue_destroy(x_queue); \
|
||||
us_queue_destroy(x_q); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
us_queue_s *us_queue_init(uint capacity);
|
||||
void us_queue_destroy(us_queue_s *queue);
|
||||
void us_queue_destroy(us_queue_s *q);
|
||||
|
||||
int us_queue_put(us_queue_s *queue, void *item, ldf timeout);
|
||||
int us_queue_get(us_queue_s *queue, void **item, ldf timeout);
|
||||
bool us_queue_is_empty(us_queue_s *queue);
|
||||
int us_queue_put(us_queue_s *q, void *item, ldf timeout);
|
||||
int us_queue_get(us_queue_s *q, void **item, ldf timeout);
|
||||
bool us_queue_is_empty(us_queue_s *q);
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
#include "queue.h"
|
||||
|
||||
|
||||
int _acquire(us_ring_s *ring, us_queue_s *queue, ldf timeout);
|
||||
void _release(us_ring_s *ring, us_queue_s *queue, uint index);
|
||||
int _acquire(us_ring_s *ring, us_queue_s *q, ldf timeout);
|
||||
void _release(us_ring_s *ring, us_queue_s *q, uint ri);
|
||||
|
||||
|
||||
us_ring_s *us_ring_init(uint capacity) {
|
||||
@@ -41,9 +41,9 @@ us_ring_s *us_ring_init(uint capacity) {
|
||||
ring->capacity = capacity;
|
||||
ring->producer = us_queue_init(capacity);
|
||||
ring->consumer = us_queue_init(capacity);
|
||||
for (uint index = 0; index < capacity; ++index) {
|
||||
ring->places[index] = index; // XXX: Just to avoid casting between pointer and uint
|
||||
assert(!us_queue_put(ring->producer, (void*)(ring->places + index), 0));
|
||||
for (uint ri = 0; ri < capacity; ++ri) {
|
||||
ring->places[ri] = ri; // XXX: Just to avoid casting between pointer and uint
|
||||
assert(!us_queue_put(ring->producer, (void*)(ring->places + ri), 0));
|
||||
}
|
||||
return ring;
|
||||
}
|
||||
@@ -60,27 +60,27 @@ int us_ring_producer_acquire(us_ring_s *ring, ldf timeout) {
|
||||
return _acquire(ring, ring->producer, timeout);
|
||||
}
|
||||
|
||||
void us_ring_producer_release(us_ring_s *ring, uint index) {
|
||||
_release(ring, ring->consumer, index);
|
||||
void us_ring_producer_release(us_ring_s *ring, uint ri) {
|
||||
_release(ring, ring->consumer, ri);
|
||||
}
|
||||
|
||||
int us_ring_consumer_acquire(us_ring_s *ring, ldf timeout) {
|
||||
return _acquire(ring, ring->consumer, timeout);
|
||||
}
|
||||
|
||||
void us_ring_consumer_release(us_ring_s *ring, uint index) {
|
||||
_release(ring, ring->producer, index);
|
||||
void us_ring_consumer_release(us_ring_s *ring, uint ri) {
|
||||
_release(ring, ring->producer, ri);
|
||||
}
|
||||
|
||||
int _acquire(us_ring_s *ring, us_queue_s *queue, ldf timeout) {
|
||||
int _acquire(us_ring_s *ring, us_queue_s *q, ldf timeout) {
|
||||
(void)ring;
|
||||
uint *place;
|
||||
if (us_queue_get(queue, (void**)&place, timeout) < 0) {
|
||||
if (us_queue_get(q, (void**)&place, timeout) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return *place;
|
||||
}
|
||||
|
||||
void _release(us_ring_s *ring, us_queue_s *queue, uint index) {
|
||||
assert(!us_queue_put(queue, (void*)(ring->places + index), 0));
|
||||
void _release(us_ring_s *ring, us_queue_s *q, uint ri) {
|
||||
assert(!us_queue_put(q, (void*)(ring->places + ri), 0));
|
||||
}
|
||||
|
||||
@@ -38,15 +38,15 @@ typedef struct {
|
||||
|
||||
#define US_RING_INIT_WITH_ITEMS(x_ring, x_capacity, x_init_item) { \
|
||||
(x_ring) = us_ring_init(x_capacity); \
|
||||
for (uz m_index = 0; m_index < (x_ring)->capacity; ++m_index) { \
|
||||
(x_ring)->items[m_index] = x_init_item(); \
|
||||
for (uz m_ri = 0; m_ri < (x_ring)->capacity; ++m_ri) { \
|
||||
(x_ring)->items[m_ri] = x_init_item(); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define US_RING_DELETE_WITH_ITEMS(x_ring, x_destroy_item) { \
|
||||
if (x_ring) { \
|
||||
for (uz m_index = 0; m_index < (x_ring)->capacity; ++m_index) { \
|
||||
x_destroy_item((x_ring)->items[m_index]); \
|
||||
for (uz m_ri = 0; m_ri < (x_ring)->capacity; ++m_ri) { \
|
||||
x_destroy_item((x_ring)->items[m_ri]); \
|
||||
} \
|
||||
us_ring_destroy(x_ring); \
|
||||
} \
|
||||
@@ -57,7 +57,7 @@ us_ring_s *us_ring_init(uint capacity);
|
||||
void us_ring_destroy(us_ring_s *ring);
|
||||
|
||||
int us_ring_producer_acquire(us_ring_s *ring, ldf timeout);
|
||||
void us_ring_producer_release(us_ring_s *ring, uint index);
|
||||
void us_ring_producer_release(us_ring_s *ring, uint ri);
|
||||
|
||||
int us_ring_consumer_acquire(us_ring_s *ring, ldf timeout);
|
||||
void us_ring_consumer_release(us_ring_s *ring, uint index);
|
||||
void us_ring_consumer_release(us_ring_s *ring, uint ri);
|
||||
|
||||
@@ -77,7 +77,7 @@ int us_unjpeg(const us_frame_s *src, us_frame_s *dest, bool decode) {
|
||||
|
||||
if (decode) {
|
||||
JSAMPARRAY scanlines;
|
||||
scanlines = (*jpeg.mem->alloc_sarray)((j_common_ptr) &jpeg, JPOOL_IMAGE, dest->stride, 1);
|
||||
scanlines = (*jpeg.mem->alloc_sarray)((j_common_ptr)&jpeg, JPOOL_IMAGE, dest->stride, 1);
|
||||
|
||||
us_frame_realloc_data(dest, ((dest->width * dest->height) << 1) * 2);
|
||||
while (jpeg.output_scanline < jpeg.output_height) {
|
||||
|
||||
Reference in New Issue
Block a user