Compare commits

...

22 Commits
v5.19 ... v5.24

Author SHA1 Message Date
Maxim Devaev
bfa1516491 Bump version: 5.23 → 5.24 2022-10-19 08:13:54 +03:00
tomaszduda23
36c9ff22b3 set HDMI EDID before starting ustreamer (#179)
* build docker image

* Push each image to an user github registry.
It can be used during development for testing.

* set HDMI EDID before starting ustreamer

* Update README.md
2022-10-18 20:11:29 +03:00
Maxim Devaev
17f54a7977 Merge pull request #178 from tomaszduda23/github_registry
GitHub registry
2022-10-18 12:08:58 +03:00
Maxim Devaev
574986d0fd added --instance-id to the manpage 2022-10-16 02:54:28 +03:00
Maxim Devaev
d5ce2e835f report version 2022-10-13 02:10:16 +03:00
Maxim Devaev
6201554ba1 instance id 2022-10-12 20:00:37 +03:00
Maxim Devaev
75dee4e91d Merge pull request #177 from tomaszduda23/master
build docker image
2022-10-09 21:09:32 +03:00
Tomasz Duda
e1b4e0db66 Push each image to an user github registry.
It can be used during development for testing.
2022-10-09 15:17:35 +02:00
Tomasz Duda
0d37b09bb4 build docker image 2022-10-09 13:28:46 +02:00
Maxim Devaev
18767b68ff Merge pull request #176 from tomaszduda23/master
check compilation
2022-10-03 16:47:05 +03:00
Tomasz Duda
7975615c6c check compilation 2022-10-03 02:31:31 +02:00
Maxim Devaev
90f09b197e Bump version: 5.22 → 5.23 2022-09-25 17:17:28 +03:00
Maxim Devaev
687e97d523 Issue #169: Reverted MIN_QP to 16 2022-09-25 17:16:31 +03:00
Maxim Devaev
c1675001fa enabled paypal 2022-09-23 19:04:48 +03:00
Maxim Devaev
69cc45a2a0 Bump version: 5.21 → 5.22 2022-09-09 16:25:02 +03:00
Maxim Devaev
ece96b5834 changed arch mirror 2022-09-09 16:22:54 +03:00
Maxim Devaev
383ed7530b Issue #169: changed min QP to avoid stream corruption 2022-09-09 15:49:00 +03:00
Maxim Devaev
7f620c758f new style typing 2022-09-04 17:12:56 +03:00
Maxim Devaev
fb50eea526 Bump version: 5.20 → 5.21 2022-08-27 07:27:40 +03:00
Maxim Devaev
63f757a9da readme update 2022-08-27 07:25:44 +03:00
Maxim Devaev
4ec02d46b9 Bump version: 5.19 → 5.20 2022-08-17 17:59:16 +03:00
Maxim Devaev
527afb66df fixed arch deps 2022-08-17 17:55:59 +03:00
20 changed files with 208 additions and 22 deletions

View File

@@ -1,7 +1,7 @@
[bumpversion]
commit = True
tag = True
current_version = 5.19
current_version = 5.24
parse = (?P<major>\d+)\.(?P<minor>\d+)
serialize =
{major}.{minor}

View File

@@ -7,3 +7,4 @@
!python/**
!janus/**
!man/**
!pkg/docker/entry.sh

2
.github/FUNDING.yml vendored
View File

@@ -1,4 +1,4 @@
# These are supported funding model platforms
patreon: pikvm
#custom: https://www.paypal.me/mdevaev
custom: https://paypal.me/pikvm

View File

@@ -0,0 +1,81 @@
name: Build Alpine
on:
push:
branches: [master, build_*]
tags: [v*]
pull_request:
branches: [master]
jobs:
buildx:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v3
-
name: Login to GitHub Container Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
-
name: Login to DockerHub Container Registry
if: startsWith(github.ref, 'refs/tags/v')
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Docker meta
id: meta
uses: docker/metadata-action@v4
with:
images: |
${{ secrets.DOCKERHUB_USERNAME }}/ustreamer,enable=${{ startsWith(github.ref, 'refs/tags/v') }}
ghcr.io/${{ github.repository }},enable=${{ github.event_name != 'pull_request' }}
tags: |
type=ref,event=tag
type=sha,format=long
-
name: Set up QEMU
uses: docker/setup-qemu-action@v2
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
with:
driver-opts: image=moby/buildkit:master
-
name: Build and export to Docker
uses: docker/build-push-action@v3
with:
context: .
load: true
tags: ustreamer
file: pkg/docker/Dockerfile.alpine
-
name: Test
run: |
echo version: $(docker run --rm -e NO_EDID=1 -t ustreamer --version)
echo -e "features:\n$(docker run --rm -e NO_EDID=1 -t ustreamer --features)"
-
name: Build multi arch
uses: docker/build-push-action@v3
with:
context: .
platforms: linux/arm64,linux/amd64,linux/arm/v7
file: pkg/docker/Dockerfile.alpine
-
name: Push
if: steps.meta.outputs.tags != ''
uses: docker/build-push-action@v3
with:
context: .
platforms: linux/arm64,linux/amd64,linux/arm/v7
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
file: pkg/docker/Dockerfile.alpine

View File

@@ -5,7 +5,7 @@
[[Русская версия]](README.ru.md)
µStreamer is a lightweight and very quick server to stream [MJPEG](https://en.wikipedia.org/wiki/Motion_JPEG) video from any V4L2 device to the net. All new browsers have native support of this video format, as well as most video players such as mplayer, VLC etc.
µStreamer is a part of the [Pi-KVM](https://github.com/pikvm/pikvm) project designed to stream [VGA](https://www.amazon.com/dp/B0126O0RDC) and [HDMI](https://auvidea.com/b101-hdmi-to-csi-2-bridge-15-pin-fpc/) screencast hardware data with the highest resolution and FPS possible.
µStreamer is a part of the [PiKVM](https://github.com/pikvm/pikvm) project designed to stream [VGA](https://www.amazon.com/dp/B0126O0RDC) and [HDMI](https://auvidea.com/b101-hdmi-to-csi-2-bridge-15-pin-fpc/) screencast hardware data with the highest resolution and FPS possible.
µStreamer is very similar to [mjpg-streamer](https://github.com/jacksonliam/mjpg-streamer) with ```input_uvc.so``` and ```output_http.so``` plugins, however, there are some major differences. The key ones are:
@@ -81,6 +81,33 @@ $ ./ustreamer \
You can always view the full list of options with ```ustreamer --help```.
# Docker (Raspberry Pi 4 HDMI)
## Preparations
Add following lines to /boot/firmware/usercfg.txt:
```
gpu_mem=128
dtoverlay=tc358743
```
Check size of CMA:
```bash
$ dmesg | grep cma-reserved
[ 0.000000] Memory: 7700524K/8244224K available (11772K kernel code, 1278K rwdata, 4320K rodata, 4096K init, 1077K bss, 281556K reserved, 262144K cma-reserved)
```
If it is smaller than 128M add following to /boot/firmware/cmdline.txt:
```
cma=128M
```
Save changes and reboot.
## Launch
Start container:
```bash
$ docker run --device /dev/video0:/dev/video0 -p 8080:8080 pikvm/ustreamer:latest
```
Then access the web interface at port 8080 (e.g. http://raspberrypi.local:8080).
## EDID
Container will set HDMI EDID before starging ustreamer. Use `-e NO_EDID=1` to not set EDID. Use `-e EDID_HEX=xx` to specify custom EDID data.
-----
# Raspberry Pi Camera Example
Example usage for the Raspberry Pi v1 camera:

View File

@@ -5,7 +5,7 @@
[[English version]](README.md)
µStreamer - это маленький и очень быстрый сервер, который позволяет организовать трансляцию видео в формате [MJPEG](https://en.wikipedia.org/wiki/Motion_JPEG) с любого устройства V4L2 в сеть. Этот формат нативно поддерживается всеми современными браузерами и большинством приложений для просмотра видео (mplayer, VLC и так далее). µStreamer был разработан в рамках проекта [Pi-KVM](https://github.com/pikvm/pikvm) специально для стриминга с устройств видеозахвата [VGA](https://www.amazon.com/dp/B0126O0RDC) и [HDMI](https://auvidea.com/b101-hdmi-to-csi-2-bridge-15-pin-fpc/) с максимально возможным разрешением и FPS, которые только позволяет железо.
µStreamer - это маленький и очень быстрый сервер, который позволяет организовать трансляцию видео в формате [MJPEG](https://en.wikipedia.org/wiki/Motion_JPEG) с любого устройства V4L2 в сеть. Этот формат нативно поддерживается всеми современными браузерами и большинством приложений для просмотра видео (mplayer, VLC и так далее). µStreamer был разработан в рамках проекта [PiKVM](https://github.com/pikvm/pikvm) специально для стриминга с устройств видеозахвата [VGA](https://www.amazon.com/dp/B0126O0RDC) и [HDMI](https://auvidea.com/b101-hdmi-to-csi-2-bridge-15-pin-fpc/) с максимально возможным разрешением и FPS, которые только позволяет железо.
Функционально µStreamer очень похож на [mjpg-streamer](https://github.com/jacksonliam/mjpg-streamer) при использовании им плагинов ```input_uvc.so``` и ```output_http.so```, однако имеет ряд серьезных отличий. Основные приведены в этой таблице:

View File

@@ -250,7 +250,7 @@ static int _plugin_init(janus_callbacks *gw, const char *config_dir_path) {
// sysctl -w net.core.rmem_max=1000000
// sysctl -w net.core.wmem_max=1000000
US_JLOG_INFO("main", "Initializing plugin ...");
US_JLOG_INFO("main", "Initializing PiKVM uStreamer plugin %s ...", US_VERSION);
if (gw == NULL || config_dir_path == NULL || ((_g_config = us_config_init(config_dir_path)) == NULL)) {
return -1;
}

View File

@@ -3,7 +3,7 @@ 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 echo 'Server = https://mirror.rackspace.com/archlinux/$repo/os/$arch' > /etc/pacman.d/mirrorlist
RUN pacman -Syu --noconfirm \
&& pacman -S --needed --noconfirm \

View File

@@ -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 5.19" "January 2021"
.TH USTREAMER-DUMP 1 "version 5.24" "January 2021"
.SH NAME
ustreamer-dump \- Dump uStreamer's memory sink to file

View 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 5.19" "November 2020"
.TH USTREAMER 1 "version 5.24" "November 2020"
.SH NAME
ustreamer \- stream MJPEG video from any V4L2 device to the network
@@ -10,7 +10,7 @@ ustreamer \- stream MJPEG video from any V4L2 device to the network
.RI [OPTIONS]
.SH DESCRIPTION
µStreamer (\fBustreamer\fP) is a lightweight and very quick server to stream MJPEG video from any V4L2 device to the network. All new browsers have native support of this video format, as well as most video players such as mplayer, VLC etc. µStreamer is a part of the Pi-KVM project designed to stream VGA and HDMI screencast hardware data with the highest resolution and FPS possible.
µStreamer (\fBustreamer\fP) is a lightweight and very quick server to stream MJPEG video from any V4L2 device to the network. All new browsers have native support of this video format, as well as most video players such as mplayer, VLC etc. µStreamer is a part of the PiKVM project designed to stream VGA and HDMI screencast hardware data with the highest resolution and FPS possible.
.SH USAGE
Without arguments, \fBustreamer\fR will try to open \fB/dev/video0\fR with 640x480 resolution and start streaming on \fBhttp://127\.0\.0\.1:8080\fR\. You can override this behavior using parameters \fB\-\-device\fR, \fB\-\-host\fR and \fB\-\-port\fR\. For example, to stream to the world, run: \fBustreamer --device=/dev/video1 --host=0.0.0.0 --port=80\fR
@@ -203,6 +203,9 @@ Default: disabled.
.BR \-\-allow\-origin\ \fIstr
Set Access\-Control\-Allow\-Origin header. Default: disabled.
.TP
.BR \-\-instance\-id\ \fIstr
A short string identifier to be displayed in the /state handle. It must satisfy regexp ^[a-zA-Z0-9\./+_-]*$. Default: an empty string.
.TP
.BR \-\-server\-timeout\ \fIsec
Timeout for client connections. Default: 10.

View File

@@ -3,7 +3,7 @@
pkgname=ustreamer
pkgver=5.19
pkgver=5.24
pkgrel=1
pkgdesc="Lightweight and fast MJPEG-HTTP streamer"
url="https://github.com/pikvm/ustreamer"
@@ -22,8 +22,8 @@ if [ -e /usr/bin/python3 ]; then
makedepends+=(python-setuptools)
fi
if [ -e /usr/include/janus/plugins/plugin.h ];then
depends+=(janus-gateway-pikvm alsa-lib opus)
makedepends+=(janus-gateway-pikvm alsa-lib opus)
depends+=(janus-gateway alsa-lib opus)
makedepends+=(janus-gateway alsa-lib opus)
_options="$_options WITH_JANUS=1"
fi

View File

@@ -0,0 +1,34 @@
FROM alpine:3.16 as build
RUN apk add --no-cache \
alpine-sdk \
linux-headers \
libjpeg-turbo-dev \
libevent-dev \
libbsd-dev \
libgpiod-dev
WORKDIR /build/ustreamer/
COPY . .
RUN make -j5 WITH_GPIO=1
FROM alpine:3.16 as run
RUN apk add --no-cache \
libevent \
libjpeg-turbo \
libevent \
libgpiod \
libbsd \
v4l-utils
WORKDIR /ustreamer
COPY --from=build /build/ustreamer/src/ustreamer.bin ustreamer
RUN wget https://raw.githubusercontent.com/pikvm/kvmd/master/configs/kvmd/tc358743-edid.hex -O /edid.hex
COPY pkg/docker/entry.sh /
EXPOSE 8080
ENTRYPOINT ["/entry.sh"]
CMD ["--dv-timings", "--format", "UYVY"]
# vim: syntax=dockerfile

14
pkg/docker/entry.sh Executable file
View File

@@ -0,0 +1,14 @@
#!/bin/sh
set -e
[ -z "$NO_EDID" ] && {
[ -n "$EDID_HEX" ] && echo "$EDID_HEX" > /edid.hex
while true; do
v4l2-ctl --device=/dev/video0 --set-edid=file=/edid.hex --fix-edid-checksums --info-edid && break
echo 'Failed to set EDID. Reetrying...'
sleep 1
done
}
./ustreamer --host=0.0.0.0 $@

View File

@@ -6,7 +6,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=ustreamer
PKG_VERSION:=5.19
PKG_VERSION:=5.24
PKG_RELEASE:=1
PKG_MAINTAINER:=Maxim Devaev <mdevaev@gmail.com>

View File

@@ -1,14 +1,12 @@
import os
from typing import List
from setuptools import Extension
from setuptools import setup
# =====
def _find_sources(suffix: str) -> List[str]:
sources: List[str] = []
def _find_sources(suffix: str) -> list[str]:
sources: list[str] = []
for (root_path, _, names) in os.walk("src"):
for name in names:
if name.endswith(suffix):
@@ -19,7 +17,7 @@ def _find_sources(suffix: str) -> List[str]:
if __name__ == "__main__":
setup(
name="ustreamer",
version="5.19",
version="5.24",
description="uStreamer tools",
author="Maxim Devaev",
author_email="mdevaev@gmail.com",

View File

@@ -23,7 +23,7 @@
#pragma once
#define US_VERSION_MAJOR 5
#define US_VERSION_MINOR 19
#define US_VERSION_MINOR 24
#define US_MAKE_VERSION2(_major, _minor) #_major "." #_minor
#define US_MAKE_VERSION1(_major, _minor) US_MAKE_VERSION2(_major, _minor)

View File

@@ -75,6 +75,7 @@ us_server_s *us_server_init(us_stream_s *stream) {
server->passwd = "";
server->static_path = "";
server->allow_origin = "";
server->instance_id = "";
server->timeout = 10;
server->run = run;
@@ -400,7 +401,9 @@ static void _http_callback_state(struct evhttp_request *request, void *v_server)
_A_EVBUFFER_ADD_PRINTF(buf,
"{\"ok\": true, \"result\": {"
" \"instance_id\": \"%s\","
" \"encoder\": {\"type\": \"%s\", \"quality\": %u},",
server->instance_id,
us_encoder_type_to_string(enc_type),
enc_quality
);

View File

@@ -149,6 +149,7 @@ typedef struct us_server_sx {
char *passwd;
char *static_path;
char *allow_origin;
char *instance_id;
unsigned drop_same_frames;
unsigned fake_width;

View File

@@ -82,6 +82,7 @@ enum _US_OPT_VALUES {
_O_PASSWD,
_O_STATIC,
_O_ALLOW_ORIGIN,
_O_INSTANCE_ID,
_O_TCP_NODELAY,
_O_SERVER_TIMEOUT,
@@ -177,6 +178,7 @@ static const struct option _LONG_OPTS[] = {
{"static", required_argument, NULL, _O_STATIC},
{"drop-same-frames", required_argument, NULL, _O_DROP_SAME_FRAMES},
{"allow-origin", required_argument, NULL, _O_ALLOW_ORIGIN},
{"instance-id", required_argument, NULL, _O_INSTANCE_ID},
{"fake-resolution", required_argument, NULL, _O_FAKE_RESOLUTION},
{"tcp-nodelay", no_argument, NULL, _O_TCP_NODELAY},
{"server-timeout", required_argument, NULL, _O_SERVER_TIMEOUT},
@@ -228,6 +230,7 @@ static const struct option _LONG_OPTS[] = {
static int _parse_resolution(const char *str, unsigned *width, unsigned *height, bool limited);
static int _check_instance_id(const char *str);
static void _features(void);
static void _help(FILE *fp, us_device_s *dev, us_encoder_s *enc, us_stream_s *stream, us_server_s *server);
@@ -419,6 +422,13 @@ int options_parse(us_options_s *options, us_device_s *dev, us_encoder_s *enc, us
case _O_DROP_SAME_FRAMES: OPT_NUMBER("--drop-same-frames", server->drop_same_frames, 0, US_VIDEO_MAX_FPS, 0);
case _O_FAKE_RESOLUTION: OPT_RESOLUTION("--fake-resolution", server->fake_width, server->fake_height, false);
case _O_ALLOW_ORIGIN: OPT_SET(server->allow_origin, optarg);
case _O_INSTANCE_ID:
if (_check_instance_id(optarg) != 0) {
printf("Invalid instance ID, it should be like: ^[a-zA-Z0-9\\./+_-]*$\n");
return -1;
}
server->instance_id = optarg;
break;
case _O_TCP_NODELAY: OPT_SET(server->tcp_nodelay, true);
case _O_SERVER_TIMEOUT: OPT_NUMBER("--server-timeout", server->timeout, 1, 60, 0);
@@ -473,6 +483,8 @@ int options_parse(us_options_s *options, us_device_s *dev, us_encoder_s *enc, us
}
}
US_LOG_INFO("Starting PiKVM uStreamer %s ...", US_VERSION);
options->blank = us_blank_frame_init(blank_path);
stream->blank = options->blank;
@@ -530,6 +542,18 @@ static int _parse_resolution(const char *str, unsigned *width, unsigned *height,
return 0;
}
static int _check_instance_id(const char *str) {
for (const char *ptr = str; *ptr; ++ptr) {
if (!(isascii(*ptr) && (
isalpha(*ptr) || isdigit(*ptr)
|| *ptr == '.' || *ptr == '/' || *ptr == '+' || *ptr == '_' || *ptr == '-'
))) {
return -1;
}
}
return 0;
}
static void _features(void) {
# ifdef WITH_GPIO
puts("+ WITH_GPIO");
@@ -657,6 +681,8 @@ static void _help(FILE *fp, us_device_s *dev, us_encoder_s *enc, us_stream_s *st
SAY(" --tcp-nodelay ────────────── Set TCP_NODELAY flag to the client /stream socket. Only for TCP socket.");
SAY(" Default: disabled.\n");
SAY(" --allow-origin <str> ─────── Set Access-Control-Allow-Origin header. Default: disabled.\n");
SAY(" --instance-id <str> ──────── A short string identifier to be displayed in the /state handle.");
SAY(" It must satisfy regexp ^[a-zA-Z0-9\\./+_-]*$. Default: an empty string.\n");
SAY(" --server-timeout <sec> ───── Timeout for client connections. Default: %u.\n", server->timeout);
# define ADD_SINK(x_name, x_opt) \
SAY(x_name " sink options:"); \

View File

@@ -26,13 +26,11 @@ import os
import io
import struct
from typing import Tuple
import common
# =====
def _get_jpeg_size(data: bytes) -> Tuple[int, int]:
def _get_jpeg_size(data: bytes) -> tuple[int, int]:
# https://sheep.horse/2013/9/finding_the_dimensions_of_a_jpeg_file_in_python.html
stream = io.BytesIO(data)