mirror of
https://github.com/Harshit-Dhanwalkar/AsciiCam.git
synced 2026-06-21 10:58:05 +02:00
Add system level camera parameter controles like hue, sat, expo, etc
This commit is contained in:
parent
dc843f3e59
commit
f531035887
4 changed files with 272 additions and 8 deletions
|
|
@ -31,4 +31,20 @@ int webcam_requeue_buffer(webcam_t *cam);
|
|||
// Stop streaming and clean up resources
|
||||
void webcam_cleanup(webcam_t *cam);
|
||||
|
||||
// Hardware camera controls.
|
||||
int webcam_set_auto_exposure(webcam_t *cam, int enable);
|
||||
int webcam_set_auto_white_balance(webcam_t *cam, int enable);
|
||||
|
||||
int webcam_adjust_exposure(webcam_t *cam, int delta, int *out_value);
|
||||
int webcam_adjust_contrast(webcam_t *cam, int delta, int *out_value);
|
||||
int webcam_adjust_white_balance(webcam_t *cam, int delta, int *out_value);
|
||||
|
||||
int webcam_get_exposure(webcam_t *cam, int *value);
|
||||
int webcam_get_contrast(webcam_t *cam, int *value);
|
||||
int webcam_get_white_balance(webcam_t *cam, int *value);
|
||||
|
||||
int webcam_get_exposure_range(webcam_t *cam, int *min, int *max);
|
||||
int webcam_get_contrast_range(webcam_t *cam, int *min, int *max);
|
||||
int webcam_get_white_balance_range(webcam_t *cam, int *min, int *max);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -56,18 +56,19 @@ void *nl_malloc(size_t n) {
|
|||
}
|
||||
p += sizeof(block_hdr_t) + h->size;
|
||||
}
|
||||
return (void *)0; /* OOM */
|
||||
return (void *)0; // OOM
|
||||
}
|
||||
|
||||
void *nl_calloc(size_t nmemb, size_t size) {
|
||||
if (nmemb != 0 && size > SIZE_MAX / nmemb)
|
||||
return NULL;
|
||||
|
||||
size_t total = nmemb * size;
|
||||
void *p = nl_malloc(total);
|
||||
if (p) {
|
||||
// uint8_t *b = (uint8_t *)p;
|
||||
// for (size_t i = 0; i < total; i++)
|
||||
// b[i] = 0;
|
||||
if (nmemb && size > SIZE_MAX / nmemb)
|
||||
return NULL;
|
||||
uint8_t *b = (uint8_t *)p;
|
||||
for (size_t i = 0; i < total; i++)
|
||||
b[i] = 0;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
|
@ -91,6 +92,19 @@ void nl_free(void *ptr) {
|
|||
}
|
||||
}
|
||||
|
||||
// Coalesce Backward
|
||||
// TODO:
|
||||
// Coalesce backward
|
||||
unsigned char *p = _arena;
|
||||
unsigned char *target = (unsigned char *)h;
|
||||
block_hdr_t *prev = NULL;
|
||||
while (p < target) {
|
||||
block_hdr_t *cur = (block_hdr_t *)p;
|
||||
if (cur->magic != HDR_MAGIC)
|
||||
break; // heap corruption guard
|
||||
prev = cur;
|
||||
p += sizeof(block_hdr_t) + cur->size;
|
||||
}
|
||||
if (prev && prev->free && p == target) {
|
||||
prev->size += sizeof(block_hdr_t) + h->size;
|
||||
h->magic = 0; // h is now absorbed into prev
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ typedef struct webcam_impl webcam_impl_t;
|
|||
|
||||
struct webcam_impl {
|
||||
struct v4l2_buffer buf_info;
|
||||
int auto_exposure_disabled;
|
||||
int auto_wb_disabled;
|
||||
};
|
||||
|
||||
static webcam_impl_t _impl_storage;
|
||||
|
|
@ -127,4 +129,155 @@ void webcam_cleanup(webcam_t *cam) {
|
|||
cam->impl = (webcam_impl_t *)0;
|
||||
}
|
||||
|
||||
// Hardware controls (V4L2_CID_*)
|
||||
static int v4l2_query_range(int fd, unsigned int id, int *min, int *max) {
|
||||
struct v4l2_queryctrl q;
|
||||
nl_memset(&q, 0, sizeof(q));
|
||||
q.id = id;
|
||||
if (ioctl(fd, VIDIOC_QUERYCTRL, &q) < 0)
|
||||
return -1;
|
||||
if (q.flags & V4L2_CTRL_FLAG_DISABLED)
|
||||
return -1;
|
||||
if (min)
|
||||
*min = q.minimum;
|
||||
if (max)
|
||||
*max = q.maximum;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int v4l2_get_value(int fd, unsigned int id, int *value) {
|
||||
struct v4l2_control c;
|
||||
nl_memset(&c, 0, sizeof(c));
|
||||
c.id = id;
|
||||
if (ioctl(fd, VIDIOC_G_CTRL, &c) < 0)
|
||||
return -1;
|
||||
*value = c.value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int v4l2_set_value(int fd, unsigned int id, int value) {
|
||||
struct v4l2_control c;
|
||||
nl_memset(&c, 0, sizeof(c));
|
||||
c.id = id;
|
||||
c.value = value;
|
||||
return ioctl(fd, VIDIOC_S_CTRL, &c);
|
||||
}
|
||||
|
||||
static int v4l2_clamp(int v, int lo, int hi) {
|
||||
return (v < lo) ? lo : (v > hi) ? hi : v;
|
||||
}
|
||||
|
||||
int webcam_set_auto_exposure(webcam_t *cam, int enable) {
|
||||
if (!cam || cam->fd < 0)
|
||||
return -1;
|
||||
// NOTE: UVC drivers expose V4L2_CID_EXPOSURE_AUTO as a menu (0=manual,
|
||||
// 1=aperture priority, 3=auto, driver-dependent which subset exists).
|
||||
// Some webcam drivers instead/also expose the simpler boolean
|
||||
// V4L2_CID_AUTOGAIN. Try the proper one first, fall back to the boolean.
|
||||
if (v4l2_set_value(cam->fd, V4L2_CID_EXPOSURE_AUTO,
|
||||
enable ? V4L2_EXPOSURE_AUTO : V4L2_EXPOSURE_MANUAL) == 0)
|
||||
return 0;
|
||||
return v4l2_set_value(cam->fd, V4L2_CID_AUTOGAIN, enable ? 1 : 0);
|
||||
}
|
||||
|
||||
int webcam_set_auto_white_balance(webcam_t *cam, int enable) {
|
||||
if (!cam || cam->fd < 0)
|
||||
return -1;
|
||||
return v4l2_set_value(cam->fd, V4L2_CID_AUTO_WHITE_BALANCE, enable ? 1 : 0);
|
||||
}
|
||||
|
||||
int webcam_get_exposure(webcam_t *cam, int *value) {
|
||||
if (!cam || cam->fd < 0 || !value)
|
||||
return -1;
|
||||
return v4l2_get_value(cam->fd, V4L2_CID_EXPOSURE_ABSOLUTE, value);
|
||||
}
|
||||
|
||||
int webcam_get_contrast(webcam_t *cam, int *value) {
|
||||
if (!cam || cam->fd < 0 || !value)
|
||||
return -1;
|
||||
return v4l2_get_value(cam->fd, V4L2_CID_CONTRAST, value);
|
||||
}
|
||||
|
||||
int webcam_get_white_balance(webcam_t *cam, int *value) {
|
||||
if (!cam || cam->fd < 0 || !value)
|
||||
return -1;
|
||||
return v4l2_get_value(cam->fd, V4L2_CID_WHITE_BALANCE_TEMPERATURE, value);
|
||||
}
|
||||
|
||||
int webcam_get_exposure_range(webcam_t *cam, int *min, int *max) {
|
||||
if (!cam || cam->fd < 0)
|
||||
return -1;
|
||||
return v4l2_query_range(cam->fd, V4L2_CID_EXPOSURE_ABSOLUTE, min, max);
|
||||
}
|
||||
|
||||
int webcam_get_contrast_range(webcam_t *cam, int *min, int *max) {
|
||||
if (!cam || cam->fd < 0)
|
||||
return -1;
|
||||
return v4l2_query_range(cam->fd, V4L2_CID_CONTRAST, min, max);
|
||||
}
|
||||
|
||||
int webcam_get_white_balance_range(webcam_t *cam, int *min, int *max) {
|
||||
if (!cam || cam->fd < 0)
|
||||
return -1;
|
||||
return v4l2_query_range(cam->fd, V4L2_CID_WHITE_BALANCE_TEMPERATURE, min,
|
||||
max);
|
||||
}
|
||||
|
||||
int webcam_adjust_exposure(webcam_t *cam, int delta, int *out_value) {
|
||||
if (!cam || cam->fd < 0)
|
||||
return -1;
|
||||
if (!cam->impl->auto_exposure_disabled) {
|
||||
webcam_set_auto_exposure(cam, 0);
|
||||
cam->impl->auto_exposure_disabled = 1;
|
||||
}
|
||||
int min, max, cur;
|
||||
if (v4l2_query_range(cam->fd, V4L2_CID_EXPOSURE_ABSOLUTE, &min, &max) < 0)
|
||||
return -1;
|
||||
if (v4l2_get_value(cam->fd, V4L2_CID_EXPOSURE_ABSOLUTE, &cur) < 0)
|
||||
cur = min;
|
||||
int next = v4l2_clamp(cur + delta, min, max);
|
||||
if (v4l2_set_value(cam->fd, V4L2_CID_EXPOSURE_ABSOLUTE, next) < 0)
|
||||
return -1;
|
||||
if (out_value)
|
||||
*out_value = next;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int webcam_adjust_contrast(webcam_t *cam, int delta, int *out_value) {
|
||||
if (!cam || cam->fd < 0)
|
||||
return -1;
|
||||
int min, max, cur;
|
||||
if (v4l2_query_range(cam->fd, V4L2_CID_CONTRAST, &min, &max) < 0)
|
||||
return -1;
|
||||
if (v4l2_get_value(cam->fd, V4L2_CID_CONTRAST, &cur) < 0)
|
||||
cur = min;
|
||||
int next = v4l2_clamp(cur + delta, min, max);
|
||||
if (v4l2_set_value(cam->fd, V4L2_CID_CONTRAST, next) < 0)
|
||||
return -1;
|
||||
if (out_value)
|
||||
*out_value = next;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int webcam_adjust_white_balance(webcam_t *cam, int delta, int *out_value) {
|
||||
if (!cam || cam->fd < 0)
|
||||
return -1;
|
||||
if (!cam->impl->auto_wb_disabled) {
|
||||
webcam_set_auto_white_balance(cam, 0);
|
||||
cam->impl->auto_wb_disabled = 1;
|
||||
}
|
||||
int min, max, cur;
|
||||
if (v4l2_query_range(cam->fd, V4L2_CID_WHITE_BALANCE_TEMPERATURE, &min,
|
||||
&max) < 0)
|
||||
return -1;
|
||||
if (v4l2_get_value(cam->fd, V4L2_CID_WHITE_BALANCE_TEMPERATURE, &cur) < 0)
|
||||
cur = min;
|
||||
int next = v4l2_clamp(cur + delta, min, max);
|
||||
if (v4l2_set_value(cam->fd, V4L2_CID_WHITE_BALANCE_TEMPERATURE, next) < 0)
|
||||
return -1;
|
||||
if (out_value)
|
||||
*out_value = next;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -294,4 +294,85 @@ void webcam_cleanup(webcam_t *cam) {
|
|||
cam->buffer = NULL;
|
||||
}
|
||||
|
||||
// Hardware controls
|
||||
// TODO: : not implemented on macOS yet.
|
||||
// AVFoundation expose the equivalent knobs on AVCaptureDevice
|
||||
// (exposureMode/setExposureModeCustomWithDuration:ISO:, whiteBalanceMode/
|
||||
// setWhiteBalanceModeLocked:..., per-key-value-observed lockForConfiguration
|
||||
// dance), it needs its own implementation rather than
|
||||
// a thin wrapper
|
||||
// HACK: "unsupported" for now so callers (main.c) don't.
|
||||
// TODO: implement via AVCaptureDevice exposure/white-balance APIs.
|
||||
int webcam_set_auto_exposure(webcam_t *cam, int enable) {
|
||||
(void)cam;
|
||||
(void)enable;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int webcam_set_auto_white_balance(webcam_t *cam, int enable) {
|
||||
(void)cam;
|
||||
(void)enable;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int webcam_adjust_exposure(webcam_t *cam, int delta, int *out_value) {
|
||||
(void)cam;
|
||||
(void)delta;
|
||||
(void)out_value;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int webcam_adjust_contrast(webcam_t *cam, int delta, int *out_value) {
|
||||
(void)cam;
|
||||
(void)delta;
|
||||
(void)out_value;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int webcam_adjust_white_balance(webcam_t *cam, int delta, int *out_value) {
|
||||
(void)cam;
|
||||
(void)delta;
|
||||
(void)out_value;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int webcam_get_exposure(webcam_t *cam, int *value) {
|
||||
(void)cam;
|
||||
(void)value;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int webcam_get_contrast(webcam_t *cam, int *value) {
|
||||
(void)cam;
|
||||
(void)value;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int webcam_get_white_balance(webcam_t *cam, int *value) {
|
||||
(void)cam;
|
||||
(void)value;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int webcam_get_exposure_range(webcam_t *cam, int *min, int *max) {
|
||||
(void)cam;
|
||||
(void)min;
|
||||
(void)max;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int webcam_get_contrast_range(webcam_t *cam, int *min, int *max) {
|
||||
(void)cam;
|
||||
(void)min;
|
||||
(void)max;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int webcam_get_white_balance_range(webcam_t *cam, int *min, int *max) {
|
||||
(void)cam;
|
||||
(void)min;
|
||||
(void)max;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* PLATFORM_MACOS */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue