Compare commits

...

20 Commits
v4.8 ... v4.12

Author SHA1 Message Date
Maxim Devaev
fec76dc9eb Bump version: 4.11 → 4.12 2022-02-11 20:53:52 +03:00
Maxim Devaev
48826208fd Fixed #143: Show HDMI info 2022-02-11 20:00:47 +03:00
Maxim Devaev
dd4fda6f5d fixed indent 2022-02-11 19:57:15 +03:00
Maxim Devaev
1dafb54621 Merge pull request #140 from fphammerle/readme-libopenmaxil-on-bullseye
readme: suggest adding `/opt/vc/lib/` to library search path on bullseye
2022-02-05 14:44:26 +03:00
Maxim Devaev
19f9567098 added comment about evbuffer_add_file() 2022-02-05 14:35:07 +03:00
Maxim Devaev
b3d1f06e5d Merge pull request #141 from russdill/evbuffer_add_file_fix
Don't close evbuffer_add_file's file descriptor
2022-02-05 14:30:24 +03:00
Maxim Devaev
f17069153d fixed quotes 2022-02-05 14:12:54 +03:00
Maxim Devaev
8a7d7b9c54 Merge pull request #142 from russdill/client-key-in-state
Expose supplied client key in state
2022-02-05 14:09:34 +03:00
Russ Dill
df7649d56f Expose supplied client key in state
The client key and id is currently supplied in a cookie. This
provides a way for a client to determine it's id in order to match
it within the state response. However if cookies are disabled or
the source domain differs from the ustreamer domain the cookie will
not be set.

This provides an alternate way for a client to find the state
response associated with it's connection by including the client
provided key in the state response. If the client does not supply
a key, the value 0 is supplied.

Signed-off-by: Russ Dill <russ.dill@gmail.com>
2022-02-04 23:07:41 -08:00
Russ Dill
58cc227cba Don't close evbuffer_add_file's file descriptor
evbuffer_add_file takes ownership for the file descriptor we pass
and manages closing it. Closing it ourselves will lead to the function
only being able to make very small transfers.

Signed-off-by: Russ Dill <russ.dill@gmail.com>
2022-02-04 23:06:22 -08:00
Fabian Peter Hammerle
76be4a1d10 readme: suggest adding /opt/vc/lib/ to library search path on bullseye
On Raspberry Pi OS Bullseye:
```sh
$ make WITH_OMX=1
[...]
== LD ustreamer.bin
/usr/bin/ld: warning: libbrcmGLESv2.so, needed by /opt/vc/lib/libopenmaxil.so, not found (try using -rpath or -rpath-link)
/usr/bin/ld: warning: libbrcmEGL.so, needed by /opt/vc/lib/libopenmaxil.so, not found (try using -rpath or -rpath-link)
[...]
$ ./ustreamer --features
./ustreamer: error while loading shared libraries: libopenmaxil.so: cannot open shared object file: No such file or directory
$ LD_LIBRARY_PATH=/opt/vc/lib/ ./ustreamer --features
+ WITH_OMX
- WITH_GPIO
+ WITH_PTHREAD_NP
+ WITH_SETPROCTITLE
+ HAS_PDEATHSIG
```
2022-01-30 19:57:43 +01:00
Maxim Devaev
496c9300fc Bump version: 4.10 → 4.11 2021-12-31 01:28:51 +03:00
Maxim Devaev
5b7780cf7c using python-3.10 2021-12-31 01:26:47 +03:00
Maxim Devaev
421f4a1f2e Bump version: 4.9 → 4.10 2021-11-28 08:43:41 +03:00
Maxim Devaev
55a5d4bbdd real bitrate range 2021-11-28 08:40:56 +03:00
Maxim Devaev
666ae0c4f1 Merge pull request #133 from jtrmal/patch-1
correct/updated package name is libgpiod-dev
2021-11-26 03:33:04 +03:00
Jan "yenda" Trmal
ca3afc074c correct/updated package name is libgpiod-dev 2021-11-21 12:19:03 -05:00
Maxim Devaev
030077fb47 Bump version: 4.8 → 4.9 2021-10-30 11:40:31 +03:00
Maxim Devaev
61ddff8b6e Merge pull request #129 from b-rad15/master
Change html links to relative not absolute
2021-10-30 11:27:20 +03:00
Bradley O'Connell
27fbfe149e changed html links to relative not absolute 2021-10-30 03:20:57 -04:00
14 changed files with 53 additions and 33 deletions

