Compare commits

...

8 Commits
v5.26 ... v5.28

Author SHA1 Message Date
Maxim Devaev
c8600e62c2 Bump version: 5.27 → 5.28 2022-11-03 19:12:35 +03:00
Maxim Devaev
335f19f0e3 refactoring 2022-11-03 19:11:58 +03:00
Michael Lynch
a24e0eeb86 Document additional required audio packages (#184) 2022-11-03 19:11:26 +03:00
Michael Lynch
3fcb8d3ee5 Document additional required audio packages (#184) 2022-11-03 19:10:17 +03:00
Michael Lynch
ca30656bf8 Assign stream index on outgoing RTP packets (#182)
* Assign stream index on outgoing RTP packets (#5)

* Correctly assign mindex on outgoing rtp packets

Previously mindex was not set and defaulted to zero. This lead to most packets
getting dropped because of sequence number reuse when streaming both audio and
video. This reorders the SDP entries for video and audio so that video is first
in both a video-only and a audio+video configuration. This means that the mindex
for video packets should always be zero, and for audio (if present) should
always be one. This assumes there will never be an audio-only configuration.

* Adjust comments

Co-authored-by: Michael Lynch <git@mtlynch.io>

* Add preprocessor conditional to guard packet.mindex setting

The mindex field wasn't added to the janus_plugin_rtp_packet until Janus 1.0, so this change adds a precompiler check to ensure JANUS_PLUGIN_API_VERSION is >= 100 before assigning a value to the mindex field.

* Preserve audio-then-video ordering for Janus 0.x

Co-authored-by: Louis Goessling <louis@goessling.com>
2022-11-03 19:04:15 +03:00
Michael Lynch
4f0abf7eec Assign stream index on outgoing RTP packets (#182)
* Assign stream index on outgoing RTP packets (#5)

* Correctly assign mindex on outgoing rtp packets

Previously mindex was not set and defaulted to zero. This lead to most packets
getting dropped because of sequence number reuse when streaming both audio and
video. This reorders the SDP entries for video and audio so that video is first
in both a video-only and a audio+video configuration. This means that the mindex
for video packets should always be zero, and for audio (if present) should
always be one. This assumes there will never be an audio-only configuration.

* Adjust comments

Co-authored-by: Michael Lynch <git@mtlynch.io>

* Add preprocessor conditional to guard packet.mindex setting

The mindex field wasn't added to the janus_plugin_rtp_packet until Janus 1.0, so this change adds a precompiler check to ensure JANUS_PLUGIN_API_VERSION is >= 100 before assigning a value to the mindex field.

* Preserve audio-then-video ordering for Janus 0.x

Co-authored-by: Louis Goessling <louis@goessling.com>
2022-11-03 19:03:16 +03:00
Maxim Devaev
8b233a4c71 Bump version: 5.26 → 5.27 2022-11-01 22:30:04 +03:00
Maxim Devaev
8a81158276 improved dump 2022-11-01 20:59:16 +03:00
15 changed files with 38 additions and 22 deletions

View File

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

View File

@@ -38,7 +38,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, ```libjpeg9```/```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 `libgpiod-dev` for `WITH_GPIO=1` and `libsystemd-dev` for `WITH_SYSTEMD=1`.
* Raspbian: `sudo apt install libevent-dev libjpeg8-dev libbsd-dev`. Add `libgpiod-dev` for `WITH_GPIO=1` and `libsystemd-dev` for `WITH_SYSTEMD=1` and `libasound2-dev libspeex-dev libspeexdsp-dev libopus-dev` for `WITH_JANUS=1`.
* Debian/Ubuntu: `sudo apt install build-essential libevent-dev libjpeg-dev libbsd-dev`.
* Alpine: `sudo apk add libevent-dev libbsd-dev libjpeg-turbo-dev musl-dev`. Build with `WITH_PTHREAD_NP=0`.

View File

@@ -102,6 +102,11 @@ static void *_common_thread(void *v_client, bool video) {
packet.video = rtp->video;
packet.buffer = (char *)rtp->datagram;
packet.length = rtp->used;
# if JANUS_PLUGIN_API_VERSION >= 100
// The uStreamer Janus plugin places video in stream index 0 and audio
// (if available) in stream index 1.
packet.mindex = (rtp->video ? 0 : 1);
# endif
janus_plugin_rtp_extensions_reset(&packet.extensions);
// FIXME: Это очень эффективный способ уменьшить задержку, но WebRTC стек в хроме и фоксе
// слишком корявый, чтобы обработать это, из-за чего на кейфреймах начинаются заикания.

View File

@@ -440,7 +440,16 @@ static struct janus_plugin_result *_plugin_handle_message(
"s=PiKVM uStreamer" RN
"t=0 0" RN
"%s%s",
us_get_now_id() >> 1, audio_sdp, video_sdp
us_get_now_id() >> 1,
# if JANUS_PLUGIN_API_VERSION >= 100
// Place video SDP before audio SDP so that the video and audio streams
// have predictable indices, even if audio is not available.
// See also client.c.
video_sdp, audio_sdp
# else
// For versions of Janus prior to 1.x, place the audio SDP first.
audio_sdp, video_sdp
# endif
);
free(audio_sdp);
free(video_sdp);

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

View File

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

View File

@@ -6,7 +6,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=ustreamer
PKG_VERSION:=5.26
PKG_VERSION:=5.28
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.26",
version="5.28",
description="uStreamer tools",
author="Maxim Devaev",
author_email="mdevaev@gmail.com",

View File

@@ -52,11 +52,11 @@ void us_output_file_write(void *v_output, const us_frame_s *frame) {
us_base64_encode(frame->data, frame->used, &output->base64_data, &output->base64_allocated);
fprintf(output->fp,
"{\"size\": %zu, \"width\": %u, \"height\": %u,"
" \"format\": %u, \"stride\": %u, \"online\": %u,"
" \"format\": %u, \"stride\": %u, \"online\": %u, \"key\": %u,"
" \"grab_ts\": %.3Lf, \"encode_begin_ts\": %.3Lf, \"encode_end_ts\": %.3Lf,"
" \"data\": \"%s\"}\n",
frame->used, frame->width, frame->height,
frame->format, frame->stride, frame->online,
frame->format, frame->stride, frame->online, frame->key,
frame->grab_ts, frame->encode_begin_ts, frame->encode_end_ts,
output->base64_data);
} else {

View File

@@ -251,7 +251,8 @@ static int _dump_sink(
long double last_ts = 0;
while (!_g_stop) {
const int error = us_memsink_client_get(sink, frame, key_required);
bool key_requested;
const int error = us_memsink_client_get(sink, frame, &key_requested, key_required);
if (error == 0) {
key_required = false;
@@ -259,11 +260,12 @@ static int _dump_sink(
const long long now_second = us_floor_ms(now);
char fourcc_str[8];
US_LOG_VERBOSE("Frame: size=%zu, res=%ux%u, fourcc=%s, stride=%u, online=%d, key=%d, latency=%.3Lf, diff=%.3Lf",
frame->used, frame->width, frame->height,
US_LOG_VERBOSE("Frame: res=%ux%u, fmt=%s, stride=%u, online=%d, key=%d, kr=%d, latency=%.3Lf, diff=%.3Lf, size=%zu",
frame->width, frame->height,
us_fourcc_to_string(frame->format, fourcc_str, 8),
frame->stride, frame->online, frame->key,
now - frame->grab_ts, (last_ts ? now - last_ts : 0));
frame->stride, frame->online, frame->key, key_requested,
now - frame->grab_ts, (last_ts ? now - last_ts : 0),
frame->used);
last_ts = now;
US_LOG_DEBUG(" grab_ts=%.3Lf, encode_begin_ts=%.3Lf, encode_end_ts=%.3Lf",

View File

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

View File

@@ -136,9 +136,7 @@ int us_memsink_server_put(us_memsink_s *sink, const us_frame_s *frame, bool *con
if (sink->mem->key_requested && frame->key) {
sink->mem->key_requested = false;
}
if (key_requested != NULL) {
*key_requested = sink->mem->key_requested;
}
*key_requested = sink->mem->key_requested;
memcpy(sink->mem->data, frame->data, frame->used);
sink->mem->used = frame->used;
@@ -166,7 +164,7 @@ int us_memsink_server_put(us_memsink_s *sink, const us_frame_s *frame, bool *con
return 0;
}
int us_memsink_client_get(us_memsink_s *sink, us_frame_s *frame, bool key_required) { // cppcheck-suppress unusedFunction
int us_memsink_client_get(us_memsink_s *sink, us_frame_s *frame, bool *const key_requested, bool key_required) { // cppcheck-suppress unusedFunction
assert(!sink->server); // Client only
if (us_flock_timedwait_monotonic(sink->fd, sink->timeout) < 0) {
@@ -189,6 +187,7 @@ int us_memsink_client_get(us_memsink_s *sink, us_frame_s *frame, bool key_requir
sink->last_id = sink->mem->id;
us_frame_set_data(frame, sink->mem->data, sink->mem->used);
US_FRAME_COPY_META(sink->mem, frame);
*key_requested = sink->mem->key_requested;
retval = 0;
}
sink->mem->last_client_ts = us_get_now_monotonic();

View File

@@ -65,4 +65,4 @@ void us_memsink_destroy(us_memsink_s *sink);
bool us_memsink_server_check(us_memsink_s *sink, const us_frame_s *frame);
int us_memsink_server_put(us_memsink_s *sink, const us_frame_s *frame, bool *const key_requested);
int us_memsink_client_get(us_memsink_s *sink, us_frame_s *frame, bool key_required);
int us_memsink_client_get(us_memsink_s *sink, us_frame_s *frame, bool *const key_requested, bool key_required);

View File

@@ -32,7 +32,8 @@ static void _stream_expose_frame(us_stream_s *stream, us_frame_s *frame, unsigne
#define _SINK_PUT(x_sink, x_frame) { \
if (stream->x_sink && us_memsink_server_check(stream->x_sink, x_frame)) {\
us_memsink_server_put(stream->x_sink, x_frame, NULL); \
bool m_key_requested; /* Unused */ \
us_memsink_server_put(stream->x_sink, x_frame, &m_key_requested); \
} \
}