mirror of
https://github.com/pikvm/ustreamer.git
synced 2026-02-27 12:16:31 +00:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fec76dc9eb | ||
|
|
48826208fd | ||
|
|
dd4fda6f5d | ||
|
|
1dafb54621 | ||
|
|
19f9567098 | ||
|
|
b3d1f06e5d | ||
|
|
f17069153d | ||
|
|
8a7d7b9c54 | ||
|
|
df7649d56f | ||
|
|
58cc227cba | ||
|
|
76be4a1d10 | ||
|
|
496c9300fc | ||
|
|
5b7780cf7c | ||
|
|
421f4a1f2e | ||
|
|
55a5d4bbdd | ||
|
|
666ae0c4f1 | ||
|
|
ca3afc074c |
@@ -1,7 +1,7 @@
|
|||||||
[bumpversion]
|
[bumpversion]
|
||||||
commit = True
|
commit = True
|
||||||
tag = True
|
tag = True
|
||||||
current_version = 4.9
|
current_version = 4.12
|
||||||
parse = (?P<major>\d+)\.(?P<minor>\d+)
|
parse = (?P<major>\d+)\.(?P<minor>\d+)
|
||||||
serialize =
|
serialize =
|
||||||
{major}.{minor}
|
{major}.{minor}
|
||||||
|
|||||||
@@ -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).
|
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`.
|
* 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`.
|
* 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```.
|
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:
|
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
|
```bash
|
||||||
|
$ export LD_LIBRARY_PATH=/opt/vc/lib/ # on bullseye
|
||||||
$ ./ustreamer \
|
$ ./ustreamer \
|
||||||
--format=uyvy \ # Device input format
|
--format=uyvy \ # Device input format
|
||||||
--encoder=omx \ # Hardware encoding with OpenMAX
|
--encoder=omx \ # Hardware encoding with OpenMAX
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ envlist = cppcheck, flake8, pylint, mypy, vulture, htmlhint
|
|||||||
skipsdist = true
|
skipsdist = true
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
basepython = python3.9
|
basepython = python3.10
|
||||||
changedir = /src
|
changedir = /src
|
||||||
|
|
||||||
[testenv:cppcheck]
|
[testenv:cppcheck]
|
||||||
|
|||||||
@@ -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 4.9" "January 2021"
|
.TH USTREAMER-DUMP 1 "version 4.12" "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 4.9" "November 2020"
|
.TH USTREAMER 1 "version 4.12" "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
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
|
|
||||||
pkgname=ustreamer
|
pkgname=ustreamer
|
||||||
pkgver=4.9
|
pkgver=4.12
|
||||||
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"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=ustreamer
|
PKG_NAME:=ustreamer
|
||||||
PKG_VERSION:=4.9
|
PKG_VERSION:=4.12
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
PKG_MAINTAINER:=Maxim Devaev <mdevaev@gmail.com>
|
PKG_MAINTAINER:=Maxim Devaev <mdevaev@gmail.com>
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from distutils.core import setup
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
setup(
|
setup(
|
||||||
name="ustreamer",
|
name="ustreamer",
|
||||||
version="4.9",
|
version="4.12",
|
||||||
description="uStreamer tools",
|
description="uStreamer tools",
|
||||||
author="Maxim Devaev",
|
author="Maxim Devaev",
|
||||||
author_email="mdevaev@gmail.com",
|
author_email="mdevaev@gmail.com",
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define VERSION_MAJOR 4
|
#define VERSION_MAJOR 4
|
||||||
#define VERSION_MINOR 9
|
#define VERSION_MINOR 12
|
||||||
|
|
||||||
#define MAKE_VERSION2(_major, _minor) #_major "." #_minor
|
#define MAKE_VERSION2(_major, _minor) #_major "." #_minor
|
||||||
#define MAKE_VERSION1(_major, _minor) MAKE_VERSION2(_major, _minor)
|
#define MAKE_VERSION1(_major, _minor) MAKE_VERSION2(_major, _minor)
|
||||||
|
|||||||
@@ -282,7 +282,7 @@ int device_switch_capturing(device_s *dev, bool enable) {
|
|||||||
RUN(capturing) = enable;
|
RUN(capturing) = enable;
|
||||||
LOG_INFO("Capturing %s", (enable ? "started" : "stopped"));
|
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) {
|
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) ...");
|
LOG_DEBUG("Calling ioctl(VIDIOC_QUERY_DV_TIMINGS) ...");
|
||||||
if (xioctl(RUN(fd), VIDIOC_QUERY_DV_TIMINGS, &dv) == 0) {
|
if (xioctl(RUN(fd), VIDIOC_QUERY_DV_TIMINGS, &dv) == 0) {
|
||||||
LOG_INFO("Got new DV timings: resolution=%ux%u, pixclk=%llu",
|
if (dv.type == V4L2_DV_BT_656_1120) {
|
||||||
dv.bt.width, dv.bt.height, (unsigned long long)dv.bt.pixelclock); // Issue #11
|
// 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) ...");
|
LOG_DEBUG("Calling ioctl(VIDIOC_S_DV_TIMINGS) ...");
|
||||||
if (xioctl(RUN(fd), VIDIOC_S_DV_TIMINGS, &dv) < 0) {
|
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) {
|
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) {
|
if (format == _FORMATS[index].format) {
|
||||||
return _FORMATS[index].name;
|
return _FORMATS[index].name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *_format_to_string_supported(unsigned format) {
|
static const char *_format_to_string_supported(unsigned format) {
|
||||||
|
|||||||
@@ -317,6 +317,10 @@ static void _http_callback_static(struct evhttp_request *request, void *v_server
|
|||||||
goto not_found;
|
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));
|
ADD_HEADER("Content-Type", guess_mime_type(static_path));
|
||||||
evhttp_send_reply(request, HTTP_OK, "OK", buf);
|
evhttp_send_reply(request, HTTP_OK, "OK", buf);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@@ -421,13 +425,14 @@ static void _http_callback_state(struct evhttp_request *request, void *v_server)
|
|||||||
LIST_ITERATE(RUN(stream_clients), client, {
|
LIST_ITERATE(RUN(stream_clients), client, {
|
||||||
assert(evbuffer_add_printf(buf,
|
assert(evbuffer_add_printf(buf,
|
||||||
"\"%" PRIx64 "\": {\"fps\": %u, \"extra_headers\": %s, \"advance_headers\": %s,"
|
"\"%" 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->id,
|
||||||
client->fps,
|
client->fps,
|
||||||
bool_to_string(client->extra_headers),
|
bool_to_string(client->extra_headers),
|
||||||
bool_to_string(client->advance_headers),
|
bool_to_string(client->advance_headers),
|
||||||
bool_to_string(client->dual_final_frames),
|
bool_to_string(client->dual_final_frames),
|
||||||
bool_to_string(client->zero_data),
|
bool_to_string(client->zero_data),
|
||||||
|
(client->key != NULL ? client->key : "0"),
|
||||||
(client->next ? ", " : "")
|
(client->next ? ", " : "")
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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)
|
ADD_SINK("raw-", raw_sink, RAW_SINK)
|
||||||
# ifdef WITH_OMX
|
# ifdef WITH_OMX
|
||||||
ADD_SINK("h264-", h264_sink, H264_SINK)
|
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);
|
case _O_H264_GOP: OPT_NUMBER("--h264-gop", stream->h264_gop, 0, 60, 0);
|
||||||
# endif
|
# endif
|
||||||
# undef ADD_SINK
|
# undef ADD_SINK
|
||||||
|
|||||||
Reference in New Issue
Block a user