auto playout delay

This commit is contained in:
Maxim Devaev
2022-11-13 06:26:30 +03:00
parent c1363d55e0
commit 414f536ace
9 changed files with 19 additions and 22 deletions

View File

@@ -108,12 +108,13 @@ static void *_common_thread(void *v_client, bool video) {
packet.mindex = (rtp->video ? 0 : 1); packet.mindex = (rtp->video ? 0 : 1);
# endif # endif
janus_plugin_rtp_extensions_reset(&packet.extensions); janus_plugin_rtp_extensions_reset(&packet.extensions);
// FIXME: Это очень эффективный способ уменьшить задержку, но WebRTC стек в хроме и фоксе
// слишком корявый, чтобы обработать это, из-за чего на кейфреймах начинаются заикания.
// - https://github.com/Glimesh/janus-ftl-plugin/issues/101
if (rtp->zero_playout_delay) { if (rtp->zero_playout_delay) {
// https://github.com/pikvm/pikvm/issues/784
packet.extensions.min_delay = 0; packet.extensions.min_delay = 0;
packet.extensions.max_delay = 0; packet.extensions.max_delay = 0;
} else {
packet.extensions.min_delay = 0;
packet.extensions.max_delay = 1000;
} }
client->gw->relay_rtp(client->session, &packet); client->gw->relay_rtp(client->session, &packet);
} }

View File

