mirror of
https://github.com/pikvm/ustreamer.git
synced 2026-03-01 13:16:32 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8637ff5c09 | ||
|
|
bd5cf7d3de | ||
|
|
e488eec90c | ||
|
|
6615a23361 | ||
|
|
a91eba8d90 |
@@ -1,7 +1,7 @@
|
|||||||
[bumpversion]
|
[bumpversion]
|
||||||
commit = True
|
commit = True
|
||||||
tag = True
|
tag = True
|
||||||
current_version = 1.18
|
current_version = 1.19
|
||||||
parse = (?P<major>\d+)\.(?P<minor>\d+)(\.(?P<patch>\d+)(\-(?P<release>[a-z]+))?)?
|
parse = (?P<major>\d+)\.(?P<minor>\d+)(\.(?P<patch>\d+)(\-(?P<release>[a-z]+))?)?
|
||||||
serialize =
|
serialize =
|
||||||
{major}.{minor}
|
{major}.{minor}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
|
|
||||||
pkgname=ustreamer
|
pkgname=ustreamer
|
||||||
pkgver=1.18
|
pkgver=1.19
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="Lightweight and fast MJPG-HTTP streamer"
|
pkgdesc="Lightweight and fast MJPG-HTTP streamer"
|
||||||
url="https://github.com/pikvm/ustreamer"
|
url="https://github.com/pikvm/ustreamer"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=ustreamer
|
PKG_NAME:=ustreamer
|
||||||
PKG_VERSION:=1.18
|
PKG_VERSION:=1.19
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
PKG_MAINTAINER:=Maxim Devaev <mdevaev@gmail.com>
|
PKG_MAINTAINER:=Maxim Devaev <mdevaev@gmail.com>
|
||||||
|
|
||||||
|
|||||||
@@ -23,5 +23,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifndef VERSION
|
#ifndef VERSION
|
||||||
# define VERSION "1.18"
|
# define VERSION "1.19"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
112
src/device.c
112
src/device.c
@@ -67,13 +67,23 @@ static const struct {
|
|||||||
{"JPEG", V4L2_PIX_FMT_JPEG},
|
{"JPEG", V4L2_PIX_FMT_JPEG},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct {
|
||||||
|
const char *name;
|
||||||
|
const enum v4l2_memory io_method;
|
||||||
|
} _IO_METHODS[] = {
|
||||||
|
{"MMAP", V4L2_MEMORY_MMAP},
|
||||||
|
{"USERPTR", V4L2_MEMORY_USERPTR},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static int _device_open_check_cap(struct device_t *dev);
|
static int _device_open_check_cap(struct device_t *dev);
|
||||||
static int _device_open_dv_timings(struct device_t *dev);
|
static int _device_open_dv_timings(struct device_t *dev);
|
||||||
static int _device_apply_dv_timings(struct device_t *dev);
|
static int _device_apply_dv_timings(struct device_t *dev);
|
||||||
static int _device_open_format(struct device_t *dev);
|
static int _device_open_format(struct device_t *dev);
|
||||||
static void _device_open_hw_fps(struct device_t *dev);
|
static void _device_open_hw_fps(struct device_t *dev);
|
||||||
static int _device_open_mmap(struct device_t *dev);
|
static int _device_open_io_method(struct device_t *dev);
|
||||||
|
static int _device_open_io_method_mmap(struct device_t *dev);
|
||||||
|
static int _device_open_io_method_userptr(struct device_t *dev);
|
||||||
static int _device_open_queue_buffers(struct device_t *dev);
|
static int _device_open_queue_buffers(struct device_t *dev);
|
||||||
static void _device_open_alloc_picbufs(struct device_t *dev);
|
static void _device_open_alloc_picbufs(struct device_t *dev);
|
||||||
static int _device_apply_resolution(struct device_t *dev, unsigned width, unsigned height);
|
static int _device_apply_resolution(struct device_t *dev, unsigned width, unsigned height);
|
||||||
@@ -86,6 +96,7 @@ static const char *_format_to_string_fourcc(char *buf, size_t size, unsigned for
|
|||||||
static const char *_format_to_string_nullable(unsigned format);
|
static const char *_format_to_string_nullable(unsigned format);
|
||||||
static const char *_format_to_string_supported(unsigned format);
|
static const char *_format_to_string_supported(unsigned format);
|
||||||
static const char *_standard_to_string(v4l2_std_id standard);
|
static const char *_standard_to_string(v4l2_std_id standard);
|
||||||
|
static const char *_io_method_to_string_supported(enum v4l2_memory io_method);
|
||||||
|
|
||||||
|
|
||||||
struct device_t *device_init(void) {
|
struct device_t *device_init(void) {
|
||||||
@@ -111,6 +122,7 @@ struct device_t *device_init(void) {
|
|||||||
dev->n_workers = min_u(cores_available, dev->n_buffers);
|
dev->n_workers = min_u(cores_available, dev->n_buffers);
|
||||||
dev->timeout = 1;
|
dev->timeout = 1;
|
||||||
dev->error_delay = 1;
|
dev->error_delay = 1;
|
||||||
|
dev->io_method = V4L2_MEMORY_MMAP;
|
||||||
dev->run = run;
|
dev->run = run;
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
@@ -138,6 +150,15 @@ v4l2_std_id device_parse_standard(const char *str) {
|
|||||||
return STANDARD_UNKNOWN;
|
return STANDARD_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int device_parse_io_method(const char *str) {
|
||||||
|
for (unsigned index = 0; index < ARRAY_LEN(_IO_METHODS); ++index) {
|
||||||
|
if (!strcasecmp(str, _IO_METHODS[index].name)) {
|
||||||
|
return _IO_METHODS[index].io_method;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return IO_METHOD_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
int device_open(struct device_t *dev) {
|
int device_open(struct device_t *dev) {
|
||||||
if ((dev->run->fd = open(dev->path, O_RDWR|O_NONBLOCK)) < 0) {
|
if ((dev->run->fd = open(dev->path, O_RDWR|O_NONBLOCK)) < 0) {
|
||||||
LOG_PERROR("Can't open device");
|
LOG_PERROR("Can't open device");
|
||||||
@@ -155,7 +176,7 @@ int device_open(struct device_t *dev) {
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
_device_open_hw_fps(dev);
|
_device_open_hw_fps(dev);
|
||||||
if (_device_open_mmap(dev) < 0) {
|
if (_device_open_io_method(dev) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (_device_open_queue_buffers(dev) < 0) {
|
if (_device_open_queue_buffers(dev) < 0) {
|
||||||
@@ -187,13 +208,19 @@ void device_close(struct device_t *dev) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dev->run->hw_buffers) {
|
if (dev->run->hw_buffers) {
|
||||||
LOG_DEBUG("Unmapping HW buffers ...");
|
LOG_DEBUG("Releasing HW buffers ...");
|
||||||
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(allocated) > 0 && HW_BUFFER(data) != MAP_FAILED) {
|
if (dev->io_method == V4L2_MEMORY_MMAP) {
|
||||||
if (munmap(HW_BUFFER(data), HW_BUFFER(allocated)) < 0) {
|
if (HW_BUFFER(allocated) > 0 && HW_BUFFER(data) != MAP_FAILED) {
|
||||||
LOG_PERROR("Can't unmap device buffer %u", index);
|
if (munmap(HW_BUFFER(data), HW_BUFFER(allocated)) < 0) {
|
||||||
|
LOG_PERROR("Can't unmap device buffer %u", index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // V4L2_MEMORY_USERPTR
|
||||||
|
if (HW_BUFFER(data)) {
|
||||||
|
free(HW_BUFFER(data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,7 +298,7 @@ int device_grab_buffer(struct device_t *dev) {
|
|||||||
|
|
||||||
MEMSET_ZERO(buf_info);
|
MEMSET_ZERO(buf_info);
|
||||||
buf_info.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
buf_info.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
buf_info.memory = V4L2_MEMORY_MMAP;
|
buf_info.memory = dev->io_method;
|
||||||
|
|
||||||
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) {
|
||||||
@@ -465,6 +492,8 @@ static int _device_open_format(struct device_t *dev) {
|
|||||||
|
|
||||||
dev->run->format = fmt.fmt.pix.pixelformat;
|
dev->run->format = fmt.fmt.pix.pixelformat;
|
||||||
LOG_INFO("Using pixelformat: %s", _format_to_string_supported(dev->run->format));
|
LOG_INFO("Using pixelformat: %s", _format_to_string_supported(dev->run->format));
|
||||||
|
|
||||||
|
dev->run->raw_size = fmt.fmt.pix.sizeimage; // Only for userptr
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -510,7 +539,17 @@ static void _device_open_hw_fps(struct device_t *dev) {
|
|||||||
# undef SETFPS_TPF
|
# undef SETFPS_TPF
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _device_open_mmap(struct device_t *dev) {
|
static int _device_open_io_method(struct device_t *dev) {
|
||||||
|
LOG_INFO("Using IO method: %s", _io_method_to_string_supported(dev->io_method));
|
||||||
|
switch (dev->io_method) {
|
||||||
|
case V4L2_MEMORY_MMAP: return _device_open_io_method_mmap(dev);
|
||||||
|
case V4L2_MEMORY_USERPTR: return _device_open_io_method_userptr(dev);
|
||||||
|
default: assert(0 && "Unsupported IO method");
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _device_open_io_method_mmap(struct device_t *dev) {
|
||||||
struct v4l2_requestbuffers req;
|
struct v4l2_requestbuffers req;
|
||||||
|
|
||||||
MEMSET_ZERO(req);
|
MEMSET_ZERO(req);
|
||||||
@@ -518,9 +557,9 @@ static int _device_open_mmap(struct device_t *dev) {
|
|||||||
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
req.memory = V4L2_MEMORY_MMAP;
|
req.memory = V4L2_MEMORY_MMAP;
|
||||||
|
|
||||||
LOG_DEBUG("Calling ioctl(VIDIOC_REQBUFS) ...");
|
LOG_DEBUG("Calling ioctl(VIDIOC_REQBUFS) for V4L2_MEMORY_MMAP ...");
|
||||||
if (xioctl(dev->run->fd, VIDIOC_REQBUFS, &req) < 0) {
|
if (xioctl(dev->run->fd, VIDIOC_REQBUFS, &req) < 0) {
|
||||||
LOG_PERROR("Device '%s' doesn't support memory mapping", dev->path);
|
LOG_PERROR("Device '%s' doesn't support V4L2_MEMORY_MMAP", dev->path);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -563,14 +602,56 @@ static int _device_open_mmap(struct device_t *dev) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _device_open_io_method_userptr(struct device_t *dev) {
|
||||||
|
struct v4l2_requestbuffers req;
|
||||||
|
unsigned page_size = getpagesize();
|
||||||
|
unsigned buf_size = align_size(dev->run->raw_size, page_size);
|
||||||
|
|
||||||
|
MEMSET_ZERO(req);
|
||||||
|
req.count = dev->n_buffers;
|
||||||
|
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
|
req.memory = V4L2_MEMORY_USERPTR;
|
||||||
|
|
||||||
|
LOG_DEBUG("Calling ioctl(VIDIOC_REQBUFS) for V4L2_MEMORY_USERPTR ...");
|
||||||
|
if (xioctl(dev->run->fd, VIDIOC_REQBUFS, &req) < 0) {
|
||||||
|
LOG_PERROR("Device '%s' doesn't support V4L2_MEMORY_USERPTR", dev->path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.count < 1) {
|
||||||
|
LOG_ERROR("Insufficient buffer memory: %u", req.count);
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
LOG_INFO("Requested %u HW buffers, got %u", dev->n_buffers, req.count);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DEBUG("Allocating HW buffers ...");
|
||||||
|
|
||||||
|
A_CALLOC(dev->run->hw_buffers, req.count);
|
||||||
|
for (dev->run->n_buffers = 0; dev->run->n_buffers < req.count; ++dev->run->n_buffers) {
|
||||||
|
# define HW_BUFFER(_next) dev->run->hw_buffers[dev->run->n_buffers]._next
|
||||||
|
|
||||||
|
assert(HW_BUFFER(data) = aligned_alloc(page_size, buf_size));
|
||||||
|
memset(HW_BUFFER(data), 0, buf_size);
|
||||||
|
HW_BUFFER(allocated) = buf_size;
|
||||||
|
|
||||||
|
# undef HW_BUFFER
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int _device_open_queue_buffers(struct device_t *dev) {
|
static int _device_open_queue_buffers(struct device_t *dev) {
|
||||||
for (unsigned index = 0; index < dev->run->n_buffers; ++index) {
|
for (unsigned index = 0; index < dev->run->n_buffers; ++index) {
|
||||||
struct v4l2_buffer buf_info;
|
struct v4l2_buffer buf_info;
|
||||||
|
|
||||||
MEMSET_ZERO(buf_info);
|
MEMSET_ZERO(buf_info);
|
||||||
buf_info.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
buf_info.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
buf_info.memory = V4L2_MEMORY_MMAP;
|
buf_info.memory = dev->io_method;
|
||||||
buf_info.index = index;
|
buf_info.index = index;
|
||||||
|
if (dev->io_method == V4L2_MEMORY_USERPTR) {
|
||||||
|
buf_info.m.userptr = (unsigned long)dev->run->hw_buffers[index].data;
|
||||||
|
buf_info.length = dev->run->hw_buffers[index].allocated;
|
||||||
|
}
|
||||||
|
|
||||||
LOG_DEBUG("Calling ioctl(VIDIOC_QBUF) for buffer %u ...", index);
|
LOG_DEBUG("Calling ioctl(VIDIOC_QBUF) for buffer %u ...", index);
|
||||||
if (xioctl(dev->run->fd, VIDIOC_QBUF, &buf_info) < 0) {
|
if (xioctl(dev->run->fd, VIDIOC_QBUF, &buf_info) < 0) {
|
||||||
@@ -739,3 +820,12 @@ static const char *_standard_to_string(v4l2_std_id standard) {
|
|||||||
}
|
}
|
||||||
return _STANDARDS[0].name;
|
return _STANDARDS[0].name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *_io_method_to_string_supported(enum v4l2_memory io_method) {
|
||||||
|
for (unsigned index = 0; index < ARRAY_LEN(_IO_METHODS); ++index) {
|
||||||
|
if (io_method == _IO_METHODS[index].io_method) {
|
||||||
|
return _IO_METHODS[index].name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "unsupported";
|
||||||
|
}
|
||||||
|
|||||||
@@ -44,6 +44,9 @@
|
|||||||
#define FORMAT_UNKNOWN -1
|
#define FORMAT_UNKNOWN -1
|
||||||
#define FORMATS_STR "YUYV, UYVY, RGB565, RGB24, JPEG"
|
#define FORMATS_STR "YUYV, UYVY, RGB565, RGB24, JPEG"
|
||||||
|
|
||||||
|
#define IO_METHOD_UNKNOWN -1
|
||||||
|
#define IO_METHODS_STR "MMAP, USERPTR"
|
||||||
|
|
||||||
|
|
||||||
struct hw_buffer_t {
|
struct hw_buffer_t {
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
@@ -57,6 +60,7 @@ struct device_runtime_t {
|
|||||||
unsigned width;
|
unsigned width;
|
||||||
unsigned height;
|
unsigned height;
|
||||||
unsigned format;
|
unsigned format;
|
||||||
|
size_t raw_size;
|
||||||
unsigned n_buffers;
|
unsigned n_buffers;
|
||||||
unsigned n_workers;
|
unsigned n_workers;
|
||||||
struct hw_buffer_t *hw_buffers;
|
struct hw_buffer_t *hw_buffers;
|
||||||
@@ -95,6 +99,7 @@ struct device_t {
|
|||||||
unsigned height;
|
unsigned height;
|
||||||
unsigned format;
|
unsigned format;
|
||||||
v4l2_std_id standard;
|
v4l2_std_id standard;
|
||||||
|
enum v4l2_memory io_method;
|
||||||
bool dv_timings;
|
bool dv_timings;
|
||||||
unsigned n_buffers;
|
unsigned n_buffers;
|
||||||
unsigned n_workers;
|
unsigned n_workers;
|
||||||
@@ -115,6 +120,7 @@ void device_destroy(struct device_t *dev);
|
|||||||
|
|
||||||
int device_parse_format(const char *str);
|
int device_parse_format(const char *str);
|
||||||
v4l2_std_id device_parse_standard(const char *str);
|
v4l2_std_id device_parse_standard(const char *str);
|
||||||
|
int device_parse_io_method(const char *str);
|
||||||
|
|
||||||
int device_open(struct device_t *dev);
|
int device_open(struct device_t *dev);
|
||||||
void device_close(struct device_t *dev);
|
void device_close(struct device_t *dev);
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ enum _OPT_VALUES {
|
|||||||
_O_RESOLUTION = 'r',
|
_O_RESOLUTION = 'r',
|
||||||
_O_FORMAT = 'm',
|
_O_FORMAT = 'm',
|
||||||
_O_TV_STANDARD = 'a',
|
_O_TV_STANDARD = 'a',
|
||||||
|
_O_IO_METHOD = 'I',
|
||||||
_O_DESIRED_FPS = 'f',
|
_O_DESIRED_FPS = 'f',
|
||||||
_O_MIN_FRAME_SIZE = 'z',
|
_O_MIN_FRAME_SIZE = 'z',
|
||||||
_O_PERSISTENT = 'n',
|
_O_PERSISTENT = 'n',
|
||||||
@@ -128,6 +129,7 @@ static const struct option _LONG_OPTS[] = {
|
|||||||
{"resolution", required_argument, NULL, _O_RESOLUTION},
|
{"resolution", required_argument, NULL, _O_RESOLUTION},
|
||||||
{"format", required_argument, NULL, _O_FORMAT},
|
{"format", required_argument, NULL, _O_FORMAT},
|
||||||
{"tv-standard", required_argument, NULL, _O_TV_STANDARD},
|
{"tv-standard", required_argument, NULL, _O_TV_STANDARD},
|
||||||
|
{"io-method", required_argument, NULL, _O_IO_METHOD},
|
||||||
{"desired-fps", required_argument, NULL, _O_DESIRED_FPS},
|
{"desired-fps", required_argument, NULL, _O_DESIRED_FPS},
|
||||||
{"min-frame-size", required_argument, NULL, _O_MIN_FRAME_SIZE},
|
{"min-frame-size", required_argument, NULL, _O_MIN_FRAME_SIZE},
|
||||||
{"persistent", no_argument, NULL, _O_PERSISTENT},
|
{"persistent", no_argument, NULL, _O_PERSISTENT},
|
||||||
@@ -327,6 +329,7 @@ int options_parse(struct options_t *options, struct device_t *dev, struct encode
|
|||||||
case _O_FORMAT: OPT_PARSE("pixel format", dev->format, device_parse_format, FORMAT_UNKNOWN, FORMATS_STR);
|
case _O_FORMAT: OPT_PARSE("pixel format", dev->format, device_parse_format, FORMAT_UNKNOWN, FORMATS_STR);
|
||||||
# pragma GCC diagnostic pop
|
# pragma GCC diagnostic pop
|
||||||
case _O_TV_STANDARD: OPT_PARSE("TV standard", dev->standard, device_parse_standard, STANDARD_UNKNOWN, STANDARDS_STR);
|
case _O_TV_STANDARD: OPT_PARSE("TV standard", dev->standard, device_parse_standard, STANDARD_UNKNOWN, STANDARDS_STR);
|
||||||
|
case _O_IO_METHOD: OPT_PARSE("IO method", dev->io_method, device_parse_io_method, IO_METHOD_UNKNOWN, IO_METHODS_STR);
|
||||||
case _O_DESIRED_FPS: OPT_NUMBER("--desired-fps", dev->desired_fps, 0, VIDEO_MAX_FPS, 0);
|
case _O_DESIRED_FPS: OPT_NUMBER("--desired-fps", dev->desired_fps, 0, VIDEO_MAX_FPS, 0);
|
||||||
case _O_MIN_FRAME_SIZE: OPT_NUMBER("--min-frame-size", dev->min_frame_size, 0, 8192, 0);
|
case _O_MIN_FRAME_SIZE: OPT_NUMBER("--min-frame-size", dev->min_frame_size, 0, 8192, 0);
|
||||||
case _O_PERSISTENT: OPT_SET(dev->persistent, true);
|
case _O_PERSISTENT: OPT_SET(dev->persistent, true);
|
||||||
@@ -548,6 +551,9 @@ static void _help(struct device_t *dev, struct encoder_t *encoder, struct http_s
|
|||||||
printf(" Available: %s; default: YUYV.\n\n", FORMATS_STR);
|
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(" Available: %s; default: disabled.\n\n", STANDARDS_STR);
|
||||||
|
printf(" -I|--io-method <method> ───────────── Set V4L2 IO method (see kernel documentation).\n");
|
||||||
|
printf(" Changing of this parameter may increase the performance. Or not.\n");
|
||||||
|
printf(" Available: %s; default: MMAP\n\n", IO_METHODS_STR);
|
||||||
printf(" -f|--desired-fps <N> ──────────────── Desired FPS. Default: maximum possible.\n\n");
|
printf(" -f|--desired-fps <N> ──────────────── Desired FPS. Default: maximum possible.\n\n");
|
||||||
printf(" -z|--min-frame-size <N> ───────────── Drop frames smaller then this limit. Useful if the device\n");
|
printf(" -z|--min-frame-size <N> ───────────── Drop frames smaller then this limit. Useful if the device\n");
|
||||||
printf(" produces small-sized garbage frames. Default: disabled.\n\n");
|
printf(" produces small-sized garbage frames. Default: disabled.\n\n");
|
||||||
|
|||||||
@@ -73,9 +73,7 @@ void picture_append_data(struct picture_t *picture, const unsigned char *data, s
|
|||||||
}
|
}
|
||||||
|
|
||||||
void picture_copy(const struct picture_t *src, struct picture_t *dest) {
|
void picture_copy(const struct picture_t *src, struct picture_t *dest) {
|
||||||
assert(src->allocated);
|
picture_set_data(dest, src->data, src->used);
|
||||||
|
|
||||||
picture_set_data(dest, src->data, src->allocated);
|
|
||||||
|
|
||||||
# define COPY(_field) dest->_field = src->_field
|
# define COPY(_field) dest->_field = src->_field
|
||||||
|
|
||||||
@@ -92,5 +90,9 @@ void picture_copy(const struct picture_t *src, struct picture_t *dest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool picture_compare(const struct picture_t *a, const struct picture_t *b) {
|
bool picture_compare(const struct picture_t *a, const struct picture_t *b) {
|
||||||
return (a->used == b->used && !memcmp(a->data, b->data, b->used));
|
return (
|
||||||
|
a->allocated && b->allocated
|
||||||
|
&& a->used == b->used
|
||||||
|
&& !memcmp(a->data, b->data, b->used)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user