Compare commits

...

14 Commits
v5.22 ... 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
18 changed files with 200 additions and 10 deletions

View File

@@ -1,7 +1,7 @@
[bumpversion]
commit = True
tag = True
current_version = 5.22
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

@@ -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

@@ -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

@@ -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.22" "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.22" "November 2020"
.TH USTREAMER 1 "version 5.24" "November 2020"
.SH NAME
ustreamer \- stream MJPEG video from any V4L2 device to the network
@@ -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.22
pkgver=5.24
pkgrel=1
pkgdesc="Lightweight and fast MJPEG-HTTP streamer"
url="https://github.com/pikvm/ustreamer"

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.22
PKG_VERSION:=5.24
PKG_RELEASE:=1
PKG_MAINTAINER:=Maxim Devaev <mdevaev@gmail.com>

View File

@@ -17,7 +17,7 @@ def _find_sources(suffix: str) -> list[str]:
if __name__ == "__main__":
setup(
name="ustreamer",
version="5.22",
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 22
#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

@@ -186,7 +186,7 @@ static void _m2m_encoder_prepare(us_m2m_encoder_s *enc, const us_frame_s *frame)
SET_OPTION(V4L2_CID_MPEG_VIDEO_H264_LEVEL, V4L2_MPEG_VIDEO_H264_LEVEL_5_1);
}
SET_OPTION(V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER, 1);
SET_OPTION(V4L2_CID_MPEG_VIDEO_H264_MIN_QP, 20);
SET_OPTION(V4L2_CID_MPEG_VIDEO_H264_MIN_QP, 16);
SET_OPTION(V4L2_CID_MPEG_VIDEO_H264_MAX_QP, 32);
} else if (enc->output_format == V4L2_PIX_FMT_MJPEG) {
SET_OPTION(V4L2_CID_MPEG_VIDEO_BITRATE, enc->bitrate);

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:"); \