View File

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

View File

@@ -37,7 +37,7 @@ If you're going to live-stream from your backyard webcam and need to control it,
You'll need ```make```, ```gcc```, ```libevent``` with ```pthreads``` support, ```libjpeg8```/```libjpeg-turbo``` and ```libbsd``` (only for Linux).
* Arch: `sudo pacman -S libevent libjpeg-turbo libutil-linux libbsd`.
* Raspbian: `sudo apt install libevent-dev libjpeg8-dev libbsd-dev`. Add `libraspberrypi-dev` for `WITH_OMX=1` and `libgpiod` for `WITH_GPIO=1`.
* Raspbian: `sudo apt install libevent-dev libjpeg8-dev libbsd-dev`. Add `libraspberrypi-dev` for `WITH_OMX=1` and `libgpiod-dev` for `WITH_GPIO=1`.
* Debian/Ubuntu: `sudo apt install build-essential libevent-dev libjpeg-dev libbsd-dev`.
On Raspberry Pi you can build the program with OpenMAX IL. To do this pass option ```WITH_OMX=1``` to ```make```. To enable GPIO support install [libgpiod](https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/about) and pass option ```WITH_GPIO=1```. If the compiler reports about a missing function ```pthread_get_name_np()``` (or similar), add option ```WITH_PTHREAD_NP=0``` (it's enabled by default). For the similar error with ```setproctitle()``` add option ```WITH_SETPROCTITLE=0```.
@@ -63,6 +63,7 @@ Without arguments, ```ustreamer``` will try to open ```/dev/video0``` with 640x4
The recommended way of running µStreamer with [Auvidea B101](https://www.raspberrypi.org/forums/viewtopic.php?f=38&t=120702&start=400#p1339178) on Raspberry Pi:
```bash
$ export LD_LIBRARY_PATH=/opt/vc/lib/ # on bullseye
$ ./ustreamer \
--format=uyvy \ # Device input format
--encoder=omx \ # Hardware encoding with OpenMAX

View File

@@ -3,7 +3,7 @@ envlist = cppcheck, flake8, pylint, mypy, vulture, htmlhint
skipsdist = true
[testenv]
basepython = python3.9
basepython = python3.10
changedir = /src
[testenv:cppcheck]

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 4.8" "January 2021"
.TH USTREAMER-DUMP 1 "version 4.12" "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 4.8" "November 2020"
.TH USTREAMER 1 "version 4.12" "November 2020"
.SH NAME
ustreamer \- stream MJPG video from any V4L2 device to the network

View File

@@ -3,7 +3,7 @@
pkgname=ustreamer
pkgver=4.8
pkgver=4.12
pkgrel=1
pkgdesc="Lightweight and fast MJPG-HTTP streamer"
url="https://github.com/pikvm/ustreamer"

View File

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

View File

@@ -8,7 +8,7 @@ from distutils.core import setup
if __name__ == "__main__":
setup(
name="ustreamer",
version="4.8",
version="4.12",
description="uStreamer tools",
author="Maxim Devaev",
author_email="mdevaev@gmail.com",

View File

@@ -23,7 +23,7 @@
#pragma once
#define VERSION_MAJOR 4
#define VERSION_MINOR 8
#define VERSION_MINOR 12
#define MAKE_VERSION2(_major, _minor) #_major "." #_minor
#define MAKE_VERSION1(_major, _minor) MAKE_VERSION2(_major, _minor)

View File

@@ -12,30 +12,30 @@
<hr>
<ul>
<li>
<a href="/state"><b>/state</b></a><br>
<a href="state"><b>/state</b></a><br>
Get JSON structure with the state of the server.
</li>
<br>
<li>
<a href="/snapshot"><b>/snapshot</b></a><br>
<a href="snapshot"><b>/snapshot</b></a><br>
Get a current actual image from the server.
</li>
<br>
<li>
<a href="/stream"><b>/stream</b></a><br>
<a href="stream"><b>/stream</b></a><br>
Get a live stream. Query params:<br>
<br>
<ul>
<li>
<b>key=abc123</b><br>
The user-defined key, which is part of cookie <i>stream_client</i>, which allows<br>
the stream client to determine its identifier and view statistics using <a href="/state">/state</a>.
the stream client to determine its identifier and view statistics using <a href="state">/state</a>.
</li>
<br>
<li>
<b>extra_headers=1</b><br>
Add <i>X-UStreamer-*</i> headers to the <a href="/stream">/stream</a> handle
(like with the <a href="/snapshot">/snapshot</a>).
Add <i>X-UStreamer-*</i> headers to the <a href="stream">/stream</a> handle
(like with the <a href="snapshot">/snapshot</a>).
</li>
<br>
<li>
@@ -62,9 +62,9 @@
The mjpg-streamer compatibility layer:<br>
<br>
<ul>
<li><a href="/?action=snapshot">/?action=snapshot</a> as alias to the <a href="/snapshot">/snapshot</a>.</li>
<li><a href="?action=snapshot">/?action=snapshot</a> as alias to the <a href="snapshot">/snapshot</a>.</li>
<br>
<li><a href="/?action=stream">/?action=stream</a> as alias to the <a href="/stream">/stream</a>.</li>
<li><a href="?action=stream">/?action=stream</a> as alias to the <a href="stream">/stream</a>.</li>
</ul>
</li>
</ul>

View File

@@ -37,30 +37,30 @@ const char *const HTML_INDEX_PAGE = " \
<hr> \
<ul> \
<li> \
<a href=\"/state\"><b>/state</b></a><br> \
<a href=\"state\"><b>/state</b></a><br> \
Get JSON structure with the state of the server. \
</li> \
<br> \
<li> \
<a href=\"/snapshot\"><b>/snapshot</b></a><br> \
<a href=\"snapshot\"><b>/snapshot</b></a><br> \
Get a current actual image from the server. \
</li> \
<br> \
<li> \
<a href=\"/stream\"><b>/stream</b></a><br> \
<a href=\"stream\"><b>/stream</b></a><br> \
Get a live stream. Query params:<br> \
<br> \
<ul> \
<li> \
<b>key=abc123</b><br> \
The user-defined key, which is part of cookie <i>stream_client</i>, which allows<br> \
the stream client to determine its identifier and view statistics using <a href=\"/state\">/state</a>. \
the stream client to determine its identifier and view statistics using <a href=\"state\">/state</a>. \
</li> \
<br> \
<li> \
<b>extra_headers=1</b><br> \
Add <i>X-UStreamer-*</i> headers to the <a href=\"/stream\">/stream</a> handle \
(like with the <a href=\"/snapshot\">/snapshot</a>). \
Add <i>X-UStreamer-*</i> headers to the <a href=\"stream\">/stream</a> handle \
(like with the <a href=\"snapshot\">/snapshot</a>). \
</li> \
<br> \
<li> \
@@ -87,9 +87,9 @@ const char *const HTML_INDEX_PAGE = " \
The mjpg-streamer compatibility layer:<br> \
<br> \
<ul> \
<li><a href=\"/?action=snapshot\">/?action=snapshot</a> as alias to the <a href=\"/snapshot\">/snapshot</a>.</li> \
<li><a href=\"?action=snapshot\">/?action=snapshot</a> as alias to the <a href=\"snapshot\">/snapshot</a>.</li> \
<br> \
<li><a href=\"/?action=stream\">/?action=stream</a> as alias to the <a href=\"/stream\">/stream</a>.</li> \
<li><a href=\"?action=stream\">/?action=stream</a> as alias to the <a href=\"stream\">/stream</a>.</li> \
</ul> \
</li> \
</ul> \

View File

@@ -282,7 +282,7 @@ int device_switch_capturing(device_s *dev, bool enable) {
RUN(capturing) = enable;
LOG_INFO("Capturing %s", (enable ? "started" : "stopped"));
}
return 0;
return 0;
}
int device_select(device_s *dev, bool *has_read, bool *has_write, bool *has_error) {
@@ -497,8 +497,22 @@ static int _device_apply_dv_timings(device_s *dev) {
LOG_DEBUG("Calling ioctl(VIDIOC_QUERY_DV_TIMINGS) ...");
if (xioctl(RUN(fd), VIDIOC_QUERY_DV_TIMINGS, &dv) == 0) {
LOG_INFO("Got new DV timings: resolution=%ux%u, pixclk=%llu",
dv.bt.width, dv.bt.height, (unsigned long long)dv.bt.pixelclock); // Issue #11
if (dv.type == V4L2_DV_BT_656_1120) {
// See v4l2_print_dv_timings() in the kernel
unsigned htot = V4L2_DV_BT_FRAME_WIDTH(&dv.bt);
unsigned vtot = V4L2_DV_BT_FRAME_HEIGHT(&dv.bt);
if (dv.bt.interlaced) {
vtot /= 2;
}
unsigned fps = ((htot * vtot) > 0 ? ((100 * (uint64_t)dv.bt.pixelclock)) / (htot * vtot) : 0);
LOG_INFO("Got new DV-timings: %ux%u%s%u.%02u, pixclk=%llu, vsync=%u, hsync=%u",
dv.bt.width, dv.bt.height, (dv.bt.interlaced ? "i" : "p"), fps / 100, fps % 100,
(unsigned long long)dv.bt.pixelclock, dv.bt.vsync, dv.bt.hsync); // See #11 about %llu
} else {
LOG_INFO("Got new DV-timings: %ux%u, pixclk=%llu, vsync=%u, hsync=%u",
dv.bt.width, dv.bt.height,
(unsigned long long)dv.bt.pixelclock, dv.bt.vsync, dv.bt.hsync);
}
LOG_DEBUG("Calling ioctl(VIDIOC_S_DV_TIMINGS) ...");
if (xioctl(RUN(fd), VIDIOC_S_DV_TIMINGS, &dv) < 0) {
@@ -906,12 +920,12 @@ static void _device_set_control(
}
static const char *_format_to_string_nullable(unsigned format) {
for (unsigned index = 0; index < ARRAY_LEN(_FORMATS); ++index) {
for (unsigned index = 0; index < ARRAY_LEN(_FORMATS); ++index) {
if (format == _FORMATS[index].format) {
return _FORMATS[index].name;
}
}
return NULL;
}
return NULL;
}
static const char *_format_to_string_supported(unsigned format) {

View File

@@ -317,6 +317,10 @@ static void _http_callback_static(struct evhttp_request *request, void *v_server
goto not_found;
}
// evbuffer_add_file() owns the resulting file descriptor
// and will close it when finished transferring data
fd = -1;
ADD_HEADER("Content-Type", guess_mime_type(static_path));
evhttp_send_reply(request, HTTP_OK, "OK", buf);
goto cleanup;
@@ -421,13 +425,14 @@ static void _http_callback_state(struct evhttp_request *request, void *v_server)
LIST_ITERATE(RUN(stream_clients), client, {
assert(evbuffer_add_printf(buf,
"\"%" PRIx64 "\": {\"fps\": %u, \"extra_headers\": %s, \"advance_headers\": %s,"
" \"dual_final_frames\": %s, \"zero_data\": %s}%s",
" \"dual_final_frames\": %s, \"zero_data\": %s, \"key\": \"%s\"}%s",
client->id,
client->fps,
bool_to_string(client->extra_headers),
bool_to_string(client->advance_headers),
bool_to_string(client->dual_final_frames),
bool_to_string(client->zero_data),
(client->key != NULL ? client->key : "0"),
(client->next ? ", " : "")
));
});

View File

@@ -438,7 +438,7 @@ int options_parse(options_s *options, device_s *dev, encoder_s *enc, stream_s *s
ADD_SINK("raw-", raw_sink, RAW_SINK)
# ifdef WITH_OMX
ADD_SINK("h264-", h264_sink, H264_SINK)
case _O_H264_BITRATE: OPT_NUMBER("--h264-bitrate", stream->h264_bitrate, 100, 16000, 0);
case _O_H264_BITRATE: OPT_NUMBER("--h264-bitrate", stream->h264_bitrate, 25, 25000, 0);
case _O_H264_GOP: OPT_NUMBER("--h264-gop", stream->h264_gop, 0, 60, 0);
# endif
# undef ADD_SINK