mirror of
https://github.com/pikvm/ustreamer.git
synced 2026-02-27 12:16:31 +00:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b08857534 | ||
|
|
eec19892fa | ||
|
|
40abe73391 | ||
|
|
e4f1ef654f | ||
|
|
fa6afb96ce | ||
|
|
c3f98b34f2 | ||
|
|
b7b3e8e87d | ||
|
|
94383a2d54 | ||
|
|
184a4879eb | ||
|
|
bf48908c59 | ||
|
|
66afbccf21 | ||
|
|
97dbe59aea | ||
|
|
d874fdeaec | ||
|
|
97e3938d56 | ||
|
|
87c7e8063f | ||
|
|
fe5beb0114 |
@@ -1,7 +1,7 @@
|
|||||||
[bumpversion]
|
[bumpversion]
|
||||||
commit = True
|
commit = True
|
||||||
tag = True
|
tag = True
|
||||||
current_version = 3.6
|
current_version = 3.8
|
||||||
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}
|
||||||
@@ -10,7 +10,7 @@ serialize =
|
|||||||
search = VERSION "{current_version}"
|
search = VERSION "{current_version}"
|
||||||
replace = VERSION "{new_version}"
|
replace = VERSION "{new_version}"
|
||||||
|
|
||||||
[bumpversion:file:src/python/setup.py]
|
[bumpversion:file:python/setup.py]
|
||||||
search = version="{current_version}"
|
search = version="{current_version}"
|
||||||
replace = version="{new_version}"
|
replace = version="{new_version}"
|
||||||
|
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -6,8 +6,10 @@
|
|||||||
/pkg/arch/ustreamer-*.pkg.tar.xz
|
/pkg/arch/ustreamer-*.pkg.tar.xz
|
||||||
/pkg/arch/ustreamer-*.pkg.tar.zst
|
/pkg/arch/ustreamer-*.pkg.tar.zst
|
||||||
/build/
|
/build/
|
||||||
|
/python/build/
|
||||||
/config.mk
|
/config.mk
|
||||||
/vgcore.*
|
/vgcore.*
|
||||||
/ustreamer
|
/ustreamer
|
||||||
/ustreamer-dump
|
/ustreamer-dump
|
||||||
|
/*.so
|
||||||
/*.sock
|
/*.sock
|
||||||
|
|||||||
14
Makefile
14
Makefile
@@ -7,6 +7,7 @@ PREFIX ?= /usr/local
|
|||||||
MANPREFIX ?= $(PREFIX)/share/man
|
MANPREFIX ?= $(PREFIX)/share/man
|
||||||
|
|
||||||
CC ?= gcc
|
CC ?= gcc
|
||||||
|
PY ?= python3
|
||||||
CFLAGS ?= -O3 -MD
|
CFLAGS ?= -O3 -MD
|
||||||
LDFLAGS ?=
|
LDFLAGS ?=
|
||||||
|
|
||||||
@@ -87,10 +88,10 @@ install: $(USTR) $(DUMP)
|
|||||||
install -m755 $(DUMP) $(DESTDIR)$(PREFIX)/bin/$(DUMP)
|
install -m755 $(DUMP) $(DESTDIR)$(PREFIX)/bin/$(DUMP)
|
||||||
install -m644 man/$(USTR).1 $(DESTDIR)$(MANPREFIX)/man1/$(USTR).1
|
install -m644 man/$(USTR).1 $(DESTDIR)$(MANPREFIX)/man1/$(USTR).1
|
||||||
install -m644 man/$(DUMP).1 $(DESTDIR)$(MANPREFIX)/man1/$(DUMP).1
|
install -m644 man/$(DUMP).1 $(DESTDIR)$(MANPREFIX)/man1/$(DUMP).1
|
||||||
gzip $(DESTDIR)$(MANPREFIX)/man1/$(USTR).1
|
gzip -f $(DESTDIR)$(MANPREFIX)/man1/$(USTR).1
|
||||||
gzip $(DESTDIR)$(MANPREFIX)/man1/$(DUMP).1
|
gzip -f $(DESTDIR)$(MANPREFIX)/man1/$(DUMP).1
|
||||||
ifneq ($(call optbool,$(WITH_PYTHON)),)
|
ifneq ($(call optbool,$(WITH_PYTHON)),)
|
||||||
cd src/python && python3 setup.py install --prefix=$(PREFIX) --root=$(DESTDIR)
|
cd python && $(PY) setup.py install --prefix=$(PREFIX) --root=$(if $(DESTDIR),$(DESTDIR),/)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
@@ -132,8 +133,9 @@ $(BUILD)/%.o: %.c
|
|||||||
|
|
||||||
python:
|
python:
|
||||||
ifneq ($(call optbool,$(WITH_PYTHON)),)
|
ifneq ($(call optbool,$(WITH_PYTHON)),)
|
||||||
cd src/python && python3 setup.py build
|
$(info == PY_BUILD ustreamer-*.so)
|
||||||
ln -sf src/python/build/lib.*/*.so .
|
@ cd python && $(PY) setup.py build
|
||||||
|
@ ln -sf python/build/lib.*/*.so .
|
||||||
else
|
else
|
||||||
@ true
|
@ true
|
||||||
endif
|
endif
|
||||||
@@ -180,7 +182,7 @@ clean-all: linters clean
|
|||||||
-it $(LINTERS_IMAGE) bash -c "cd src && rm -rf linters/{.tox,.mypy_cache}"
|
-it $(LINTERS_IMAGE) bash -c "cd src && rm -rf linters/{.tox,.mypy_cache}"
|
||||||
clean:
|
clean:
|
||||||
rm -rf pkg/arch/pkg pkg/arch/src pkg/arch/v*.tar.gz pkg/arch/ustreamer-*.pkg.tar.{xz,zst}
|
rm -rf pkg/arch/pkg pkg/arch/src pkg/arch/v*.tar.gz pkg/arch/ustreamer-*.pkg.tar.{xz,zst}
|
||||||
rm -rf $(USTR) $(DUMP) $(BUILD) src/python/build vgcore.* *.sock *.so
|
rm -rf $(USTR) $(DUMP) $(BUILD) python/build vgcore.* *.sock *.so
|
||||||
|
|
||||||
|
|
||||||
.PHONY: python linters
|
.PHONY: python linters
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
[tox]
|
[tox]
|
||||||
envlist = cppcheck, flake8, pylint, mypy, vulture, htmlhint
|
envlist = cppcheck-src, cppcheck-python, flake8, pylint, mypy, vulture, htmlhint
|
||||||
skipsdist = true
|
skipsdist = true
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
basepython = python3.9
|
basepython = python3.9
|
||||||
changedir = /src
|
changedir = /src
|
||||||
|
|
||||||
[testenv:cppcheck]
|
[testenv:cppcheck-src]
|
||||||
whitelist_externals = cppcheck
|
whitelist_externals = cppcheck
|
||||||
commands = cppcheck \
|
commands = cppcheck \
|
||||||
--force \
|
--force \
|
||||||
@@ -17,33 +17,49 @@ commands = cppcheck \
|
|||||||
--suppress=assignmentInAssert \
|
--suppress=assignmentInAssert \
|
||||||
--suppress=variableScope \
|
--suppress=variableScope \
|
||||||
--inline-suppr \
|
--inline-suppr \
|
||||||
|
--library=python \
|
||||||
-DCHAR_BIT=8 \
|
-DCHAR_BIT=8 \
|
||||||
-DWITH_OMX \
|
-DWITH_OMX \
|
||||||
-DWITH_GPIO \
|
-DWITH_GPIO \
|
||||||
src
|
src python
|
||||||
|
|
||||||
|
[testenv:cppcheck-python]
|
||||||
|
whitelist_externals = cppcheck
|
||||||
|
commands = cppcheck \
|
||||||
|
--force \
|
||||||
|
--std=c11 \
|
||||||
|
--error-exitcode=1 \
|
||||||
|
--quiet \
|
||||||
|
--enable=warning,unusedFunction,portability,performance,style \
|
||||||
|
--suppress=assignmentInAssert \
|
||||||
|
--suppress=variableScope \
|
||||||
|
--inline-suppr \
|
||||||
|
--library=python \
|
||||||
|
-DCHAR_BIT=8 \
|
||||||
|
python
|
||||||
|
|
||||||
[testenv:flake8]
|
[testenv:flake8]
|
||||||
whitelist_externals = bash
|
whitelist_externals = bash
|
||||||
commands = bash -c 'flake8 --config=linters/flake8.ini tools/*.py' src/python/*.py
|
commands = bash -c 'flake8 --config=linters/flake8.ini tools/*.py' python/*.py
|
||||||
deps =
|
deps =
|
||||||
flake8
|
flake8
|
||||||
flake8-quotes
|
flake8-quotes
|
||||||
|
|
||||||
[testenv:pylint]
|
[testenv:pylint]
|
||||||
whitelist_externals = bash
|
whitelist_externals = bash
|
||||||
commands = bash -c 'pylint --rcfile=linters/pylint.ini --output-format=colorized --reports=no tools/*.py src/python/*.py'
|
commands = bash -c 'pylint --rcfile=linters/pylint.ini --output-format=colorized --reports=no tools/*.py python/*.py'
|
||||||
deps =
|
deps =
|
||||||
pylint
|
pylint
|
||||||
|
|
||||||
[testenv:mypy]
|
[testenv:mypy]
|
||||||
whitelist_externals = bash
|
whitelist_externals = bash
|
||||||
commands = bash -c 'mypy --config-file=linters/mypy.ini tools/*.py src/python/*.py'
|
commands = bash -c 'mypy --config-file=linters/mypy.ini tools/*.py python/*.py'
|
||||||
deps =
|
deps =
|
||||||
mypy
|
mypy
|
||||||
|
|
||||||
[testenv:vulture]
|
[testenv:vulture]
|
||||||
whitelist_externals = bash
|
whitelist_externals = bash
|
||||||
commands = bash -c 'vulture tools/*.py src/python/*.py'
|
commands = bash -c 'vulture tools/*.py python/*.py'
|
||||||
deps =
|
deps =
|
||||||
vulture
|
vulture
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
.\" Manpage for ustreamer-dump.
|
.\" Manpage for ustreamer-dump.
|
||||||
.\" Open an issue or pull request to https://github.com/pikvm/ustreamer to correct errors or typos
|
.\" Open an issue or pull request to https://github.com/pikvm/ustreamer to correct errors or typos
|
||||||
.TH USTREAMER-DUMP 1 "version 3.6" "January 2021"
|
.TH USTREAMER-DUMP 1 "version 3.8" "January 2021"
|
||||||
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
ustreamer-dump \- Dump uStreamer's memory sink to file
|
ustreamer-dump \- Dump uStreamer's memory sink to file
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
.\" Manpage for ustreamer.
|
.\" Manpage for ustreamer.
|
||||||
.\" Open an issue or pull request to https://github.com/pikvm/ustreamer to correct errors or typos
|
.\" Open an issue or pull request to https://github.com/pikvm/ustreamer to correct errors or typos
|
||||||
.TH USTREAMER 1 "version 3.6" "November 2020"
|
.TH USTREAMER 1 "version 3.8" "November 2020"
|
||||||
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
ustreamer \- stream MJPG video from any V4L2 device to the network
|
ustreamer \- stream MJPG video from any V4L2 device to the network
|
||||||
|
|||||||
@@ -3,20 +3,20 @@
|
|||||||
|
|
||||||
|
|
||||||
pkgname=ustreamer
|
pkgname=ustreamer
|
||||||
pkgver=3.6
|
pkgver=3.8
|
||||||
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"
|
||||||
license=(GPL)
|
license=(GPL)
|
||||||
arch=(i686 x86_64 armv6h armv7h aarch64)
|
arch=(i686 x86_64 armv6h armv7h aarch64)
|
||||||
depends=(libjpeg libevent libutil-linux libbsd libgpiod)
|
depends=(libjpeg libevent libutil-linux libbsd libgpiod)
|
||||||
# optional: raspberrypi-firmware for OMX encoder
|
|
||||||
makedepends=(gcc make)
|
makedepends=(gcc make)
|
||||||
source=(${pkgname}::"git+https://github.com/pikvm/ustreamer#commit=v${pkgver}")
|
source=(${pkgname}::"git+https://github.com/pikvm/ustreamer#commit=v${pkgver}")
|
||||||
md5sums=(SKIP)
|
md5sums=(SKIP)
|
||||||
|
|
||||||
|
|
||||||
_options="WITH_GPIO=1"
|
_options="WITH_GPIO=1"
|
||||||
if [ -e /usr/lib/python3 ]; then
|
if [ -e /usr/bin/python3 ]; then
|
||||||
_options="$_options WITH_PYTHON=1"
|
_options="$_options WITH_PYTHON=1"
|
||||||
depends+=(python)
|
depends+=(python)
|
||||||
makedepends+=(python-setuptools)
|
makedepends+=(python-setuptools)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=ustreamer
|
PKG_NAME:=ustreamer
|
||||||
PKG_VERSION:=3.6
|
PKG_VERSION:=3.8
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
PKG_MAINTAINER:=Maxim Devaev <mdevaev@gmail.com>
|
PKG_MAINTAINER:=Maxim Devaev <mdevaev@gmail.com>
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from distutils.core import setup
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
setup(
|
setup(
|
||||||
name="ustreamer",
|
name="ustreamer",
|
||||||
version="3.6",
|
version="3.8",
|
||||||
description="uStreamer tools",
|
description="uStreamer tools",
|
||||||
author="Maxim Devaev",
|
author="Maxim Devaev",
|
||||||
author_email="mdevaev@gmail.com",
|
author_email="mdevaev@gmail.com",
|
||||||
@@ -17,6 +17,10 @@ if __name__ == "__main__":
|
|||||||
libraries=["rt", "m", "pthread"],
|
libraries=["rt", "m", "pthread"],
|
||||||
undef_macros=["NDEBUG"],
|
undef_macros=["NDEBUG"],
|
||||||
sources=["ustreamer.c"],
|
sources=["ustreamer.c"],
|
||||||
|
depends=[
|
||||||
|
"../src/libs/tools.h",
|
||||||
|
"../src/libs/memsinksh.h",
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@@ -13,8 +13,8 @@
|
|||||||
|
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
|
|
||||||
#include "../libs/tools.h" // Just a header without C-sources
|
#include "../src/libs/tools.h" // Just a header without C-sources
|
||||||
#include "../libs/memsinksh.h" // No sources again
|
#include "../src/libs/memsinksh.h" // No sources again
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -29,10 +29,16 @@ typedef struct {
|
|||||||
uint8_t *tmp_data;
|
uint8_t *tmp_data;
|
||||||
size_t tmp_data_allocated;
|
size_t tmp_data_allocated;
|
||||||
uint64_t last_id;
|
uint64_t last_id;
|
||||||
|
|
||||||
|
PyObject *frame; // PyDict
|
||||||
} MemsinkObject;
|
} MemsinkObject;
|
||||||
|
|
||||||
|
|
||||||
static void MemsinkObject_destroy_internals(MemsinkObject *self) {
|
static void MemsinkObject_destroy_internals(MemsinkObject *self) {
|
||||||
|
if (self->frame != NULL) {
|
||||||
|
Py_DECREF(self->frame);
|
||||||
|
self->frame = NULL;
|
||||||
|
}
|
||||||
if (self->mem != NULL) {
|
if (self->mem != NULL) {
|
||||||
munmap(self->mem, sizeof(memsink_shared_s));
|
munmap(self->mem, sizeof(memsink_shared_s));
|
||||||
self->mem = NULL;
|
self->mem = NULL;
|
||||||
@@ -96,6 +102,10 @@ static int MemsinkObject_init(MemsinkObject *self, PyObject *args, PyObject *kwa
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((self->frame = PyDict_New()) == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
@@ -128,53 +138,61 @@ static PyObject *MemsinkObject_exit(MemsinkObject *self, PyObject *Py_UNUSED(ign
|
|||||||
return PyObject_CallMethod((PyObject *)self, "close", "");
|
return PyObject_CallMethod((PyObject *)self, "close", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define MEM(_next) self->mem->_next
|
||||||
|
|
||||||
|
static int wait_frame(MemsinkObject *self) {
|
||||||
|
long double deadline_ts = get_now_monotonic() + self->wait_timeout;
|
||||||
|
|
||||||
|
# define RETURN_OS_ERROR { \
|
||||||
|
Py_BLOCK_THREADS \
|
||||||
|
PyErr_SetFromErrno(PyExc_OSError); \
|
||||||
|
return -1; \
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
|
|
||||||
|
int retval = flock_timedwait_monotonic(self->fd, self->lock_timeout);
|
||||||
|
if (retval < 0 && errno != EWOULDBLOCK) {
|
||||||
|
RETURN_OS_ERROR;
|
||||||
|
} else if (retval == 0) {
|
||||||
|
if (MEM(magic) == MEMSINK_MAGIC && MEM(version) == MEMSINK_VERSION && MEM(id) != self->last_id) {
|
||||||
|
Py_BLOCK_THREADS
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (flock(self->fd, LOCK_UN) < 0) {
|
||||||
|
RETURN_OS_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (usleep(1000) < 0) {
|
||||||
|
RETURN_OS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
|
if (PyErr_CheckSignals() < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} while (get_now_monotonic() < deadline_ts);
|
||||||
|
|
||||||
|
# undef RETURN_OS_ERROR
|
||||||
|
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *MemsinkObject_wait_frame(MemsinkObject *self, PyObject *Py_UNUSED(ignored)) {
|
static PyObject *MemsinkObject_wait_frame(MemsinkObject *self, PyObject *Py_UNUSED(ignored)) {
|
||||||
if (self->mem == NULL || self->fd <= 0) {
|
if (self->mem == NULL || self->fd <= 0) {
|
||||||
PyErr_SetString(PyExc_RuntimeError, "Closed");
|
PyErr_SetString(PyExc_RuntimeError, "Closed");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool found = false;
|
switch (wait_frame(self)) {
|
||||||
bool failed = false;
|
case 0: break;
|
||||||
|
case -2: Py_RETURN_NONE;
|
||||||
Py_BEGIN_ALLOW_THREADS
|
default: return NULL;
|
||||||
long double deadline_ts = get_now_monotonic() + self->wait_timeout;
|
|
||||||
do {
|
|
||||||
int retval = flock_timedwait_monotonic(self->fd, self->lock_timeout);
|
|
||||||
if (retval < 0 && errno != EWOULDBLOCK) {
|
|
||||||
failed = true;
|
|
||||||
break;
|
|
||||||
} else if (retval == 0) {
|
|
||||||
if (
|
|
||||||
self->mem->magic == MEMSINK_MAGIC
|
|
||||||
&& self->mem->version == MEMSINK_VERSION
|
|
||||||
&& self->mem->id != self->last_id
|
|
||||||
) {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (flock(self->fd, LOCK_UN) < 0) {
|
|
||||||
failed = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
errno = 0;
|
|
||||||
usleep(1000);
|
|
||||||
if (errno == EINTR) {
|
|
||||||
failed = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while (get_now_monotonic() < deadline_ts);
|
|
||||||
Py_END_ALLOW_THREADS
|
|
||||||
|
|
||||||
if (failed) {
|
|
||||||
return PyErr_SetFromErrno(PyExc_OSError);
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
Py_RETURN_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# define COPY(_type, _field) _type tmp_##_field = self->mem->_field
|
# define COPY(_type, _field) _type tmp_##_field = MEM(_field)
|
||||||
COPY(unsigned, width);
|
COPY(unsigned, width);
|
||||||
COPY(unsigned, height);
|
COPY(unsigned, height);
|
||||||
COPY(unsigned, format);
|
COPY(unsigned, format);
|
||||||
@@ -187,35 +205,52 @@ static PyObject *MemsinkObject_wait_frame(MemsinkObject *self, PyObject *Py_UNUS
|
|||||||
# undef COPY
|
# undef COPY
|
||||||
|
|
||||||
// Временный буффер используется для скорейшего разблокирования синка
|
// Временный буффер используется для скорейшего разблокирования синка
|
||||||
if (self->tmp_data_allocated < self->mem->used) {
|
if (self->tmp_data_allocated < MEM(used)) {
|
||||||
size_t size = self->mem->used + (512 * 1024);
|
size_t size = MEM(used) + (512 * 1024);
|
||||||
A_REALLOC(self->tmp_data, size);
|
A_REALLOC(self->tmp_data, size);
|
||||||
self->tmp_data_allocated = size;
|
self->tmp_data_allocated = size;
|
||||||
}
|
}
|
||||||
memcpy(self->tmp_data, self->mem->data, self->mem->used);
|
memcpy(self->tmp_data, MEM(data), MEM(used));
|
||||||
|
|
||||||
self->mem->last_client_ts = get_now_monotonic();
|
MEM(last_client_ts) = get_now_monotonic();
|
||||||
self->last_id = self->mem->id;
|
self->last_id = MEM(id);
|
||||||
|
|
||||||
if (flock(self->fd, LOCK_UN) < 0) {
|
if (flock(self->fd, LOCK_UN) < 0) {
|
||||||
return PyErr_SetFromErrno(PyExc_OSError);
|
return PyErr_SetFromErrno(PyExc_OSError);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *frame = PyDict_New();
|
PyDict_Clear(self->frame);
|
||||||
# define SET_VALUE(_field, _from, _to) PyDict_SetItemString(frame, #_field, Py##_to##_From##_from(tmp_##_field))
|
|
||||||
SET_VALUE(width, Long, Long);
|
# define SET_VALUE(_key, _maker) { \
|
||||||
SET_VALUE(height, Long, Long);
|
PyObject *_tmp = _maker; \
|
||||||
SET_VALUE(format, Long, Long);
|
if (_tmp == NULL) { \
|
||||||
SET_VALUE(stride, Long, Long);
|
return NULL; \
|
||||||
SET_VALUE(online, Long, Bool);
|
} \
|
||||||
SET_VALUE(grab_ts, Double, Float);
|
if (PyDict_SetItemString(self->frame, _key, _tmp) < 0) { \
|
||||||
SET_VALUE(encode_begin_ts, Double, Float);
|
Py_DECREF(_tmp); \
|
||||||
SET_VALUE(encode_end_ts, Double, Float);
|
return NULL; \
|
||||||
|
} \
|
||||||
|
Py_DECREF(_tmp); \
|
||||||
|
}
|
||||||
|
|
||||||
|
SET_VALUE("width", PyLong_FromLong(tmp_width));
|
||||||
|
SET_VALUE("height", PyLong_FromLong(tmp_height));
|
||||||
|
SET_VALUE("format", PyLong_FromLong(tmp_format));
|
||||||
|
SET_VALUE("stride", PyLong_FromLong(tmp_stride));
|
||||||
|
SET_VALUE("online", PyBool_FromLong(tmp_online));
|
||||||
|
SET_VALUE("grab_ts", PyFloat_FromDouble(tmp_grab_ts));
|
||||||
|
SET_VALUE("encode_begin_ts", PyFloat_FromDouble(tmp_encode_begin_ts));
|
||||||
|
SET_VALUE("encode_end_ts", PyFloat_FromDouble(tmp_encode_end_ts));
|
||||||
|
SET_VALUE("data", PyBytes_FromStringAndSize((const char *)self->tmp_data, tmp_used));
|
||||||
|
|
||||||
# undef SET_VALUE
|
# undef SET_VALUE
|
||||||
PyDict_SetItemString(frame, "data", PyBytes_FromStringAndSize((const char *)self->tmp_data, tmp_used));
|
|
||||||
return frame;
|
Py_INCREF(self->frame);
|
||||||
|
return self->frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef MEM
|
||||||
|
|
||||||
static PyObject *MemsinkObject_is_opened(MemsinkObject *self, PyObject *Py_UNUSED(ignored)) {
|
static PyObject *MemsinkObject_is_opened(MemsinkObject *self, PyObject *Py_UNUSED(ignored)) {
|
||||||
return PyBool_FromLong(self->mem != NULL && self->fd > 0);
|
return PyBool_FromLong(self->mem != NULL && self->fd > 0);
|
||||||
}
|
}
|
||||||
@@ -23,5 +23,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifndef VERSION
|
#ifndef VERSION
|
||||||
# define VERSION "3.6"
|
# define VERSION "3.8"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -40,7 +40,11 @@ memsink_s *memsink_init(
|
|||||||
|
|
||||||
LOG_INFO("Using %s-sink: %s", name, obj);
|
LOG_INFO("Using %s-sink: %s", name, obj);
|
||||||
|
|
||||||
if ((sink->fd = shm_open(sink->obj, (server ? O_RDWR | O_CREAT : O_RDWR), mode)) == -1) {
|
mode_t mask = umask(0);
|
||||||
|
sink->fd = shm_open(sink->obj, (server ? O_RDWR | O_CREAT : O_RDWR), mode);
|
||||||
|
umask(mask);
|
||||||
|
if (sink->fd == -1) {
|
||||||
|
umask(mask);
|
||||||
LOG_PERROR("%s-sink: Can't open shared memory", name);
|
LOG_PERROR("%s-sink: Can't open shared memory", name);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,7 +135,9 @@ INLINE int flock_timedwait_monotonic(int fd, long double timeout) {
|
|||||||
if (retval == 0 || errno != EWOULDBLOCK || get_now_monotonic() > deadline_ts) {
|
if (retval == 0 || errno != EWOULDBLOCK || get_now_monotonic() > deadline_ts) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
usleep(1000);
|
if (usleep(1000) < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -221,18 +221,20 @@ static int _vcos_semwait(VCOS_SEMAPHORE_T *sem) {
|
|||||||
if (sem_status == VCOS_SUCCESS) {
|
if (sem_status == VCOS_SUCCESS) {
|
||||||
return 0;
|
return 0;
|
||||||
} else if (sem_status != VCOS_EAGAIN || get_now_monotonic() > deadline_ts) {
|
} else if (sem_status != VCOS_EAGAIN || get_now_monotonic() > deadline_ts) {
|
||||||
goto error;
|
break;
|
||||||
|
}
|
||||||
|
if (usleep(1000) < 0) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
usleep(1000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error:
|
switch (sem_status) {
|
||||||
switch (sem_status) {
|
case VCOS_EAGAIN: LOG_ERROR("Can't wait VCOS semaphore: EAGAIN (timeout)"); break;
|
||||||
case VCOS_EAGAIN: LOG_ERROR("Can't wait VCOS semaphore: EAGAIN (timeout)"); break;
|
case VCOS_EINVAL: LOG_ERROR("Can't wait VCOS semaphore: EINVAL"); break;
|
||||||
case VCOS_EINVAL: LOG_ERROR("Can't wait VCOS semaphore: EINVAL"); break;
|
default: LOG_ERROR("Can't wait VCOS semaphore: %d", sem_status); break;
|
||||||
default: LOG_ERROR("Can't wait VCOS semaphore: %d", sem_status); break;
|
}
|
||||||
}
|
return -1;
|
||||||
return -1;
|
|
||||||
# else
|
# else
|
||||||
return (vcos_semaphore_wait(sem) == VCOS_SUCCESS ? 0 : -1);
|
return (vcos_semaphore_wait(sem) == VCOS_SUCCESS ? 0 : -1);
|
||||||
# endif
|
# endif
|
||||||
|
|||||||
Reference in New Issue
Block a user