mirror of
https://github.com/pikvm/ustreamer.git
synced 2026-02-20 16:56:30 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3104a00913 | ||
|
|
28c51f3f2f | ||
|
|
5c035f21c8 | ||
|
|
52ecaf7fd3 | ||
|
|
aa007c676f | ||
|
|
1f0b49e5fe |
@@ -1,7 +1,7 @@
|
||||
[bumpversion]
|
||||
commit = True
|
||||
tag = True
|
||||
current_version = 0.57
|
||||
current_version = 0.58
|
||||
parse = (?P<major>\d+)\.(?P<minor>\d+)(\.(?P<patch>\d+)(\-(?P<release>[a-z]+))?)?
|
||||
serialize =
|
||||
{major}.{minor}
|
||||
|
||||
2
PKGBUILD
2
PKGBUILD
@@ -3,7 +3,7 @@
|
||||
|
||||
|
||||
pkgname=ustreamer
|
||||
pkgver=0.57
|
||||
pkgver=0.58
|
||||
pkgrel=1
|
||||
pkgdesc="Lightweight and fast MJPG-HTTP streamer"
|
||||
url="https://github.com/pi-kvm/ustreamer"
|
||||
|
||||
@@ -22,4 +22,4 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define VERSION "0.57"
|
||||
#define VERSION "0.58"
|
||||
|
||||
67
src/device.c
67
src/device.c
@@ -95,7 +95,7 @@ struct device_t *device_init() {
|
||||
dev->height = 480;
|
||||
dev->format = V4L2_PIX_FMT_YUYV;
|
||||
dev->standard = V4L2_STD_UNKNOWN;
|
||||
dev->n_buffers = max_u(sysconf(_SC_NPROCESSORS_ONLN), 1) + 1;
|
||||
dev->n_buffers = max_u(min_u(sysconf(_SC_NPROCESSORS_ONLN), 4), 1) + 1;
|
||||
dev->n_workers = dev->n_buffers;
|
||||
dev->timeout = 1;
|
||||
dev->error_delay = 1;
|
||||
@@ -201,6 +201,71 @@ void device_close(struct device_t *dev) {
|
||||
}
|
||||
}
|
||||
|
||||
int device_switch_capturing(struct device_t *dev, bool enable) {
|
||||
if (enable != dev->run->capturing) {
|
||||
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
|
||||
LOG_DEBUG("Calling ioctl(%s) ...", (enable ? "VIDIOC_STREAMON" : "VIDIOC_STREAMOFF"));
|
||||
if (xioctl(dev->run->fd, (enable ? VIDIOC_STREAMON : VIDIOC_STREAMOFF), &type) < 0) {
|
||||
LOG_PERROR("Unable to %s capturing", (enable ? "start" : "stop"));
|
||||
if (enable) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
dev->run->capturing = enable;
|
||||
LOG_INFO("Capturing %s", (enable ? "started" : "stopped"));
|
||||
}
|
||||
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;
|
||||
|
||||
LOG_DEBUG("Calling ioctl(VIDIOC_DQBUF) ...");
|
||||
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);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int device_release_buffer(struct device_t *dev, struct v4l2_buffer *buf_info) {
|
||||
LOG_DEBUG("Calling ioctl(VIDIOC_QBUF) ...");
|
||||
if (xioctl(dev->run->fd, VIDIOC_QBUF, buf_info) < 0) {
|
||||
LOG_PERROR("Unable to requeue buffer");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int device_consume_event(struct device_t *dev) {
|
||||
struct v4l2_event event;
|
||||
|
||||
LOG_DEBUG("Calling ioctl(VIDIOC_DQEVENT) ...");
|
||||
if (!xioctl(dev->run->fd, VIDIOC_DQEVENT, &event)) {
|
||||
switch (event.type) {
|
||||
case V4L2_EVENT_SOURCE_CHANGE:
|
||||
LOG_INFO("Got V4L2_EVENT_SOURCE_CHANGE: source changed");
|
||||
return -1;
|
||||
case V4L2_EVENT_EOS:
|
||||
LOG_INFO("Got V4L2_EVENT_EOS: end of stream (ignored)");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
LOG_PERROR("Got some V4L2 device event, but where is it? ");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _device_open_check_cap(struct device_t *dev) {
|
||||
struct v4l2_capability cap;
|
||||
int input = dev->input; // Needs pointer to int for ioctl()
|
||||
|
||||
@@ -116,3 +116,8 @@ v4l2_std_id device_parse_standard(const char *str);
|
||||
|
||||
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_consume_event(struct device_t *dev);
|
||||
|
||||
111
src/main.c
111
src/main.c
@@ -41,7 +41,7 @@
|
||||
#include "http.h"
|
||||
|
||||
|
||||
static const char _SHORT_OPTS[] = "d:i:x:y:m:a:f:z:ntb:w:q:c:s:p:u:ro:e:h";
|
||||
static const char _SHORT_OPTS[] = "d:i:x:y:m:a:f:z:ntb:w:q:c:s:p:u:ro:e:lhv";
|
||||
static const struct option _LONG_OPTS[] = {
|
||||
{"device", required_argument, NULL, 'd'},
|
||||
{"input", required_argument, NULL, 'i'},
|
||||
@@ -80,7 +80,7 @@ static const struct option _LONG_OPTS[] = {
|
||||
{"unix-rm", no_argument, NULL, 'r'},
|
||||
{"unix-mode", required_argument, NULL, 'o'},
|
||||
{"drop-same-frames", required_argument, NULL, 'e'},
|
||||
{"slowdown", no_argument, NULL, 3000},
|
||||
{"slowdown", no_argument, NULL, 'l'},
|
||||
{"fake-width", required_argument, NULL, 3001},
|
||||
{"fake-height", required_argument, NULL, 3002},
|
||||
{"server-timeout", required_argument, NULL, 3003},
|
||||
@@ -90,7 +90,7 @@ static const struct option _LONG_OPTS[] = {
|
||||
{"debug", no_argument, NULL, 5002},
|
||||
{"log-level", required_argument, NULL, 5010},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"version", no_argument, NULL, 6000},
|
||||
{"version", no_argument, NULL, 'v'},
|
||||
{NULL, 0, NULL, 0},
|
||||
};
|
||||
|
||||
@@ -106,78 +106,79 @@ static void _version(bool nl) {
|
||||
|
||||
static void _help(struct device_t *dev, struct encoder_t *encoder, struct http_server_t *server) {
|
||||
printf("\nuStreamer - Lightweight and fast MJPG-HTTP streamer\n");
|
||||
printf("===================================================\n\n");
|
||||
printf("═══════════════════════════════════════════════════\n\n");
|
||||
printf("Version: ");
|
||||
_version(false);
|
||||
printf("; license: GPLv3\n");
|
||||
printf("Copyright (C) 2018 Maxim Devaev <mdevaev@gmail.com>\n\n");
|
||||
printf("Capturing options:\n");
|
||||
printf("------------------\n");
|
||||
printf(" -d|--device </dev/path> -- Path to V4L2 device. Default: %s.\n\n", dev->path);
|
||||
printf(" -i|--input <N> -- Input channel. Default: %u.\n\n", dev->input);
|
||||
printf(" -x|--width <N> -- Initial image width. Default: %u.\n\n", dev->width);
|
||||
printf(" -y|--height <N> -- Initial image height. Default: %u.\n\n", dev->height);
|
||||
printf(" -m|--format <fmt> -- Image format.\n");
|
||||
printf("══════════════════\n");
|
||||
printf(" -d|--device </dev/path> ──────── Path to V4L2 device. Default: %s.\n\n", dev->path);
|
||||
printf(" -i|--input <N> ───────────────── Input channel. Default: %u.\n\n", dev->input);
|
||||
printf(" -x|--width <N> ───────────────── Initial image width. Default: %u.\n\n", dev->width);
|
||||
printf(" -y|--height <N> ──────────────── Initial image height. Default: %u.\n\n", dev->height);
|
||||
printf(" -m|--format <fmt> ────────────── Image format.\n");
|
||||
printf(" Available: %s; default: YUYV.\n\n", FORMATS_STR);
|
||||
printf(" -a|--tv-standard <std> -- Force TV standard.\n");
|
||||
printf(" -a|--tv-standard <std> ───────── Force TV standard.\n");
|
||||
printf(" Available: %s; default: disabled.\n\n", STANDARDS_STR);
|
||||
printf(" -f|--desired-fps <N> -- Desired FPS. Default: maximum as possible.\n\n");
|
||||
printf(" -z|--min-frame-size <N> -- Drop frames smaller then this limit.\n");
|
||||
printf(" -f|--desired-fps <N> ─────────── Desired FPS. Default: maximum as possible.\n\n");
|
||||
printf(" -z|--min-frame-size <N> ──────── Drop frames smaller then this limit.\n");
|
||||
printf(" Useful if the device produces small-sized garbage frames.\n\n");
|
||||
printf(" -n|--persistent -- Don't re-initialize device on timeout. Default: disabled.\n\n");
|
||||
printf(" -t|--dv-timings -- Enable DV timings queriyng and events processing.\n");
|
||||
printf(" -n|--persistent ──────────────── Don't re-initialize device on timeout. Default: disabled.\n\n");
|
||||
printf(" -t|--dv-timings ──────────────── Enable DV timings queriyng and events processing.\n");
|
||||
printf(" Supports automatic resolution changing. Default: disabled.\n\n");
|
||||
printf(" -b|--buffers <N> -- The number of buffers to receive data from the device.\n");
|
||||
printf(" -b|--buffers <N> ─────────────── The number of buffers to receive data from the device.\n");
|
||||
printf(" Each buffer may processed using an intermediate thread.\n");
|
||||
printf(" Default: %u (number of CPU cores + 1)\n\n", dev->n_buffers);
|
||||
printf(" -w|--workers <N> -- The number of compressing threads. Default: %u (== --buffers).\n\n", dev->n_workers);
|
||||
printf(" -q|--quality <N> -- Set quality of JPEG encoding from 1 to 100 (best). Default: %u.\n\n", encoder->quality);
|
||||
printf(" -c|--encoder <type> -- Use specified encoder. It may affects to workers number.\n");
|
||||
printf(" -- Available: %s; default: CPU.\n\n", ENCODER_TYPES_STR);
|
||||
printf(" --device-timeout <seconds> -- Timeout for device querying. Default: %u\n\n", dev->timeout);
|
||||
printf(" --device-error-delay <seconds> -- Delay before trying to connect to the device again\n");
|
||||
printf(" Default: %u (the number of CPU cores (but not more 4) + 1)\n\n", dev->n_buffers);
|
||||
printf(" -w|--workers <N> ─────────────── The number of worker threads. Default: %u (== --buffers).\n\n", dev->n_workers);
|
||||
printf(" -q|--quality <N> ─────────────── Set quality of JPEG encoding from 1 to 100 (best). Default: %u.\n\n", encoder->quality);
|
||||
printf(" -c|--encoder <type> ──────────── Use specified encoder. It may affects to workers number.\n");
|
||||
printf(" Available: %s; default: CPU.\n\n", ENCODER_TYPES_STR);
|
||||
printf(" --device-timeout <seconds> ───── Timeout for device querying. Default: %u\n\n", dev->timeout);
|
||||
printf(" --device-error-delay <seconds> ─ Delay before trying to connect to the device again\n");
|
||||
printf(" after timeout. Default: %u\n\n", dev->error_delay);
|
||||
printf("Image control options:\n");
|
||||
printf("---------------\n");
|
||||
printf(" --brightness <N> -- Set brightness. Default: no change.\n\n");
|
||||
printf(" --brightness-auto -- Enable automatic brightness control. Default: no change.\n\n");
|
||||
printf(" --contrast <N> -- Set contrast. Default: no change.\n\n");
|
||||
printf(" --saturation <N> -- Set saturation. Default: no change.\n\n");
|
||||
printf(" --hue <N> -- Set hue. Default: no change.\n\n");
|
||||
printf(" --hue-auto -- Enable automatic hue control. Default: no change.\n\n");
|
||||
printf(" --gamma <N> -- Set gamma. Default: no change.\n\n");
|
||||
printf(" --sharpness <N> -- Set sharpness. Default: no change.\n\n");
|
||||
printf(" --backlight-compensation <N> -- Set backlight compensation. Default: no change.\n\n");
|
||||
printf(" --white-balance <N> -- Set white balance. Default: no change.\n\n");
|
||||
printf(" --white-balance-auto -- Enable automatic white balance control. Default: no change.\n\n");
|
||||
printf(" --gain <N> -- Set gain. Default: no change.\n\n");
|
||||
printf(" --gain-auto -- Enable automatic gain control. Default: no change.\n\n");
|
||||
printf("══════════════════════\n");
|
||||
printf(" --brightness <N> ───────────── Set brightness. Default: no change.\n\n");
|
||||
printf(" --brightness-auto ──────────── Enable automatic brightness control. Default: no change.\n\n");
|
||||
printf(" --contrast <N> ─────────────── Set contrast. Default: no change.\n\n");
|
||||
printf(" --saturation <N> ───────────── Set saturation. Default: no change.\n\n");
|
||||
printf(" --hue <N> ──────────────────── Set hue. Default: no change.\n\n");
|
||||
printf(" --hue-auto ─────────────────── Enable automatic hue control. Default: no change.\n\n");
|
||||
printf(" --gamma <N> ────────────────── Set gamma. Default: no change.\n\n");
|
||||
printf(" --sharpness <N> ────────────── Set sharpness. Default: no change.\n\n");
|
||||
printf(" --backlight-compensation <N> ─ Set backlight compensation. Default: no change.\n\n");
|
||||
printf(" --white-balance <N> ────────── Set white balance. Default: no change.\n\n");
|
||||
printf(" --white-balance-auto ───────── Enable automatic white balance control. Default: no change.\n\n");
|
||||
printf(" --gain <N> ─────────────────── Set gain. Default: no change.\n\n");
|
||||
printf(" --gain-auto ────────────────── Enable automatic gain control. Default: no change.\n\n");
|
||||
printf("HTTP server options:\n");
|
||||
printf("--------------------\n");
|
||||
printf(" -s|--host <address> -- Listen on Hostname or IP. Default: %s\n\n", server->host);
|
||||
printf(" -p|--port <N> -- Bind to this TCP port. Default: %u\n\n", server->port);
|
||||
printf(" -u|--unix <path> -- Bind to UNIX domain socket. Default: disabled\n\n");
|
||||
printf(" -r|--unix-rm -- Try to remove old UNIX socket file before binding. Default: disabled\n\n");
|
||||
printf(" -o|--unix-mode <mode> -- Set UNIX socket file permissions (like 777). Default: disabled\n\n");
|
||||
printf(" -e|--drop-same-frames <N> -- Don't send same frames to clients, but no more than specified number.\n");
|
||||
printf("════════════════════\n");
|
||||
printf(" -s|--host <address> ──────── Listen on Hostname or IP. Default: %s\n\n", server->host);
|
||||
printf(" -p|--port <N> ────────────── Bind to this TCP port. Default: %u\n\n", server->port);
|
||||
printf(" -u|--unix <path> ─────────── Bind to UNIX domain socket. Default: disabled\n\n");
|
||||
printf(" -r|--unix-rm ─────────────── Try to remove old UNIX socket file before binding. Default: disabled\n\n");
|
||||
printf(" -o|--unix-mode <mode> ────── Set UNIX socket file permissions (like 777). Default: disabled\n\n");
|
||||
printf(" -e|--drop-same-frames <N> ── Don't send same frames to clients, but no more than specified number.\n");
|
||||
printf(" It can significantly reduce the outgoing traffic, but will increase\n");
|
||||
printf(" the CPU loading. Don't use this option with analog signal sources\n");
|
||||
printf(" or webcams, it's useless. Default: disabled.\n\n");
|
||||
printf(" --slowdown -- Slowdown capturing to 1 FPS or less when no stream clients connected.\n");
|
||||
printf(" -l|--slowdown ────────────── Slowdown capturing to 1 FPS or less when no stream clients connected.\n");
|
||||
printf(" Useful to reduce CPU cosumption. Default: disabled.\n\n");
|
||||
printf(" --fake-width <N> -- Override image width for /state. Default: disabled\n\n");
|
||||
printf(" --fake-height <N> -- Override image height for /state. Default: disabled.\n\n");
|
||||
printf(" --server-timeout <seconds> -- Timeout for client connections. Default: %u\n\n", server->timeout);
|
||||
printf(" --fake-width <N> ─────────── Override image width for /state. Default: disabled\n\n");
|
||||
printf(" --fake-height <N> ────────── Override image height for /state. Default: disabled.\n\n");
|
||||
printf(" --server-timeout <seconds> ─ Timeout for client connections. Default: %u\n\n", server->timeout);
|
||||
printf("Misc options:\n");
|
||||
printf("-------------\n");
|
||||
printf(" --log-level <N> -- Verbosity level of messages from 0 (info) to 3 (debug).\n");
|
||||
printf("═════════════\n");
|
||||
printf(" --log-level <N> ─ Verbosity level of messages from 0 (info) to 3 (debug).\n");
|
||||
printf(" Enabling debugging messages can slow down the program.\n");
|
||||
printf(" Available levels: 0=info, 1=performance, 2=verbose, 3=debug.\n");
|
||||
printf(" Default: %u.\n\n", log_level);
|
||||
printf(" --perf -- Enable performance messages (same as --log-level=1). Default: disabled.\n\n");
|
||||
printf(" --verbose -- Enable verbose messages and lower (same as --log-level=2). Default: disabled.\n\n");
|
||||
printf(" --debug -- Enable debug messages and lower (same as --log-level=3). Default: disabled.\n\n");
|
||||
printf(" -h|--help -- Print this messages and exit.\n\n");
|
||||
printf(" --perf ────────── Enable performance messages (same as --log-level=1). Default: disabled.\n\n");
|
||||
printf(" --verbose ─────── Enable verbose messages and lower (same as --log-level=2). Default: disabled.\n\n");
|
||||
printf(" --debug ───────── Enable debug messages and lower (same as --log-level=3). Default: disabled.\n\n");
|
||||
printf(" -h|--help ─────── Print this text and exit.\n\n");
|
||||
printf(" -v|--version ──── Print version and exit.\n\n");
|
||||
}
|
||||
|
||||
static int _parse_options(int argc, char *argv[], struct device_t *dev, struct encoder_t *encoder, struct http_server_t *server) {
|
||||
@@ -284,7 +285,7 @@ static int _parse_options(int argc, char *argv[], struct device_t *dev, struct e
|
||||
case 5002: OPT_SET(log_level, LOG_LEVEL_DEBUG);
|
||||
case 5010: OPT_UNSIGNED(log_level, "--log-level", 0, 3);
|
||||
case 'h': _help(dev, encoder, server); return 1;
|
||||
case 6000: _version(true); return 1;
|
||||
case 'v': _version(true); return 1;
|
||||
case 0: break;
|
||||
default: _help(dev, encoder, server); return -1;
|
||||
}
|
||||
|
||||
84
src/stream.c
84
src/stream.c
@@ -49,11 +49,6 @@ static void _stream_init_workers(struct stream_t *stream, struct workers_pool_t
|
||||
static void *_stream_worker_thread(void *v_worker);
|
||||
static void _stream_destroy_workers(struct stream_t *stream, struct workers_pool_t *pool);
|
||||
|
||||
static int _stream_control(struct device_t *dev, bool enable);
|
||||
static int _stream_grab_buffer(struct device_t *dev, struct v4l2_buffer *buf_info);
|
||||
static int _stream_release_buffer(struct device_t *dev, struct v4l2_buffer *buf_info);
|
||||
static int _stream_handle_event(struct device_t *dev);
|
||||
|
||||
|
||||
struct stream_t *stream_init(struct device_t *dev, struct encoder_t *encoder) {
|
||||
struct process_t *proc;
|
||||
@@ -195,7 +190,7 @@ void stream_loop(struct stream_t *stream) {
|
||||
long double now = get_now_monotonic();
|
||||
long long now_second = floor_ms(now);
|
||||
|
||||
if (_stream_grab_buffer(stream->dev, &buf_info) < 0) {
|
||||
if (device_grab_buffer(stream->dev, &buf_info) < 0) {
|
||||
break;
|
||||
}
|
||||
stream->dev->run->pictures[buf_info.index].grab_time = now;
|
||||
@@ -269,7 +264,7 @@ void stream_loop(struct stream_t *stream) {
|
||||
|
||||
pass_frame:
|
||||
|
||||
if (_stream_release_buffer(stream->dev, &buf_info) < 0) {
|
||||
if (device_release_buffer(stream->dev, &buf_info) < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -283,7 +278,7 @@ void stream_loop(struct stream_t *stream) {
|
||||
|
||||
if (FD_ISSET(stream->dev->run->fd, &error_fds)) {
|
||||
LOG_INFO("Got V4L2 event");
|
||||
if (_stream_handle_event(stream->dev) < 0) {
|
||||
if (device_consume_event(stream->dev) < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -300,7 +295,7 @@ void stream_loop(struct stream_t *stream) {
|
||||
}
|
||||
|
||||
_stream_destroy_workers(stream, &pool);
|
||||
_stream_control(stream->dev, false);
|
||||
device_switch_capturing(stream->dev, false);
|
||||
device_close(stream->dev);
|
||||
}
|
||||
|
||||
@@ -384,13 +379,13 @@ static int _stream_init(struct stream_t *stream, struct workers_pool_t *pool) {
|
||||
SEP_INFO('=');
|
||||
|
||||
_stream_destroy_workers(stream, pool);
|
||||
_stream_control(stream->dev, false);
|
||||
device_switch_capturing(stream->dev, false);
|
||||
device_close(stream->dev);
|
||||
|
||||
if (device_open(stream->dev) < 0) {
|
||||
goto error;
|
||||
}
|
||||
if (_stream_control(stream->dev, true) < 0) {
|
||||
if (device_switch_capturing(stream->dev, true) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -462,7 +457,7 @@ static void *_stream_worker_thread(void *v_worker) {
|
||||
}
|
||||
PICTURE(encode_end_time) = get_now_monotonic();
|
||||
|
||||
if (_stream_release_buffer(worker->dev, &worker->buf_info) == 0) {
|
||||
if (device_release_buffer(worker->dev, &worker->buf_info) == 0) {
|
||||
worker->job_start_time = PICTURE(encode_begin_time);
|
||||
atomic_store(&worker->has_job, false);
|
||||
|
||||
@@ -520,68 +515,3 @@ static void _stream_destroy_workers(struct stream_t *stream, struct workers_pool
|
||||
pool->free_workers = 0;
|
||||
pool->workers = NULL;
|
||||
}
|
||||
|
||||
static int _stream_control(struct device_t *dev, bool enable) {
|
||||
if (enable != dev->run->capturing) {
|
||||
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
|
||||
LOG_DEBUG("Calling ioctl(%s) ...", (enable ? "VIDIOC_STREAMON" : "VIDIOC_STREAMOFF"));
|
||||
if (xioctl(dev->run->fd, (enable ? VIDIOC_STREAMON : VIDIOC_STREAMOFF), &type) < 0) {
|
||||
LOG_PERROR("Unable to %s capturing", (enable ? "start" : "stop"));
|
||||
if (enable) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
dev->run->capturing = enable;
|
||||
LOG_INFO("Capturing %s", (enable ? "started" : "stopped"));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _stream_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;
|
||||
|
||||
LOG_DEBUG("Calling ioctl(VIDIOC_DQBUF) ...");
|
||||
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);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _stream_release_buffer(struct device_t *dev, struct v4l2_buffer *buf_info) {
|
||||
LOG_DEBUG("Calling ioctl(VIDIOC_QBUF) ...");
|
||||
if (xioctl(dev->run->fd, VIDIOC_QBUF, buf_info) < 0) {
|
||||
LOG_PERROR("Unable to requeue buffer");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _stream_handle_event(struct device_t *dev) {
|
||||
struct v4l2_event event;
|
||||
|
||||
LOG_DEBUG("Calling ioctl(VIDIOC_DQEVENT) ...");
|
||||
if (!xioctl(dev->run->fd, VIDIOC_DQEVENT, &event)) {
|
||||
switch (event.type) {
|
||||
case V4L2_EVENT_SOURCE_CHANGE:
|
||||
LOG_INFO("Got V4L2_EVENT_SOURCE_CHANGE: source changed");
|
||||
return -1;
|
||||
case V4L2_EVENT_EOS:
|
||||
LOG_INFO("Got V4L2_EVENT_EOS: end of stream (ignored)");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
LOG_PERROR("Got some V4L2 device event, but where is it? ");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -63,12 +63,16 @@ INLINE char *bool_to_string(bool flag) {
|
||||
return (flag ? "true" : "false");
|
||||
}
|
||||
|
||||
INLINE unsigned min_u(unsigned a, unsigned b) {
|
||||
return (a < b ? a : b);
|
||||
}
|
||||
|
||||
INLINE unsigned max_u(unsigned a, unsigned b) {
|
||||
return (a > b ? a : b);
|
||||
}
|
||||
|
||||
INLINE long long floor_ms(long double now) {
|
||||
return (long long) now - (now < (long long) now); // floor()
|
||||
return (long long)now - (now < (long long)now); // floor()
|
||||
}
|
||||
|
||||
INLINE void get_now(clockid_t clk_id, time_t *sec, long *msec) {
|
||||
|
||||
Reference in New Issue
Block a user