@@ -24,7 +24,7 @@
static char *_get_value(janus_config *jcfg, const char *section, const char *option); static char *_get_value(janus_config *jcfg, const char *section, const char *option);
static bool _get_bool(janus_config *jcfg, const char *section, const char *option, bool def); // static bool _get_bool(janus_config *jcfg, const char *section, const char *option, bool def);
us_config_s *us_config_init(const char *config_dir_path) { us_config_s *us_config_init(const char *config_dir_path) {
@@ -51,9 +51,6 @@ us_config_s *us_config_init(const char *config_dir_path) {
US_JLOG_ERROR("config", "Missing config value: video.sink (ex. memsink.object)"); US_JLOG_ERROR("config", "Missing config value: video.sink (ex. memsink.object)");
goto error; goto error;
} }
if ((config->video_zero_playout_delay = _get_bool(jcfg, "video", "zero_playout_delay", false)) == true) {
US_JLOG_INFO("config", "Enabled the experimental Playout-Delay=0 RTP extension for VIDEO");
}
if ((config->audio_dev_name = _get_value(jcfg, "audio", "device")) != NULL) { if ((config->audio_dev_name = _get_value(jcfg, "audio", "device")) != NULL) {
US_JLOG_INFO("config", "Enabled the experimental AUDIO feature"); US_JLOG_INFO("config", "Enabled the experimental AUDIO feature");
if ((config->tc358743_dev_path = _get_value(jcfg, "audio", "tc358743")) == NULL) { if ((config->tc358743_dev_path = _get_value(jcfg, "audio", "tc358743")) == NULL) {
@@ -88,7 +85,7 @@ static char *_get_value(janus_config *jcfg, const char *section, const char *opt
return us_strdup(option_obj->value); return us_strdup(option_obj->value);
} }
static bool _get_bool(janus_config *jcfg, const char *section, const char *option, bool def) { /*static bool _get_bool(janus_config *jcfg, const char *section, const char *option, bool def) {
char *const tmp = _get_value(jcfg, section, option); char *const tmp = _get_value(jcfg, section, option);
bool value = def; bool value = def;
if (tmp != NULL) { if (tmp != NULL) {
@@ -96,4 +93,4 @@ static bool _get_bool(janus_config *jcfg, const char *section, const char *optio
free(tmp); free(tmp);
} }
return value; return value;
} }*/

View File

@@ -36,7 +36,6 @@
typedef struct { typedef struct {
char *video_sink_name; char *video_sink_name;
bool video_zero_playout_delay;
char *audio_dev_name; char *audio_dev_name;
char *tc358743_dev_path; char *tc358743_dev_path;

View File

@@ -262,7 +262,7 @@ static int _plugin_init(janus_callbacks *gw, const char *config_dir_path) {
_g_gw = gw; _g_gw = gw;
_g_video_queue = us_queue_init(1024); _g_video_queue = us_queue_init(1024);
_g_rtpv = us_rtpv_init(_relay_rtp_clients, _g_config->video_zero_playout_delay); _g_rtpv = us_rtpv_init(_relay_rtp_clients);
if (_g_config->audio_dev_name != NULL) { if (_g_config->audio_dev_name != NULL) {
_g_rtpa = us_rtpa_init(_relay_rtp_clients); _g_rtpa = us_rtpa_init(_relay_rtp_clients);
US_THREAD_CREATE(_g_audio_tid, _audio_thread, NULL); US_THREAD_CREATE(_g_audio_tid, _audio_thread, NULL);

View File

@@ -26,12 +26,11 @@
#include "rtp.h" #include "rtp.h"
us_rtp_s *us_rtp_init(unsigned payload, bool video, bool zero_playout_delay) { us_rtp_s *us_rtp_init(unsigned payload, bool video) {
us_rtp_s *rtp; us_rtp_s *rtp;
US_CALLOC(rtp, 1); US_CALLOC(rtp, 1);
rtp->payload = payload; rtp->payload = payload;
rtp->video = video; rtp->video = video;
rtp->zero_playout_delay = zero_playout_delay; // See client.c
rtp->ssrc = us_triple_u32(us_get_now_monotonic_u64()); rtp->ssrc = us_triple_u32(us_get_now_monotonic_u64());
return rtp; return rtp;
} }

View File

@@ -39,18 +39,18 @@
typedef struct { typedef struct {
unsigned payload; unsigned payload;
bool video; bool video;
bool zero_playout_delay;
uint32_t ssrc; uint32_t ssrc;
uint16_t seq; uint16_t seq;
uint8_t datagram[US_RTP_DATAGRAM_SIZE]; uint8_t datagram[US_RTP_DATAGRAM_SIZE];
size_t used; size_t used;
bool zero_playout_delay;
} us_rtp_s; } us_rtp_s;
typedef void (*us_rtp_callback_f)(const us_rtp_s *rtp); typedef void (*us_rtp_callback_f)(const us_rtp_s *rtp);
us_rtp_s *us_rtp_init(unsigned payload, bool video, bool zero_playout_delay); us_rtp_s *us_rtp_init(unsigned payload, bool video);
us_rtp_s *us_rtp_dup(const us_rtp_s *rtp); us_rtp_s *us_rtp_dup(const us_rtp_s *rtp);
void us_rtp_destroy(us_rtp_s *rtp); void us_rtp_destroy(us_rtp_s *rtp);

View File

@@ -26,7 +26,7 @@
us_rtpa_s *us_rtpa_init(us_rtp_callback_f callback) { us_rtpa_s *us_rtpa_init(us_rtp_callback_f callback) {
us_rtpa_s *rtpa; us_rtpa_s *rtpa;
US_CALLOC(rtpa, 1); US_CALLOC(rtpa, 1);
rtpa->rtp = us_rtp_init(111, false, false); rtpa->rtp = us_rtp_init(111, false);
rtpa->callback = callback; rtpa->callback = callback;
return rtpa; return rtpa;
} }

View File

@@ -31,10 +31,10 @@ void _rtpv_process_nalu(us_rtpv_s *rtpv, const uint8_t *data, size_t size, uint3
static ssize_t _find_annexb(const uint8_t *data, size_t size); static ssize_t _find_annexb(const uint8_t *data, size_t size);
us_rtpv_s *us_rtpv_init(us_rtp_callback_f callback, bool zero_playout_delay) { us_rtpv_s *us_rtpv_init(us_rtp_callback_f callback) {
us_rtpv_s *rtpv; us_rtpv_s *rtpv;
US_CALLOC(rtpv, 1); US_CALLOC(rtpv, 1);
rtpv->rtp = us_rtp_init(96, true, zero_playout_delay); rtpv->rtp = us_rtp_init(96, true);
rtpv->callback = callback; rtpv->callback = callback;
return rtpv; return rtpv;
} }
@@ -59,12 +59,11 @@ char *us_rtpv_make_sdp(us_rtpv_s *rtpv) {
"a=rtcp-fb:%u nack pli" RN "a=rtcp-fb:%u nack pli" RN
"a=rtcp-fb:%u goog-remb" RN "a=rtcp-fb:%u goog-remb" RN
"a=ssrc:%" PRIu32 " cname:ustreamer" RN "a=ssrc:%" PRIu32 " cname:ustreamer" RN
"%s" // playout-delay "a=extmap:1 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay" RN
"a=sendonly" RN, "a=sendonly" RN,
PAYLOAD, PAYLOAD, PAYLOAD, PAYLOAD, PAYLOAD, PAYLOAD, PAYLOAD, PAYLOAD,
PAYLOAD, PAYLOAD, PAYLOAD, PAYLOAD, PAYLOAD, PAYLOAD,
rtpv->rtp->ssrc, rtpv->rtp->ssrc
(rtpv->rtp->zero_playout_delay ? "a=extmap:1 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay" RN : "")
); );
return sdp; return sdp;
# undef PAYLOAD # undef PAYLOAD
@@ -78,6 +77,8 @@ void us_rtpv_wrap(us_rtpv_s *rtpv, const us_frame_s *frame) {
assert(frame->format == V4L2_PIX_FMT_H264); assert(frame->format == V4L2_PIX_FMT_H264);
rtpv->rtp->zero_playout_delay = (frame->gop == 0);
const uint32_t pts = us_get_now_monotonic_u64() * 9 / 100; // PTS units are in 90 kHz const uint32_t pts = us_get_now_monotonic_u64() * 9 / 100; // PTS units are in 90 kHz
ssize_t last_offset = -_PRE; ssize_t last_offset = -_PRE;

View File

@@ -43,7 +43,7 @@ typedef struct {
} us_rtpv_s; } us_rtpv_s;
us_rtpv_s *us_rtpv_init(us_rtp_callback_f callback, bool zero_playout_delay); us_rtpv_s *us_rtpv_init(us_rtp_callback_f callback);
void us_rtpv_destroy(us_rtpv_s *rtpv); void us_rtpv_destroy(us_rtpv_s *rtpv);
char *us_rtpv_make_sdp(us_rtpv_s *rtpv); char *us_rtpv_make_sdp(us_rtpv_s *rtpv);