mirror of
https://github.com/pikvm/ustreamer.git
synced 2026-02-19 16:26:30 +00:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5cfb3b1e60 | ||
|
|
82b3b78238 | ||
|
|
8a82ff6691 | ||
|
|
2807678551 | ||
|
|
e96e0aa73c | ||
|
|
d06c2619b2 | ||
|
|
6b18455d11 | ||
|
|
217977d9cb | ||
|
|
b9f186e47c | ||
|
|
d7d56f3536 | ||
|
|
2e3c764369 |
@@ -1,7 +1,7 @@
|
||||
[bumpversion]
|
||||
commit = True
|
||||
tag = True
|
||||
current_version = 3.12
|
||||
current_version = 3.14
|
||||
parse = (?P<major>\d+)\.(?P<minor>\d+)(\.(?P<patch>\d+)(\-(?P<release>[a-z]+))?)?
|
||||
serialize =
|
||||
{major}.{minor}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
FROM archlinux/base
|
||||
FROM archlinux/archlinux:base-devel
|
||||
|
||||
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 pacman -Syu --noconfirm \
|
||||
&& pacman -S --needed --noconfirm \
|
||||
base \
|
||||
base-devel \
|
||||
vim \
|
||||
git \
|
||||
libjpeg \
|
||||
@@ -17,7 +18,8 @@ RUN pacman -Syu --noconfirm \
|
||||
python-tox \
|
||||
cppcheck \
|
||||
npm \
|
||||
&& (pacman -Sc --noconfirm || true)
|
||||
&& (pacman -Sc --noconfirm || true) \
|
||||
&& rm -rf /var/cache/pacman/pkg/*
|
||||
|
||||
RUN npm install htmlhint -g
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Manpage for ustreamer-dump.
|
||||
.\" Open an issue or pull request to https://github.com/pikvm/ustreamer to correct errors or typos
|
||||
.TH USTREAMER-DUMP 1 "version 3.12" "January 2021"
|
||||
.TH USTREAMER-DUMP 1 "version 3.14" "January 2021"
|
||||
|
||||
.SH NAME
|
||||
ustreamer-dump \- Dump uStreamer's memory sink to file
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Manpage for ustreamer.
|
||||
.\" Open an issue or pull request to https://github.com/pikvm/ustreamer to correct errors or typos
|
||||
.TH USTREAMER 1 "version 3.12" "November 2020"
|
||||
.TH USTREAMER 1 "version 3.14" "November 2020"
|
||||
|
||||
.SH NAME
|
||||
ustreamer \- stream MJPG video from any V4L2 device to the network
|
||||
@@ -104,7 +104,7 @@ It doesn't do anything. Still here for compatibility. Required \fBWITH_OMX\fR fe
|
||||
Path to JPEG file that will be shown when the device is disconnected during the streaming. Default: black screen 640x480 with 'NO SIGNAL'.
|
||||
.TP
|
||||
.BR \-K\ \fIsec ", " \-\-last\-as\-blank\ \fIsec
|
||||
Show the last frame received from the camera after it was disconnected, but no more than specified time (or endlessly if 0 is specified). If the device has not yet been online, display 'NO SIGNAL' or the image specified by option \-\-blank. Default: disabled.
|
||||
Show the last frame received from the camera after it was disconnected, but no more than specified time (or endlessly if 0 is specified). If the device has not yet been online, display 'NO SIGNAL' or the image specified by option \-\-blank. Note: currently this option has no effect on memory sinks. Default: disabled.
|
||||
.TP
|
||||
.BR \-l ", " \-\-slowdown
|
||||
Slowdown capturing to 1 FPS or less when no stream or sink clients are connected. Useful to reduce CPU consumption. Default: disabled.
|
||||
@@ -118,7 +118,7 @@ Delay before trying to connect to the device again after an error (timeout for e
|
||||
.SS "Image control options"
|
||||
.TP
|
||||
.BR \-\-image\-default
|
||||
Reset all image settings bellow to default. Default: no change.
|
||||
Reset all image settings below to default. Default: no change.
|
||||
.TP
|
||||
.BR \-\-brightness\ \fIN ", " \fIauto ", " \fIdefault
|
||||
Set brightness. Default: no change.
|
||||
@@ -166,8 +166,8 @@ Bind to this TCP port. Default: 8080.
|
||||
.TP
|
||||
.BR \-U\ \fIpath ", " \-\-unix\ \fIpath
|
||||
Bind to UNIX domain socket. Default: disabled.
|
||||
.tp
|
||||
.br \-d ", " \-\-unix\-rm
|
||||
.TP
|
||||
.BR \-d ", " \-\-unix\-rm
|
||||
Try to remove old unix socket file before binding. default: disabled.
|
||||
.TP
|
||||
.BR \-M\ \fImode ", " \-\-unix\-mode\ \fImode
|
||||
@@ -234,6 +234,12 @@ Client TTL. Default: 10.
|
||||
.TP
|
||||
.BR \-\-h264\-sink\-timeout\ \fIsec
|
||||
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"
|
||||
.TP
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
|
||||
pkgname=ustreamer
|
||||
pkgver=3.12
|
||||
pkgver=3.14
|
||||
pkgrel=1
|
||||
pkgdesc="Lightweight and fast MJPG-HTTP streamer"
|
||||
url="https://github.com/pikvm/ustreamer"
|
||||
@@ -28,20 +28,21 @@ if [ -e /opt/vc/include/IL/OMX_Core.h ]; then
|
||||
fi
|
||||
|
||||
|
||||
# LD does not link mmal with this option
|
||||
# This DOESN'T affect setup.py
|
||||
LDFLAGS="${LDFLAGS//--as-needed/}"
|
||||
export LDFLAGS="${LDFLAGS//,,/,}"
|
||||
|
||||
|
||||
build() {
|
||||
cd "$srcdir"
|
||||
rm -rf $pkgname-build
|
||||
cp -r $pkgname $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
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$srcdir/$pkgname-build"
|
||||
make $_options DESTDIR="$pkgdir" PREFIX=/usr install
|
||||
make $_options CFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" DESTDIR="$pkgdir" PREFIX=/usr install
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ustreamer
|
||||
PKG_VERSION:=3.12
|
||||
PKG_VERSION:=3.14
|
||||
PKG_RELEASE:=1
|
||||
PKG_MAINTAINER:=Maxim Devaev <mdevaev@gmail.com>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ from distutils.core import setup
|
||||
if __name__ == "__main__":
|
||||
setup(
|
||||
name="ustreamer",
|
||||
version="3.12",
|
||||
version="3.14",
|
||||
description="uStreamer tools",
|
||||
author="Maxim Devaev",
|
||||
author_email="mdevaev@gmail.com",
|
||||
|
||||
@@ -23,5 +23,5 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef VERSION
|
||||
# define VERSION "3.12"
|
||||
# define VERSION "3.14"
|
||||
#endif
|
||||
|
||||
@@ -617,7 +617,8 @@ static void _help(FILE *fp, device_s *dev, encoder_s *enc, stream_s *stream, ser
|
||||
SAY(" -K|--last-as-blank <sec> ──────────── Show the last frame received from the camera after it was disconnected,");
|
||||
SAY(" but no more than specified time (or endlessly if 0 is specified).");
|
||||
SAY(" If the device has not yet been online, display 'NO SIGNAL' or the image");
|
||||
SAY(" specified by option --blank. Default: disabled.\n");
|
||||
SAY(" specified by option --blank. Default: disabled.");
|
||||
SAY(" Note: currently this option has no effect on memory sinks.\n");
|
||||
SAY(" -l|--slowdown ─────────────────────── Slowdown capturing to 1 FPS or less when no stream or sink clients");
|
||||
SAY(" are connected. Useful to reduce CPU consumption. Default: disabled.\n");
|
||||
SAY(" --device-timeout <sec> ────────────── Timeout for device querying. Default: %u.\n", dev->timeout);
|
||||
|
||||
@@ -25,11 +25,25 @@
|
||||
|
||||
static workers_pool_s *_stream_init_loop(stream_s *stream);
|
||||
static workers_pool_s *_stream_init_one(stream_s *stream);
|
||||
static bool _stream_expose_frame(stream_s *stream, frame_s *frame, unsigned captured_fps);
|
||||
static void _stream_expose_frame(stream_s *stream, frame_s *frame, unsigned captured_fps);
|
||||
|
||||
|
||||
#define RUN(_next) stream->run->_next
|
||||
|
||||
#define SINK_PUT(_sink, _frame) { \
|
||||
if (stream->_sink && memsink_server_check(stream->_sink, _frame)) {\
|
||||
memsink_server_put(stream->_sink, _frame); \
|
||||
} \
|
||||
}
|
||||
|
||||
#ifdef WITH_OMX
|
||||
# define H264_PUT(_frame, _vcsm_handle, _force_key) { \
|
||||
if (RUN(h264)) { \
|
||||
h264_stream_process(RUN(h264), _frame, _vcsm_handle, _force_key); \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
stream_s *stream_init(device_s *dev, encoder_s *enc) {
|
||||
stream_runtime_s *run;
|
||||
@@ -194,16 +208,9 @@ void stream_loop(stream_s *stream) {
|
||||
workers_pool_assign(pool, ready_wr);
|
||||
LOG_DEBUG("Assigned new frame in buffer %d to worker %s", buf_index, ready_wr->name);
|
||||
|
||||
if (stream->raw_sink) {
|
||||
if (memsink_server_check(stream->raw_sink, &hw->raw)) {
|
||||
memsink_server_put(stream->raw_sink, &hw->raw);
|
||||
}
|
||||
}
|
||||
|
||||
SINK_PUT(raw_sink, &hw->raw);
|
||||
# ifdef WITH_OMX
|
||||
if (RUN(h264)) {
|
||||
h264_stream_process(RUN(h264), &hw->raw, hw->vcsm_handle, h264_force_key);
|
||||
}
|
||||
H264_PUT(&hw->raw, hw->vcsm_handle, h264_force_key);
|
||||
# endif
|
||||
}
|
||||
} else if (buf_index != -2) { // -2 for broken frame
|
||||
@@ -253,18 +260,7 @@ static workers_pool_s *_stream_init_loop(stream_s *stream) {
|
||||
LOG_DEBUG("%s: stream->run->stop=%d", __FUNCTION__, atomic_load(&RUN(stop)));
|
||||
|
||||
while (!atomic_load(&RUN(stop))) {
|
||||
if (_stream_expose_frame(stream, NULL, 0)) {
|
||||
if (stream->raw_sink) {
|
||||
if (memsink_server_check(stream->raw_sink, stream->blank)) {
|
||||
memsink_server_put(stream->raw_sink, stream->blank);
|
||||
}
|
||||
}
|
||||
# ifdef WITH_OMX
|
||||
if (RUN(h264)) {
|
||||
h264_stream_process(RUN(h264), stream->blank, -1, false);
|
||||
}
|
||||
# endif
|
||||
}
|
||||
_stream_expose_frame(stream, NULL, 0);
|
||||
|
||||
if (access(stream->dev->path, R_OK|W_OK) < 0) {
|
||||
if (access_error != errno) {
|
||||
@@ -308,11 +304,10 @@ static workers_pool_s *_stream_init_one(stream_s *stream) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool _stream_expose_frame(stream_s *stream, frame_s *frame, unsigned captured_fps) {
|
||||
static void _stream_expose_frame(stream_s *stream, frame_s *frame, unsigned captured_fps) {
|
||||
# define VID(_next) RUN(video->_next)
|
||||
|
||||
frame_s *new = NULL;
|
||||
bool changed = false;
|
||||
|
||||
A_MUTEX_LOCK(&VID(mutex));
|
||||
|
||||
@@ -322,7 +317,11 @@ static bool _stream_expose_frame(stream_s *stream, frame_s *frame, unsigned capt
|
||||
LOG_DEBUG("Exposed ALIVE video frame");
|
||||
|
||||
} else {
|
||||
if (VID(frame->online)) { // Если переходим из online в offline
|
||||
if (VID(frame->used == 0)) {
|
||||
new = stream->blank; // Инициализация
|
||||
RUN(last_as_blank_ts) = 0;
|
||||
|
||||
} else if (VID(frame->online)) { // Если переходим из online в offline
|
||||
if (stream->last_as_blank < 0) { // Если last_as_blank выключен, просто покажем старую картинку
|
||||
new = stream->blank;
|
||||
LOG_INFO("Changed video frame to BLANK");
|
||||
@@ -332,6 +331,7 @@ static bool _stream_expose_frame(stream_s *stream, frame_s *frame, unsigned capt
|
||||
} else { // last_as_blank == 0 - показываем последний фрейм вечно
|
||||
LOG_INFO("Freezed last ALIVE video frame forever");
|
||||
}
|
||||
|
||||
} else if (stream->last_as_blank < 0) {
|
||||
new = stream->blank;
|
||||
// LOG_INFO("Changed video frame to BLANK");
|
||||
@@ -350,26 +350,28 @@ static bool _stream_expose_frame(stream_s *stream, frame_s *frame, unsigned capt
|
||||
|
||||
if (new) {
|
||||
frame_copy(new, VID(frame));
|
||||
changed = true;
|
||||
} else if (VID(frame->used) == 0) { // Инициализация
|
||||
frame_copy(stream->blank, VID(frame));
|
||||
frame = NULL;
|
||||
changed = true;
|
||||
}
|
||||
VID(frame->online) = frame;
|
||||
VID(frame->online) = (bool)frame;
|
||||
VID(captured_fps) = captured_fps;
|
||||
atomic_store(&VID(updated), true);
|
||||
|
||||
A_MUTEX_UNLOCK(&VID(mutex));
|
||||
|
||||
if (changed && stream->sink) {
|
||||
if (memsink_server_check(stream->sink, VID(frame))) {
|
||||
memsink_server_put(stream->sink, VID(frame));
|
||||
}
|
||||
}
|
||||
new = (frame ? frame : stream->blank);
|
||||
SINK_PUT(sink, new);
|
||||
|
||||
return changed;
|
||||
if (frame == NULL) {
|
||||
SINK_PUT(raw_sink, stream->blank);
|
||||
# ifdef WITH_OMX
|
||||
H264_PUT(stream->blank, -1, false);
|
||||
# endif
|
||||
}
|
||||
|
||||
# undef VID
|
||||
}
|
||||
|
||||
#ifdef WITH_OMX
|
||||
# undef H264_PUT
|
||||
#endif
|
||||
#undef SINK_PUT
|
||||
#undef RUN
|
||||
|
||||
Reference in New Issue
Block a user