mirror of
https://github.com/pikvm/ustreamer.git
synced 2026-02-27 12:16:31 +00:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2807678551 | ||
|
|
e96e0aa73c | ||
|
|
d06c2619b2 | ||
|
|
6b18455d11 | ||
|
|
217977d9cb | ||
|
|
b9f186e47c | ||
|
|
d7d56f3536 | ||
|
|
2e3c764369 | ||
|
|
7236e53813 | ||
|
|
e7f7350405 | ||
|
|
81f0266a87 | ||
|
|
eb1a2e3695 | ||
|
|
6cfd3739d3 | ||
|
|
77b8386de7 | ||
|
|
a002bd3427 | ||
|
|
202b907430 | ||
|
|
d9f4aba953 | ||
|
|
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.13
|
||||||
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
|
||||||
|
|||||||
43
Makefile
43
Makefile
@@ -7,7 +7,8 @@ PREFIX ?= /usr/local
|
|||||||
MANPREFIX ?= $(PREFIX)/share/man
|
MANPREFIX ?= $(PREFIX)/share/man
|
||||||
|
|
||||||
CC ?= gcc
|
CC ?= gcc
|
||||||
CFLAGS ?= -O3 -MD
|
PY ?= python3
|
||||||
|
CFLAGS ?= -O3
|
||||||
LDFLAGS ?=
|
LDFLAGS ?=
|
||||||
|
|
||||||
RPI_VC_HEADERS ?= /opt/vc/include
|
RPI_VC_HEADERS ?= /opt/vc/include
|
||||||
@@ -19,7 +20,8 @@ LINTERS_IMAGE ?= $(USTR)-linters
|
|||||||
|
|
||||||
|
|
||||||
# =====
|
# =====
|
||||||
override CFLAGS += -c -std=c11 -Wall -Wextra -D_GNU_SOURCE
|
_CFLAGS = -MD -c -std=c11 -Wall -Wextra -D_GNU_SOURCE $(CFLAGS)
|
||||||
|
_LDFLAGS = $(LDFLAGS)
|
||||||
|
|
||||||
_COMMON_LIBS = -lm -ljpeg -pthread -lrt
|
_COMMON_LIBS = -lm -ljpeg -pthread -lrt
|
||||||
|
|
||||||
@@ -47,7 +49,7 @@ endef
|
|||||||
|
|
||||||
ifneq ($(call optbool,$(WITH_OMX)),)
|
ifneq ($(call optbool,$(WITH_OMX)),)
|
||||||
_USTR_LIBS += -lbcm_host -lvcos -lvcsm -lopenmaxil -lmmal -lmmal_core -lmmal_util -lmmal_vc_client -lmmal_components -L$(RPI_VC_LIBS)
|
_USTR_LIBS += -lbcm_host -lvcos -lvcsm -lopenmaxil -lmmal -lmmal_core -lmmal_util -lmmal_vc_client -lmmal_components -L$(RPI_VC_LIBS)
|
||||||
override CFLAGS += -DWITH_OMX -DOMX_SKIP64BIT -I$(RPI_VC_HEADERS)
|
override _CFLAGS += -DWITH_OMX -DOMX_SKIP64BIT -I$(RPI_VC_HEADERS)
|
||||||
_USTR_SRCS += $(shell ls \
|
_USTR_SRCS += $(shell ls \
|
||||||
src/ustreamer/encoders/omx/*.c \
|
src/ustreamer/encoders/omx/*.c \
|
||||||
src/ustreamer/h264/*.c \
|
src/ustreamer/h264/*.c \
|
||||||
@@ -57,14 +59,14 @@ endif
|
|||||||
|
|
||||||
ifneq ($(call optbool,$(WITH_GPIO)),)
|
ifneq ($(call optbool,$(WITH_GPIO)),)
|
||||||
_USTR_LIBS += -lgpiod
|
_USTR_LIBS += -lgpiod
|
||||||
override CFLAGS += -DWITH_GPIO
|
override _CFLAGS += -DWITH_GPIO
|
||||||
_USTR_SRCS += $(shell ls src/ustreamer/gpio/*.c)
|
_USTR_SRCS += $(shell ls src/ustreamer/gpio/*.c)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
WITH_PTHREAD_NP ?= 1
|
WITH_PTHREAD_NP ?= 1
|
||||||
ifneq ($(call optbool,$(WITH_PTHREAD_NP)),)
|
ifneq ($(call optbool,$(WITH_PTHREAD_NP)),)
|
||||||
override CFLAGS += -DWITH_PTHREAD_NP
|
override _CFLAGS += -DWITH_PTHREAD_NP
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
@@ -73,7 +75,7 @@ ifneq ($(call optbool,$(WITH_SETPROCTITLE)),)
|
|||||||
ifeq ($(shell uname -s | tr A-Z a-z),linux)
|
ifeq ($(shell uname -s | tr A-Z a-z),linux)
|
||||||
_USTR_LIBS += -lbsd
|
_USTR_LIBS += -lbsd
|
||||||
endif
|
endif
|
||||||
override CFLAGS += -DWITH_SETPROCTITLE
|
override _CFLAGS += -DWITH_SETPROCTITLE
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
@@ -81,16 +83,16 @@ endif
|
|||||||
all: $(USTR) $(DUMP) python
|
all: $(USTR) $(DUMP) python
|
||||||
|
|
||||||
|
|
||||||
install: $(USTR) $(DUMP)
|
install: all
|
||||||
mkdir -p $(DESTDIR)$(PREFIX)/bin $(DESTDIR)$(MANPREFIX)/man1
|
mkdir -p $(DESTDIR)$(PREFIX)/bin $(DESTDIR)$(MANPREFIX)/man1
|
||||||
install -m755 $(USTR) $(DESTDIR)$(PREFIX)/bin/$(USTR)
|
install -m755 $(USTR) $(DESTDIR)$(PREFIX)/bin/$(USTR)
|
||||||
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
|
||||||
|
|
||||||
|
|
||||||
@@ -107,33 +109,34 @@ regen:
|
|||||||
$(USTR): $(_USTR_SRCS:%.c=$(BUILD)/%.o)
|
$(USTR): $(_USTR_SRCS:%.c=$(BUILD)/%.o)
|
||||||
# $(info ========================================)
|
# $(info ========================================)
|
||||||
$(info == LD $@)
|
$(info == LD $@)
|
||||||
@ $(CC) $^ -o $@ $(LDFLAGS) $(_USTR_LIBS)
|
@ $(CC) $^ -o $@ $(_LDFLAGS) $(_USTR_LIBS)
|
||||||
# $(info :: CC = $(CC))
|
# $(info :: CC = $(CC))
|
||||||
# $(info :: LIBS = $(_USTR_LIBS))
|
# $(info :: LIBS = $(_USTR_LIBS))
|
||||||
# $(info :: CFLAGS = $(CFLAGS))
|
# $(info :: CFLAGS = $(_CFLAGS))
|
||||||
# $(info :: LDFLAGS = $(LDFLAGS))
|
# $(info :: LDFLAGS = $(_LDFLAGS))
|
||||||
|
|
||||||
|
|
||||||
$(DUMP): $(_DUMP_SRCS:%.c=$(BUILD)/%.o)
|
$(DUMP): $(_DUMP_SRCS:%.c=$(BUILD)/%.o)
|
||||||
# $(info ========================================)
|
# $(info ========================================)
|
||||||
$(info == LD $@)
|
$(info == LD $@)
|
||||||
@ $(CC) $^ -o $@ $(LDFLAGS) $(_DUMP_LIBS)
|
@ $(CC) $^ -o $@ $(_LDFLAGS) $(_DUMP_LIBS)
|
||||||
# $(info :: CC = $(CC))
|
# $(info :: CC = $(CC))
|
||||||
# $(info :: LIBS = $(_DUMP_LIBS))
|
# $(info :: LIBS = $(_DUMP_LIBS))
|
||||||
# $(info :: CFLAGS = $(CFLAGS))
|
# $(info :: CFLAGS = $(_CFLAGS))
|
||||||
# $(info :: LDFLAGS = $(LDFLAGS))
|
# $(info :: LDFLAGS = $(_LDFLAGS))
|
||||||
|
|
||||||
|
|
||||||
$(BUILD)/%.o: %.c
|
$(BUILD)/%.o: %.c
|
||||||
$(info -- CC $<)
|
$(info -- CC $<)
|
||||||
@ mkdir -p $(dir $@) || true
|
@ mkdir -p $(dir $@) || true
|
||||||
@ $(CC) $< -o $@ $(CFLAGS)
|
@ $(CC) $< -o $@ $(_CFLAGS)
|
||||||
|
|
||||||
|
|
||||||
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 +183,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,5 +1,8 @@
|
|||||||
FROM archlinux/base
|
FROM archlinux/base
|
||||||
|
|
||||||
|
RUN mkdir -p /etc/pacman.d/hooks \
|
||||||
|
&& ln -s /dev/null /etc/pacman.d/hooks/30-systemd-tmpfiles.hook
|
||||||
|
|
||||||
RUN echo "Server = http://mirror.yandex.ru/archlinux/\$repo/os/\$arch" > /etc/pacman.d/mirrorlist
|
RUN echo "Server = http://mirror.yandex.ru/archlinux/\$repo/os/\$arch" > /etc/pacman.d/mirrorlist
|
||||||
|
|
||||||
RUN pacman -Syu --noconfirm \
|
RUN pacman -Syu --noconfirm \
|
||||||
|
|||||||
@@ -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.13" "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.13" "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
|
||||||
@@ -118,7 +118,7 @@ Delay before trying to connect to the device again after an error (timeout for e
|
|||||||
.SS "Image control options"
|
.SS "Image control options"
|
||||||
.TP
|
.TP
|
||||||
.BR \-\-image\-default
|
.BR \-\-image\-default
|
||||||
Reset all image settings bellow to default. Default: no change.
|
Reset all image settings below to default. Default: no change.
|
||||||
.TP
|
.TP
|
||||||
.BR \-\-brightness\ \fIN ", " \fIauto ", " \fIdefault
|
.BR \-\-brightness\ \fIN ", " \fIauto ", " \fIdefault
|
||||||
Set brightness. Default: no change.
|
Set brightness. Default: no change.
|
||||||
@@ -166,8 +166,8 @@ Bind to this TCP port. Default: 8080.
|
|||||||
.TP
|
.TP
|
||||||
.BR \-U\ \fIpath ", " \-\-unix\ \fIpath
|
.BR \-U\ \fIpath ", " \-\-unix\ \fIpath
|
||||||
Bind to UNIX domain socket. Default: disabled.
|
Bind to UNIX domain socket. Default: disabled.
|
||||||
.tp
|
.TP
|
||||||
.br \-d ", " \-\-unix\-rm
|
.BR \-d ", " \-\-unix\-rm
|
||||||
Try to remove old unix socket file before binding. default: disabled.
|
Try to remove old unix socket file before binding. default: disabled.
|
||||||
.TP
|
.TP
|
||||||
.BR \-M\ \fImode ", " \-\-unix\-mode\ \fImode
|
.BR \-M\ \fImode ", " \-\-unix\-mode\ \fImode
|
||||||
@@ -234,6 +234,12 @@ Client TTL. Default: 10.
|
|||||||
.TP
|
.TP
|
||||||
.BR \-\-h264\-sink\-timeout\ \fIsec
|
.BR \-\-h264\-sink\-timeout\ \fIsec
|
||||||
Timeout for lock. Default: 1.
|
Timeout for lock. Default: 1.
|
||||||
|
.TP
|
||||||
|
.BR \-\-h264\-bitrate\ \fIkbps
|
||||||
|
H264 bitrate in Kbps. Default: 5000.
|
||||||
|
.TP
|
||||||
|
.BR \-\-h264\-gop\ \fIN
|
||||||
|
Intarval between keyframes. Default: 30.
|
||||||
|
|
||||||
.SS "Process options"
|
.SS "Process options"
|
||||||
.TP
|
.TP
|
||||||
|
|||||||
@@ -3,20 +3,20 @@
|
|||||||
|
|
||||||
|
|
||||||
pkgname=ustreamer
|
pkgname=ustreamer
|
||||||
pkgver=3.6
|
pkgver=3.13
|
||||||
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)
|
||||||
@@ -28,20 +28,21 @@ if [ -e /opt/vc/include/IL/OMX_Core.h ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# LD does not link mmal with this option
|
||||||
|
# This DOESN'T affect setup.py
|
||||||
|
LDFLAGS="${LDFLAGS//--as-needed/}"
|
||||||
|
export LDFLAGS="${LDFLAGS//,,/,}"
|
||||||
|
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
cd "$srcdir"
|
cd "$srcdir"
|
||||||
rm -rf $pkgname-build
|
rm -rf $pkgname-build
|
||||||
cp -r $pkgname $pkgname-build
|
cp -r $pkgname $pkgname-build
|
||||||
cd $pkgname-build
|
cd $pkgname-build
|
||||||
|
|
||||||
# LD does not link mmal with this option
|
|
||||||
LDFLAGS="${LDFLAGS//--as-needed/}"
|
|
||||||
LDFLAGS="${LDFLAGS//,,/,}"
|
|
||||||
|
|
||||||
make $_options CFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" $MAKEFLAGS
|
make $_options CFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" $MAKEFLAGS
|
||||||
}
|
}
|
||||||
|
|
||||||
package() {
|
package() {
|
||||||
cd "$srcdir/$pkgname-build"
|
cd "$srcdir/$pkgname-build"
|
||||||
make DESTDIR="$pkgdir" PREFIX=/usr install
|
make $_options CFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" DESTDIR="$pkgdir" PREFIX=/usr install
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.13
|
||||||
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.13",
|
||||||
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",
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@@ -2,9 +2,9 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
@@ -13,26 +13,55 @@
|
|||||||
|
|
||||||
#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 {
|
||||||
|
uint64_t id;
|
||||||
|
long double ts;
|
||||||
|
|
||||||
|
uint8_t *data;
|
||||||
|
size_t used;
|
||||||
|
size_t allocated;
|
||||||
|
|
||||||
|
unsigned width;
|
||||||
|
unsigned height;
|
||||||
|
unsigned format;
|
||||||
|
unsigned stride;
|
||||||
|
|
||||||
|
bool online;
|
||||||
|
|
||||||
|
long double grab_ts;
|
||||||
|
long double encode_begin_ts;
|
||||||
|
long double encode_end_ts;
|
||||||
|
} tmp_frame_s;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
|
|
||||||
char *obj;
|
char *obj;
|
||||||
double lock_timeout;
|
double lock_timeout;
|
||||||
double wait_timeout;
|
double wait_timeout;
|
||||||
|
double drop_same_frames;
|
||||||
|
|
||||||
int fd;
|
int fd;
|
||||||
memsink_shared_s *mem;
|
memsink_shared_s *mem;
|
||||||
uint8_t *tmp_data;
|
|
||||||
size_t tmp_data_allocated;
|
tmp_frame_s *tmp_frame;
|
||||||
uint64_t last_id;
|
PyObject *dict_frame; // PyDict
|
||||||
} MemsinkObject;
|
} MemsinkObject;
|
||||||
|
|
||||||
|
|
||||||
|
#define MEM(_next) self->mem->_next
|
||||||
|
#define TMP(_next) self->tmp_frame->_next
|
||||||
|
|
||||||
|
|
||||||
static void MemsinkObject_destroy_internals(MemsinkObject *self) {
|
static void MemsinkObject_destroy_internals(MemsinkObject *self) {
|
||||||
|
if (self->dict_frame != NULL) {
|
||||||
|
Py_DECREF(self->dict_frame);
|
||||||
|
self->dict_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;
|
||||||
@@ -41,10 +70,12 @@ static void MemsinkObject_destroy_internals(MemsinkObject *self) {
|
|||||||
close(self->fd);
|
close(self->fd);
|
||||||
self->fd = -1;
|
self->fd = -1;
|
||||||
}
|
}
|
||||||
if (self->tmp_data) {
|
if (self->tmp_frame) {
|
||||||
free(self->tmp_data);
|
if (TMP(data)) {
|
||||||
self->tmp_data = NULL;
|
free(TMP(data));
|
||||||
self->tmp_data_allocated = 0;
|
}
|
||||||
|
free(self->tmp_frame);
|
||||||
|
self->tmp_frame = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,27 +83,29 @@ static int MemsinkObject_init(MemsinkObject *self, PyObject *args, PyObject *kwa
|
|||||||
self->lock_timeout = 1;
|
self->lock_timeout = 1;
|
||||||
self->wait_timeout = 1;
|
self->wait_timeout = 1;
|
||||||
|
|
||||||
static char *kws[] = {"obj", "lock_timeout", "wait_timeout", NULL};
|
static char *kws[] = {"obj", "lock_timeout", "wait_timeout", "drop_same_frames", NULL};
|
||||||
if (!PyArg_ParseTupleAndKeywords(
|
if (!PyArg_ParseTupleAndKeywords(
|
||||||
args, kwargs, "s|dd", kws,
|
args, kwargs, "s|ddd", kws,
|
||||||
&self->obj, &self->lock_timeout, &self->wait_timeout)) {
|
&self->obj, &self->lock_timeout, &self->wait_timeout, &self->drop_same_frames)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
# define SET_TIMEOUT(_timeout) { \
|
# define SET_DOUBLE(_field, _cond) { \
|
||||||
if (self->_timeout <= 0) { \
|
if (!(self->_field _cond)) { \
|
||||||
PyErr_SetString(PyExc_ValueError, #_timeout " must be > 0"); \
|
PyErr_SetString(PyExc_ValueError, #_field " must be " #_cond); \
|
||||||
return -1; \
|
return -1; \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
SET_TIMEOUT(lock_timeout);
|
SET_DOUBLE(lock_timeout, > 0);
|
||||||
SET_TIMEOUT(wait_timeout);
|
SET_DOUBLE(wait_timeout, > 0);
|
||||||
|
SET_DOUBLE(drop_same_frames, >= 0);
|
||||||
|
|
||||||
# undef CHECK_TIMEOUT
|
# undef SET_DOUBLE
|
||||||
|
|
||||||
self->tmp_data_allocated = 512 * 1024;
|
A_CALLOC(self->tmp_frame, 1);
|
||||||
A_REALLOC(self->tmp_data, self->tmp_data_allocated);
|
TMP(allocated) = 512 * 1024;
|
||||||
|
A_REALLOC(TMP(data), TMP(allocated));
|
||||||
|
|
||||||
if ((self->fd = shm_open(self->obj, O_RDWR, 0)) == -1) {
|
if ((self->fd = shm_open(self->obj, O_RDWR, 0)) == -1) {
|
||||||
PyErr_SetFromErrno(PyExc_OSError);
|
PyErr_SetFromErrno(PyExc_OSError);
|
||||||
@@ -96,6 +129,10 @@ static int MemsinkObject_init(MemsinkObject *self, PyObject *args, PyObject *kwa
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((self->dict_frame = PyDict_New()) == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
@@ -128,92 +165,142 @@ static PyObject *MemsinkObject_exit(MemsinkObject *self, PyObject *Py_UNUSED(ign
|
|||||||
return PyObject_CallMethod((PyObject *)self, "close", "");
|
return PyObject_CallMethod((PyObject *)self, "close", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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; \
|
||||||
|
}
|
||||||
|
|
||||||
|
long double now;
|
||||||
|
do {
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
|
|
||||||
|
int retval = flock_timedwait_monotonic(self->fd, self->lock_timeout);
|
||||||
|
now = get_now_monotonic();
|
||||||
|
|
||||||
|
if (retval < 0 && errno != EWOULDBLOCK) {
|
||||||
|
RETURN_OS_ERROR;
|
||||||
|
|
||||||
|
} else if (retval == 0) {
|
||||||
|
if (MEM(magic) == MEMSINK_MAGIC && MEM(version) == MEMSINK_VERSION && TMP(id) != MEM(id)) {
|
||||||
|
if (self->drop_same_frames > 0) {
|
||||||
|
# define CMP(_field) (TMP(_field) == MEM(_field))
|
||||||
|
if (
|
||||||
|
CMP(used)
|
||||||
|
&& CMP(width)
|
||||||
|
&& CMP(height)
|
||||||
|
&& CMP(format)
|
||||||
|
&& CMP(stride)
|
||||||
|
&& CMP(online)
|
||||||
|
&& (TMP(ts) + self->drop_same_frames > now)
|
||||||
|
&& !memcmp(TMP(data), MEM(data), MEM(used))
|
||||||
|
) {
|
||||||
|
TMP(id) = MEM(id);
|
||||||
|
goto drop;
|
||||||
|
}
|
||||||
|
# undef CMP
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_BLOCK_THREADS
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flock(self->fd, LOCK_UN) < 0) {
|
||||||
|
RETURN_OS_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop:
|
||||||
|
|
||||||
|
if (usleep(1000) < 0) {
|
||||||
|
RETURN_OS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
|
if (PyErr_CheckSignals() < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} while (now < 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(_field) TMP(_field) = MEM(_field)
|
||||||
COPY(unsigned, width);
|
COPY(width);
|
||||||
COPY(unsigned, height);
|
COPY(height);
|
||||||
COPY(unsigned, format);
|
COPY(format);
|
||||||
COPY(unsigned, stride);
|
COPY(stride);
|
||||||
COPY(bool, online);
|
COPY(online);
|
||||||
COPY(double, grab_ts);
|
COPY(grab_ts);
|
||||||
COPY(double, encode_begin_ts);
|
COPY(encode_begin_ts);
|
||||||
COPY(double, encode_end_ts);
|
COPY(encode_end_ts);
|
||||||
COPY(unsigned, used);
|
COPY(used);
|
||||||
# undef COPY
|
# undef COPY
|
||||||
|
|
||||||
// Временный буффер используется для скорейшего разблокирования синка
|
if (TMP(allocated) < MEM(used)) {
|
||||||
if (self->tmp_data_allocated < self->mem->used) {
|
size_t size = MEM(used) + (512 * 1024);
|
||||||
size_t size = self->mem->used + (512 * 1024);
|
A_REALLOC(TMP(data), size);
|
||||||
A_REALLOC(self->tmp_data, size);
|
TMP(allocated) = size;
|
||||||
self->tmp_data_allocated = size;
|
|
||||||
}
|
}
|
||||||
memcpy(self->tmp_data, self->mem->data, self->mem->used);
|
memcpy(TMP(data), MEM(data), MEM(used));
|
||||||
|
TMP(used) = MEM(used);
|
||||||
|
|
||||||
self->mem->last_client_ts = get_now_monotonic();
|
TMP(id) = MEM(id);
|
||||||
self->last_id = self->mem->id;
|
TMP(ts) = get_now_monotonic();
|
||||||
|
MEM(last_client_ts) = TMP(ts);
|
||||||
|
|
||||||
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->dict_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->dict_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); \
|
||||||
|
}
|
||||||
|
# define SET_NUMBER(_key, _from, _to) SET_VALUE(#_key, Py##_to##_From##_from(TMP(_key)))
|
||||||
|
|
||||||
|
SET_NUMBER(width, Long, Long);
|
||||||
|
SET_NUMBER(height, Long, Long);
|
||||||
|
SET_NUMBER(format, Long, Long);
|
||||||
|
SET_NUMBER(stride, Long, Long);
|
||||||
|
SET_NUMBER(online, Long, Bool);
|
||||||
|
SET_NUMBER(grab_ts, Double, Float);
|
||||||
|
SET_NUMBER(encode_begin_ts, Double, Float);
|
||||||
|
SET_NUMBER(encode_end_ts, Double, Float);
|
||||||
|
SET_VALUE("data", PyBytes_FromStringAndSize((const char *)TMP(data), TMP(used)));
|
||||||
|
|
||||||
|
# undef SET_NUMBER
|
||||||
# undef SET_VALUE
|
# undef SET_VALUE
|
||||||
PyDict_SetItemString(frame, "data", PyBytes_FromStringAndSize((const char *)self->tmp_data, tmp_used));
|
|
||||||
return frame;
|
Py_INCREF(self->dict_frame);
|
||||||
|
return self->dict_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *MemsinkObject_is_opened(MemsinkObject *self, PyObject *Py_UNUSED(ignored)) {
|
static PyObject *MemsinkObject_is_opened(MemsinkObject *self, PyObject *Py_UNUSED(ignored)) {
|
||||||
@@ -228,16 +315,18 @@ static PyObject *MemsinkObject_is_opened(MemsinkObject *self, PyObject *Py_UNUSE
|
|||||||
FIELD_GETTER(obj, String, Unicode)
|
FIELD_GETTER(obj, String, Unicode)
|
||||||
FIELD_GETTER(lock_timeout, Double, Float)
|
FIELD_GETTER(lock_timeout, Double, Float)
|
||||||
FIELD_GETTER(wait_timeout, Double, Float)
|
FIELD_GETTER(wait_timeout, Double, Float)
|
||||||
|
FIELD_GETTER(drop_same_frames, Double, Float)
|
||||||
|
|
||||||
#undef FIELD_GETTER
|
#undef FIELD_GETTER
|
||||||
|
|
||||||
static PyMethodDef MemsinkObject_methods[] = {
|
static PyMethodDef MemsinkObject_methods[] = {
|
||||||
# define ADD_METHOD(_meth, _flags) {.ml_name = #_meth, .ml_meth = (PyCFunction)MemsinkObject_##_meth, .ml_flags = (_flags)}
|
# define ADD_METHOD(_name, _method, _flags) \
|
||||||
ADD_METHOD(close, METH_NOARGS),
|
{.ml_name = _name, .ml_meth = (PyCFunction)MemsinkObject_##_method, .ml_flags = (_flags)}
|
||||||
ADD_METHOD(enter, METH_NOARGS),
|
ADD_METHOD("close", close, METH_NOARGS),
|
||||||
ADD_METHOD(exit, METH_VARARGS),
|
ADD_METHOD("__enter__", enter, METH_NOARGS),
|
||||||
ADD_METHOD(wait_frame, METH_NOARGS),
|
ADD_METHOD("__exit__", exit, METH_VARARGS),
|
||||||
ADD_METHOD(is_opened, METH_NOARGS),
|
ADD_METHOD("wait_frame", wait_frame, METH_NOARGS),
|
||||||
|
ADD_METHOD("is_opened", is_opened, METH_NOARGS),
|
||||||
{},
|
{},
|
||||||
# undef ADD_METHOD
|
# undef ADD_METHOD
|
||||||
};
|
};
|
||||||
@@ -247,6 +336,7 @@ static PyGetSetDef MemsinkObject_getsets[] = {
|
|||||||
ADD_GETTER(obj),
|
ADD_GETTER(obj),
|
||||||
ADD_GETTER(lock_timeout),
|
ADD_GETTER(lock_timeout),
|
||||||
ADD_GETTER(wait_timeout),
|
ADD_GETTER(wait_timeout),
|
||||||
|
ADD_GETTER(drop_same_frames),
|
||||||
{},
|
{},
|
||||||
# undef ADD_GETTER
|
# undef ADD_GETTER
|
||||||
};
|
};
|
||||||
@@ -288,3 +378,6 @@ PyMODINIT_FUNC PyInit_ustreamer(void) { // cppcheck-suppress unusedFunction
|
|||||||
|
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef TMP
|
||||||
|
#undef MEM
|
||||||
@@ -23,5 +23,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifndef VERSION
|
#ifndef VERSION
|
||||||
# define VERSION "3.6"
|
# define VERSION "3.13"
|
||||||
#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