From a1ae02de5d6e2a420d0a810b6ecef800359f56c8 Mon Sep 17 00:00:00 2001 From: Maxim Devaev Date: Sat, 31 Jan 2026 16:45:26 +0200 Subject: [PATCH] janus: refactored sdp logic --- janus/src/plugin.c | 28 +++--------- janus/src/rtpa.c | 27 +---------- janus/src/rtpa.h | 1 - janus/src/rtpv.c | 28 +----------- janus/src/rtpv.h | 1 - janus/src/sdp.c | 110 +++++++++++++++++++++++++++++++++++++++++++++ janus/src/sdp.h | 31 +++++++++++++ 7 files changed, 150 insertions(+), 76 deletions(-) create mode 100644 janus/src/sdp.c create mode 100644 janus/src/sdp.h diff --git a/janus/src/plugin.c b/janus/src/plugin.c index 0a578bf..46c95b3 100644 --- a/janus/src/plugin.c +++ b/janus/src/plugin.c @@ -22,7 +22,6 @@ #include #include -#include #include #include #include @@ -56,6 +55,7 @@ #include "rtp.h" #include "rtpv.h" #include "rtpa.h" +#include "sdp.h" #include "memsinkfd.h" #include "config.h" @@ -641,31 +641,13 @@ static struct janus_plugin_result *_plugin_handle_message( } { - char *sdp; - char *const video_sdp = us_rtpv_make_sdp(_g_rtpv); - char *const audio_sdp = (with_acap ? us_rtpa_make_sdp(_g_rtpa, with_aplay) : us_strdup("")); - US_ASPRINTF(sdp, - "v=0" RN - "o=- %" PRIu64 " 1 IN IP4 0.0.0.0" RN - "s=PiKVM uStreamer" RN - "t=0 0" RN - "%s%s", - 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 - ); + char *const sdp = us_sdp_create( + _g_rtpv, + (with_acap ? _g_rtpa : NULL), + (with_acap && with_aplay)); json_t *const offer_jsep = json_pack("{ssss}", "type", "offer", "sdp", sdp); PUSH_STATUS("started", NULL, offer_jsep); json_decref(offer_jsep); - free(audio_sdp); - free(video_sdp); free(sdp); } diff --git a/janus/src/rtpa.c b/janus/src/rtpa.c index 1cdd5b9..54eac7c 100644 --- a/janus/src/rtpa.c +++ b/janus/src/rtpa.c @@ -23,11 +23,12 @@ #include "rtpa.h" #include -#include #include "uslibs/types.h" #include "uslibs/tools.h" +#include "rtp.h" + us_rtpa_s *us_rtpa_init(us_rtp_callback_f callback) { us_rtpa_s *rtpa; @@ -43,30 +44,6 @@ void us_rtpa_destroy(us_rtpa_s *rtpa) { free(rtpa); } -char *us_rtpa_make_sdp(us_rtpa_s *rtpa, bool mic) { - const uint pl = rtpa->rtp->payload; - char *sdp; - US_ASPRINTF(sdp, - "m=audio 1 RTP/SAVPF %u" RN - "c=IN IP4 0.0.0.0" RN - "a=rtpmap:%u OPUS/%u/%u" RN - "a=fmtp:%u sprop-stereo=1" RN // useinbandfec=1 - "a=rtcp-fb:%u nack" RN - "a=rtcp-fb:%u nack pli" RN - "a=rtcp-fb:%u goog-remb" RN - "a=mid:a" RN - "a=msid:audio a" RN - "a=ssrc:%" PRIu32 " cname:ustreamer" RN - "a=%s" RN, - pl, pl, - US_RTP_OPUS_HZ, US_RTP_OPUS_CH, - pl, pl, pl, pl, - rtpa->rtp->ssrc, - (mic ? "sendrecv" : "sendonly") - ); - return sdp; -} - void us_rtpa_wrap(us_rtpa_s *rtpa, const u8 *data, uz size, u32 pts) { if (size + US_RTP_HEADER_SIZE <= US_RTP_DATAGRAM_SIZE) { us_rtp_write_header(rtpa->rtp, pts, false); diff --git a/janus/src/rtpa.h b/janus/src/rtpa.h index be2559b..a340a36 100644 --- a/janus/src/rtpa.h +++ b/janus/src/rtpa.h @@ -36,5 +36,4 @@ typedef struct { us_rtpa_s *us_rtpa_init(us_rtp_callback_f callback); void us_rtpa_destroy(us_rtpa_s *rtpa); -char *us_rtpa_make_sdp(us_rtpa_s *rtpa, bool mic); void us_rtpa_wrap(us_rtpa_s *rtpa, const u8 *data, uz size, u32 pts); diff --git a/janus/src/rtpv.c b/janus/src/rtpv.c index 7db99e9..9c59b35 100644 --- a/janus/src/rtpv.c +++ b/janus/src/rtpv.c @@ -35,6 +35,8 @@ #include "uslibs/tools.h" #include "uslibs/frame.h" +#include "rtp.h" + void _rtpv_process_nalu(us_rtpv_s *rtpv, const u8 *data, uz size, u32 pts, bool marked); @@ -55,32 +57,6 @@ void us_rtpv_destroy(us_rtpv_s *rtpv) { free(rtpv); } -char *us_rtpv_make_sdp(us_rtpv_s *rtpv) { - // https://tools.ietf.org/html/rfc6184 - // https://github.com/meetecho/janus-gateway/issues/2443 - const uint pl = rtpv->rtp->payload; - char *sdp; - US_ASPRINTF(sdp, - "m=video 1 RTP/SAVPF %u" RN - "c=IN IP4 0.0.0.0" RN - "a=rtpmap:%u H264/90000" RN - "a=fmtp:%u profile-level-id=42E01F;packetization-mode=1" RN - "a=rtcp-fb:%u nack" RN - "a=rtcp-fb:%u nack pli" RN - "a=rtcp-fb:%u goog-remb" RN - "a=mid:v" RN - "a=msid:video v" RN - "a=ssrc:%" PRIu32 " cname:ustreamer" RN - "a=extmap:1/sendonly urn:3gpp:video-orientation" RN - "a=extmap:2/sendonly http://www.webrtc.org/experiments/rtp-hdrext/playout-delay" RN - "a=extmap:3/sendonly http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time" RN - "a=sendonly" RN, - pl, pl, pl, pl, pl, pl, - rtpv->rtp->ssrc - ); - return sdp; -} - #define _PRE 3 // Annex B prefix length void us_rtpv_wrap(us_rtpv_s *rtpv, const us_frame_s *frame, bool zero_playout_delay) { diff --git a/janus/src/rtpv.h b/janus/src/rtpv.h index 21cf04e..f0a3932 100644 --- a/janus/src/rtpv.h +++ b/janus/src/rtpv.h @@ -37,5 +37,4 @@ typedef struct { us_rtpv_s *us_rtpv_init(us_rtp_callback_f callback); void us_rtpv_destroy(us_rtpv_s *rtpv); -char *us_rtpv_make_sdp(us_rtpv_s *rtpv); void us_rtpv_wrap(us_rtpv_s *rtpv, const us_frame_s *frame, bool zero_playout_delay); diff --git a/janus/src/sdp.c b/janus/src/sdp.c new file mode 100644 index 0000000..86fe29d --- /dev/null +++ b/janus/src/sdp.c @@ -0,0 +1,110 @@ +/***************************************************************************** +# # +# uStreamer - Lightweight and fast MJPEG-HTTP streamer. # +# # +# Copyright (C) 2018-2024 Maxim Devaev # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +*****************************************************************************/ + + +#include "sdp.h" + +#include + +#include + +#include "uslibs/types.h" +#include "uslibs/tools.h" + +#include "rtp.h" +#include "rtpv.h" +#include "rtpa.h" + + +char *us_sdp_create(us_rtpv_s *rtpv, us_rtpa_s *rtpa, bool mic) { + char *video_sdp; + { + // https://tools.ietf.org/html/rfc6184 + // https://github.com/meetecho/janus-gateway/issues/2443 + const uint pl = rtpv->rtp->payload; + US_ASPRINTF( + video_sdp, + "m=video 1 RTP/SAVPF %u" RN + "c=IN IP4 0.0.0.0" RN + "a=rtpmap:%u H264/90000" RN + "a=fmtp:%u profile-level-id=42E01F;packetization-mode=1" RN + "a=rtcp-fb:%u nack" RN + "a=rtcp-fb:%u nack pli" RN + "a=rtcp-fb:%u goog-remb" RN + "a=mid:v" RN + "a=msid:video v" RN + "a=ssrc:%" PRIu32 " cname:ustreamer" RN + "a=extmap:1/sendonly urn:3gpp:video-orientation" RN + "a=extmap:2/sendonly http://www.webrtc.org/experiments/rtp-hdrext/playout-delay" RN + "a=extmap:3/sendonly http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time" RN + "a=sendonly" RN, + pl, pl, pl, pl, pl, pl, + rtpv->rtp->ssrc); + } + + char *audio_sdp; + if (rtpa == NULL) { + audio_sdp = us_strdup(""); + } else { + const uint pl = rtpa->rtp->payload; + US_ASPRINTF( + audio_sdp, + "m=audio 1 RTP/SAVPF %u" RN + "c=IN IP4 0.0.0.0" RN + "a=rtpmap:%u OPUS/%u/%u" RN + "a=fmtp:%u sprop-stereo=1" RN // useinbandfec=1 + "a=rtcp-fb:%u nack" RN + "a=rtcp-fb:%u nack pli" RN + "a=rtcp-fb:%u goog-remb" RN + "a=mid:a" RN + "a=msid:audio a" RN + "a=ssrc:%" PRIu32 " cname:ustreamer" RN + "a=%s" RN, + pl, pl, + US_RTP_OPUS_HZ, US_RTP_OPUS_CH, + pl, pl, pl, pl, + rtpa->rtp->ssrc, + (mic ? "sendrecv" : "sendonly")); + } + + char *sdp; + US_ASPRINTF(sdp, + "v=0" RN + "o=- %" PRIu64 " 1 IN IP4 0.0.0.0" RN + "s=PiKVM uStreamer" RN + "t=0 0" RN + "%s%s", + 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); + return sdp; +} diff --git a/janus/src/sdp.h b/janus/src/sdp.h new file mode 100644 index 0000000..1f0e626 --- /dev/null +++ b/janus/src/sdp.h @@ -0,0 +1,31 @@ +/***************************************************************************** +# # +# uStreamer - Lightweight and fast MJPEG-HTTP streamer. # +# # +# Copyright (C) 2018-2024 Maxim Devaev # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +*****************************************************************************/ + + +#pragma once + +#include "uslibs/types.h" + +#include "rtpv.h" +#include "rtpa.h" + + +char *us_sdp_create(us_rtpv_s *rtpv, us_rtpa_s *rtpa, bool mic);