mirror of
https://github.com/pikvm/ustreamer.git
synced 2026-02-27 12:16:31 +00:00
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fec76dc9eb | ||
|
|
48826208fd | ||
|
|
dd4fda6f5d | ||
|
|
1dafb54621 | ||
|
|
19f9567098 | ||
|
|
b3d1f06e5d | ||
|
|
f17069153d | ||
|
|
8a7d7b9c54 | ||
|
|
df7649d56f | ||
|
|
58cc227cba | ||
|
|
76be4a1d10 | ||
|
|
496c9300fc | ||
|
|
5b7780cf7c | ||
|
|
421f4a1f2e | ||
|
|
55a5d4bbdd | ||
|
|
666ae0c4f1 | ||
|
|
ca3afc074c | ||
|
|
030077fb47 | ||
|
|
61ddff8b6e | ||
|
|
27fbfe149e | ||
|
|
349f655cd9 | ||
|
|
f5c0a15967 | ||
|
|
d822ae0890 |
@@ -1,7 +1,7 @@
|
|||||||
[bumpversion]
|
[bumpversion]
|
||||||
commit = True
|
commit = True
|
||||||
tag = True
|
tag = True
|
||||||
current_version = 4.7
|
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
|
||||||
@@ -122,7 +123,6 @@ v4l2 utilities provide the tools to manage USB webcam setting and information. S
|
|||||||
-----
|
-----
|
||||||
# See also
|
# See also
|
||||||
* [Running uStreamer via systemd service](https://github.com/pikvm/ustreamer/issues/16).
|
* [Running uStreamer via systemd service](https://github.com/pikvm/ustreamer/issues/16).
|
||||||
* [uStreamer Ansible Role](https://github.com/mtlynch/ansible-role-ustreamer): Use [Ansible](https://docs.ansible.com/ansible/latest/index.html) to compile uStreamer and install it as a systemd service automatically.
|
|
||||||
|
|
||||||
-----
|
-----
|
||||||
# License
|
# License
|
||||||
|
|||||||
@@ -122,7 +122,6 @@ V4L2 предоставляет ряд официальных утилит дл
|
|||||||
-----
|
-----
|
||||||
# Смотрите также
|
# Смотрите также
|
||||||
* [Запуск с помощью systemd-сервиса](https://github.com/pikvm/ustreamer/issues/16).
|
* [Запуск с помощью systemd-сервиса](https://github.com/pikvm/ustreamer/issues/16).
|
||||||
* [uStreamer Ansible Role](https://github.com/mtlynch/ansible-role-ustreamer): Использование [Ansible](https://docs.ansible.com/ansible/latest/index.html) для сборки и установки стримера как systemd-сервиса.
|
|
||||||
|
|
||||||
-----
|
-----
|
||||||
# Лицензия
|
# Лицензия
|
||||||
|
|||||||
@@ -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.7" "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.7" "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.7
|
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.7
|
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.7",
|
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 7
|
#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)
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ typedef struct {
|
|||||||
_dest->encode_end_ts = _src->encode_end_ts; \
|
_dest->encode_end_ts = _src->encode_end_ts; \
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void frame_copy_meta(const frame_s *src, frame_s *dest) {
|
static inline void frame_copy_meta(const frame_s *src, frame_s *dest) {
|
||||||
FRAME_COPY_META(src, dest);
|
FRAME_COPY_META(src, dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,6 +97,6 @@ unsigned frame_get_padding(const frame_s *frame);
|
|||||||
|
|
||||||
const char *fourcc_to_string(unsigned format, char *buf, size_t size);
|
const char *fourcc_to_string(unsigned format, char *buf, size_t size);
|
||||||
|
|
||||||
inline bool is_jpeg(unsigned format) {
|
static inline bool is_jpeg(unsigned format) {
|
||||||
return (format == V4L2_PIX_FMT_JPEG || format == V4L2_PIX_FMT_MJPEG);
|
return (format == V4L2_PIX_FMT_JPEG || format == V4L2_PIX_FMT_MJPEG);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,30 +12,30 @@
|
|||||||
<hr>
|
<hr>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<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.
|
Get JSON structure with the state of the server.
|
||||||
</li>
|
</li>
|
||||||
<br>
|
<br>
|
||||||
<li>
|
<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.
|
Get a current actual image from the server.
|
||||||
</li>
|
</li>
|
||||||
<br>
|
<br>
|
||||||
<li>
|
<li>
|
||||||
<a href="/stream"><b>/stream</b></a><br>
|
<a href="stream"><b>/stream</b></a><br>
|
||||||
Get a live stream. Query params:<br>
|
Get a live stream. Query params:<br>
|
||||||
<br>
|
<br>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<b>key=abc123</b><br>
|
<b>key=abc123</b><br>
|
||||||
The user-defined key, which is part of cookie <i>stream_client</i>, which allows<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>
|
</li>
|
||||||
<br>
|
<br>
|
||||||
<li>
|
<li>
|
||||||
<b>extra_headers=1</b><br>
|
<b>extra_headers=1</b><br>
|
||||||
Add <i>X-UStreamer-*</i> headers to the <a href="/stream">/stream</a> handle
|
Add <i>X-UStreamer-*</i> headers to the <a href="stream">/stream</a> handle
|
||||||
(like with the <a href="/snapshot">/snapshot</a>).
|
(like with the <a href="snapshot">/snapshot</a>).
|
||||||
</li>
|
</li>
|
||||||
<br>
|
<br>
|
||||||
<li>
|
<li>
|
||||||
@@ -62,9 +62,9 @@
|
|||||||
The mjpg-streamer compatibility layer:<br>
|
The mjpg-streamer compatibility layer:<br>
|
||||||
<br>
|
<br>
|
||||||
<ul>
|
<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>
|
<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>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -37,30 +37,30 @@ const char *const HTML_INDEX_PAGE = " \
|
|||||||
<hr> \
|
<hr> \
|
||||||
<ul> \
|
<ul> \
|
||||||
<li> \
|
<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. \
|
Get JSON structure with the state of the server. \
|
||||||
</li> \
|
</li> \
|
||||||
<br> \
|
<br> \
|
||||||
<li> \
|
<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. \
|
Get a current actual image from the server. \
|
||||||
</li> \
|
</li> \
|
||||||
<br> \
|
<br> \
|
||||||
<li> \
|
<li> \
|
||||||
<a href=\"/stream\"><b>/stream</b></a><br> \
|
<a href=\"stream\"><b>/stream</b></a><br> \
|
||||||
Get a live stream. Query params:<br> \
|
Get a live stream. Query params:<br> \
|
||||||
<br> \
|
<br> \
|
||||||
<ul> \
|
<ul> \
|
||||||
<li> \
|
<li> \
|
||||||
<b>key=abc123</b><br> \
|
<b>key=abc123</b><br> \
|
||||||
The user-defined key, which is part of cookie <i>stream_client</i>, which allows<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> \
|
</li> \
|
||||||
<br> \
|
<br> \
|
||||||
<li> \
|
<li> \
|
||||||
<b>extra_headers=1</b><br> \
|
<b>extra_headers=1</b><br> \
|
||||||
Add <i>X-UStreamer-*</i> headers to the <a href=\"/stream\">/stream</a> handle \
|
Add <i>X-UStreamer-*</i> headers to the <a href=\"stream\">/stream</a> handle \
|
||||||
(like with the <a href=\"/snapshot\">/snapshot</a>). \
|
(like with the <a href=\"snapshot\">/snapshot</a>). \
|
||||||
</li> \
|
</li> \
|
||||||
<br> \
|
<br> \
|
||||||
<li> \
|
<li> \
|
||||||
@@ -87,9 +87,9 @@ const char *const HTML_INDEX_PAGE = " \
|
|||||||
The mjpg-streamer compatibility layer:<br> \
|
The mjpg-streamer compatibility layer:<br> \
|
||||||
<br> \
|
<br> \
|
||||||
<ul> \
|
<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> \
|
<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> \
|
</ul> \
|
||||||
</li> \
|
</li> \
|
||||||
</ul> \
|
</ul> \
|
||||||
|
|||||||
@@ -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