From c4d68cf4cd1a03d7e98d56c4d5d189ebec9390ec Mon Sep 17 00:00:00 2001 From: "nicolas.tizon@renater.fr" Date: Sun, 3 Jul 2022 00:13:38 +0200 Subject: [PATCH 01/38] [Added] x11grab source --- mk/modules.mk | 2 +- modules/x11grab/module.mk | 12 +++ modules/x11grab/x11grab.c | 220 ++++++++++++++++++++++++++++++++++++++ src/config.c | 1 + 4 files changed, 234 insertions(+), 1 deletion(-) create mode 100644 modules/x11grab/module.mk create mode 100644 modules/x11grab/x11grab.c diff --git a/mk/modules.mk b/mk/modules.mk index b76e572b62..9d39137d5e 100644 --- a/mk/modules.mk +++ b/mk/modules.mk @@ -360,7 +360,7 @@ ifneq ($(USE_WINWAVE),) MODULES += winwave endif ifneq ($(USE_X11),) -MODULES += x11 +MODULES += x11 x11grab endif ifneq ($(USE_ZRTP),) MODULES += zrtp diff --git a/modules/x11grab/module.mk b/modules/x11grab/module.mk new file mode 100644 index 0000000000..b8f3ed808b --- /dev/null +++ b/modules/x11grab/module.mk @@ -0,0 +1,12 @@ +# +# module.mk +# +# Copyright (C) 2010 Alfred E. Heggestad +# + +MOD := x11grab +$(MOD)_SRCS += x11grab.c +$(MOD)_LFLAGS += -lX11 -lXext +$(MOD)_CFLAGS += -Wno-variadic-macros + +include mk/mod.mk diff --git a/modules/x11grab/x11grab.c b/modules/x11grab/x11grab.c new file mode 100644 index 0000000000..2f479b42b0 --- /dev/null +++ b/modules/x11grab/x11grab.c @@ -0,0 +1,220 @@ +/** + * @file x11grab.c X11 grabbing video-source + * + * Copyright (C) 2010 Alfred E. Heggestad + */ +#define _DEFAULT_SOURCE 1 +#define _BSD_SOURCE 1 +#include +#ifndef SOLARIS +#define _XOPEN_SOURCE 1 +#endif +#include +#include +#include +#include +#include +#include + + +/** + * @defgroup x11grab x11grab + * + * X11 window-grabbing video-source module + * + */ + + +struct vidsrc_st { + Display *disp; + XImage *image; + pthread_t thread; + bool run; + int fps; + struct vidsz size; + enum vidfmt pixfmt; + vidsrc_frame_h *frameh; + void *arg; +}; + + +static struct vidsrc *vidsrc; + + +static int x11grab_open(struct vidsrc_st *st, const struct vidsz *sz, + const char *dev) +{ + int x = 0, y = 0; + + st->disp = XOpenDisplay(dev); + if (!st->disp) { + warning("x11grab: error opening display '%s'\n", dev); + return ENODEV; + } + + st->image = XGetImage(st->disp, + RootWindow(st->disp, DefaultScreen(st->disp)), + x, y, sz->w, sz->h, AllPlanes, ZPixmap); + if (!st->image) { + warning("x11grab: error creating Ximage\n"); + return ENODEV; + } + + switch (st->image->bits_per_pixel) { + + case 32: + st->pixfmt = VID_FMT_RGB32; + break; + + default: + warning("x11grab: not supported: bpp=%d\n", + st->image->bits_per_pixel); + return ENOSYS; + } + + return 0; +} + + +static inline uint8_t *x11grab_read(struct vidsrc_st *st) +{ + const int x = 0, y = 0; + XImage *im; + + im = XGetSubImage(st->disp, + RootWindow(st->disp, DefaultScreen(st->disp)), + x, y, st->size.w, st->size.h, AllPlanes, ZPixmap, + st->image, 0, 0); + if (!im) + return NULL; + + return (uint8_t *)st->image->data; +} + + +static void call_frame_handler(struct vidsrc_st *st, uint8_t *buf, + uint64_t timestamp) +{ + struct vidframe frame; + + vidframe_init_buf(&frame, st->pixfmt, &st->size, buf); + + st->frameh(&frame, timestamp, st->arg); +} + + +static void *read_thread(void *arg) +{ + struct vidsrc_st *st = arg; + uint64_t ts = tmr_jiffies(); + uint8_t *buf; + + while (st->run) { + + uint64_t timestamp; + + if (tmr_jiffies() < ts) { + sys_msleep(4); + continue; + } + + buf = x11grab_read(st); + if (!buf) + continue; + + timestamp = ts * VIDEO_TIMEBASE / 1000; + + ts += (1000/st->fps); + + call_frame_handler(st, buf, timestamp); + } + + return NULL; +} + + +static void destructor(void *arg) +{ + struct vidsrc_st *st = arg; + + if (st->run) { + st->run = false; + pthread_join(st->thread, NULL); + } + + if (st->image) + XDestroyImage(st->image); + + if (st->disp) + XCloseDisplay(st->disp); +} + + +static int alloc(struct vidsrc_st **stp, const struct vidsrc *vs, + struct vidsrc_prm *prm, + const struct vidsz *size, const char *fmt, + const char *dev, vidsrc_frame_h *frameh, + vidsrc_packet_h *packeth, + vidsrc_error_h *errorh, void *arg) +{ + struct vidsrc_st *st; + int err; + + (void)fmt; + (void)packeth; + (void)errorh; + (void)vs; + + if (!stp || !prm || !size || !frameh) + return EINVAL; + + st = mem_zalloc(sizeof(*st), destructor); + if (!st) + return ENOMEM; + + st->size = *size; + st->fps = prm->fps; + st->frameh = frameh; + st->arg = arg; + + err = x11grab_open(st, size, dev); + if (err) + goto out; + + st->run = true; + err = pthread_create(&st->thread, NULL, read_thread, st); + if (err) { + st->run = false; + goto out; + } + + out: + if (err) + mem_deref(st); + else + *stp = st; + + return err; +} + + +static int x11grab_init(void) +{ + return vidsrc_register(&vidsrc, baresip_vidsrcl(), + "x11grab", alloc, NULL); +} + + +static int x11grab_close(void) +{ + vidsrc = mem_deref(vidsrc); + return 0; +} + + +EXPORT_SYM const struct mod_export DECL_EXPORTS(x11grab) = { + "x11grab", + "vidsrc", + x11grab_init, + x11grab_close +}; diff --git a/src/config.c b/src/config.c index 493dbdaddf..57eccb894e 100644 --- a/src/config.c +++ b/src/config.c @@ -1008,6 +1008,7 @@ int config_write_template(const char *file, const struct config *cfg) #else (void)re_fprintf(f, "#module\t\t\t" "v4l2" MOD_EXT "\n"); #endif + (void)re_fprintf(f, "#module\t\t\t" "x11grab" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "vidbridge" MOD_EXT "\n"); (void)re_fprintf(f, "\n# Video display modules\n"); From 54712967b7ed9e86f60cbd7381ae3c7e49cf409f Mon Sep 17 00:00:00 2001 From: nicotyze Date: Mon, 5 Dec 2022 16:29:57 +0100 Subject: [PATCH 02/38] [Changed] RTCP FIR from rfc5104 --- src/video.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/video.c b/src/video.c index 8756aa4b9f..54d2284444 100644 --- a/src/video.c +++ b/src/video.c @@ -617,9 +617,9 @@ static void send_fir(struct stream *s, bool pli) err = rtcp_send_pli(stream_rtp_sock(s), ssrc); } else - err = rtcp_send_fir(stream_rtp_sock(s), - rtp_sess_ssrc(stream_rtp_sock(s))); - + err = rtcp_send_fir_rfc5104(stream_rtp_sock(s), rtp_sess_ssrc(stream_rtp_sock(s)), 0); + //err = rtcp_send_fir(stream_rtp_sock(s), + // rtp_sess_ssrc(stream_rtp_sock(s))); if (err) { warning("video: failed to send RTCP %s: %m\n", pli ? "PLI" : "FIR", err); From 80f94358693183947f1c9d82dfc686b352114660 Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Wed, 7 Dec 2022 16:44:11 +0100 Subject: [PATCH 03/38] [Added] support of EVEN-PORT + RESERVATION-TOKEN based negociation for STUN --- modules/ice/ice.c | 2 +- modules/turn/turn.c | 24 ++++++++++++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/modules/ice/ice.c b/modules/ice/ice.c index f5cc406757..3593b35af7 100644 --- a/modules/ice/ice.c +++ b/modules/ice/ice.c @@ -231,7 +231,7 @@ static int cand_gather_relayed(struct mnat_media *m, struct comp *comp, err = turnc_alloc(&turnc, stun_conf(icem_stun(m->icem)), IPPROTO_UDP, comp->sock, layer, &m->sess->srv, username, password, - 60, turnc_handler, comp); + 60, NULL, turnc_handler, comp); if (err) return err; diff --git a/modules/turn/turn.c b/modules/turn/turn.c index 119c2fb694..27dd78b6f7 100644 --- a/modules/turn/turn.c +++ b/modules/turn/turn.c @@ -49,6 +49,7 @@ struct mnat_media { struct tls_conn *tlsc; struct mbuf *mb; unsigned ix; + uint64_t token; } compv[COMPC]; }; @@ -196,16 +197,27 @@ static void turn_handler(int err, uint16_t scode, const char *reason, void *arg) { struct comp *comp = arg; + uint64_t token; struct mnat_media *m = comp->m; (void)mapped_addr; (void)msg; if (!err && !scode) { - const struct comp *other = &m->compv[comp->ix ^ 1]; + struct comp *other = &m->compv[comp->ix ^ 1]; - if (comp->ix == 0) - sdp_media_set_laddr(m->sdpm, relay_addr); + struct stun_attr *token_attr = stun_msg_attr(msg, STUN_ATTR_RSV_TOKEN); + if (token_attr) + token = token_attr->v.uint64; + + if (comp->ix == 0) { + sdp_media_set_laddr(m->sdpm, relay_addr); + err = turnc_alloc(&other->turnc, NULL, + IPPROTO_UDP, other->sock, LAYER, + &m->sess->srv, m->sess->user, m->sess->pass, + TURN_DEFAULT_LIFETIME, &token, + turn_handler, other); + } else sdp_media_set_laddr_rtcp(m->sdpm, relay_addr); @@ -238,7 +250,7 @@ static void tcp_estab_handler(void *arg) err = turnc_alloc(&comp->turnc, NULL, IPPROTO_TCP, comp->tc, 0, &m->sess->srv, m->sess->user, m->sess->pass, - TURN_DEFAULT_LIFETIME, turn_handler, comp); + TURN_DEFAULT_LIFETIME, NULL, turn_handler, comp); if (err) { m->sess->estabh(err, 0, NULL, m->sess->arg); } @@ -259,7 +271,7 @@ static int media_start(struct mnat_sess *sess, struct mnat_media *m) unsigned i; int err = 0; - for (i=0; icompv[i]; @@ -272,7 +284,7 @@ static int media_start(struct mnat_sess *sess, struct mnat_media *m) err |= turnc_alloc(&comp->turnc, NULL, IPPROTO_UDP, comp->sock, LAYER, &sess->srv, sess->user, sess->pass, - TURN_DEFAULT_LIFETIME, + TURN_DEFAULT_LIFETIME, NULL, turn_handler, comp); break; From 0f73868f8e1076b740834014292bc15839bdc6c3 Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Fri, 9 Dec 2022 16:08:43 +0100 Subject: [PATCH 04/38] [Added] multi-threading support in avcodec/decode --- modules/avcodec/decode.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/modules/avcodec/decode.c b/modules/avcodec/decode.c index bccc8c4096..b956639056 100644 --- a/modules/avcodec/decode.c +++ b/modules/avcodec/decode.c @@ -104,6 +104,8 @@ static enum AVPixelFormat get_hw_format(AVCodecContext *ctx, static int init_decoder(struct viddec_state *st, const char *name) { enum AVCodecID codec_id; + char thread_type[64] = "2"; + char thread_count[64] = "1"; codec_id = avcodec_resolve_codecid(name); if (codec_id == AV_CODEC_ID_NONE) @@ -152,6 +154,11 @@ static int init_decoder(struct viddec_state *st, const char *name) } #endif + conf_get_str(conf_cur(), "thread_type", thread_type, sizeof(thread_type)); + conf_get_str(conf_cur(), "thread_count", thread_count, sizeof(thread_count)); + st->ctx->thread_type = atoi(thread_type); + st->ctx->thread_count = atoi(thread_count); + if (avcodec_open2(st->ctx, st->codec, NULL) < 0) return ENOENT; From 4ebd23a4102f63e40b81d6fef4f4ef43debc6585 Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Mon, 12 Dec 2022 22:40:20 +0100 Subject: [PATCH 05/38] [Changed] multi-threading support in avcodec/decode --- modules/avcodec/decode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/avcodec/decode.c b/modules/avcodec/decode.c index a6e6a0e901..0fd8fb4893 100644 --- a/modules/avcodec/decode.c +++ b/modules/avcodec/decode.c @@ -103,8 +103,8 @@ static enum AVPixelFormat get_hw_format(AVCodecContext *ctx, static int init_decoder(struct viddec_state *st, const char *name) { enum AVCodecID codec_id; - char thread_type[64] = "2"; - char thread_count[64] = "1"; + char thread_type[1] = "2"; + char thread_count[8] = "1"; codec_id = avcodec_resolve_codecid(name); if (codec_id == AV_CODEC_ID_NONE) From 53825cf3217d8af614caabb0c06676745f243689 Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Tue, 13 Dec 2022 16:11:36 +0100 Subject: [PATCH 06/38] [Added] x11grab cmake --- cmake/modules.cmake | 1 + modules/x11grab/CMakeLists.txt | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 modules/x11grab/CMakeLists.txt diff --git a/cmake/modules.cmake b/cmake/modules.cmake index 02d96dbd41..649c8811e5 100644 --- a/cmake/modules.cmake +++ b/cmake/modules.cmake @@ -173,6 +173,7 @@ if(WEBRTC_AECM_FOUND) endif() if(X11_XShm_FOUND) list(APPEND MODULES x11) + list(APPEND MODULES x11grab) endif() if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") list(APPEND MODULES evdev) diff --git a/modules/x11grab/CMakeLists.txt b/modules/x11grab/CMakeLists.txt new file mode 100644 index 0000000000..37d4fd0734 --- /dev/null +++ b/modules/x11grab/CMakeLists.txt @@ -0,0 +1,12 @@ +project(x11grab) + +set(SRCS x11grab.c) + +if(STATIC) + add_library(${PROJECT_NAME} OBJECT ${SRCS}) +else() + add_library(${PROJECT_NAME} MODULE ${SRCS}) +endif() + +target_include_directories(${PROJECT_NAME} PRIVATE ${X11_INCLUDE_DIRS}) +target_link_libraries(${PROJECT_NAME} PRIVATE ${X11_LIBRARIES}) From 39b95529ac06914a26710b1d66c62e7fb5f9edab Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Sun, 18 Dec 2022 22:43:32 +0100 Subject: [PATCH 07/38] [Added] public address configuration parameter --- src/call.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/call.c b/src/call.c index a66bd215aa..c5f39861a8 100644 --- a/src/call.c +++ b/src/call.c @@ -1339,6 +1339,8 @@ static bool call_need_modify(const struct call *call) int call_answer(struct call *call, uint16_t scode, enum vidmode vmode) { struct mbuf *desc; + char public_address[16] = ""; + struct sa pub_addr; int err; if (!call || !call->sess) @@ -1368,7 +1370,14 @@ int call_answer(struct call *call, uint16_t scode, enum vidmode vmode) ua_event(call->ua, UA_EVENT_CALL_LOCAL_SDP, call, "%s", !call->got_offer ? "offer" : "answer"); - err = sdp_encode(&desc, call->sdp, !call->got_offer); + sa_ntop(sdp_session_laddr(call->sdp), public_address, + sizeof(public_address) ); + + conf_get_str(conf_cur(), "public_address", public_address, sizeof(public_address)); + err = sa_set_str(&pub_addr, public_address, 0); + + sdp_session_set_laddr(call->sdp, &pub_addr); + err |= sdp_encode(&desc, call->sdp, !call->got_offer); if (err) return err; From 6813343ce639b326daf8eb3c7c4af7f05732626f Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Fri, 30 Dec 2022 17:02:55 +0100 Subject: [PATCH 08/38] [Added] RTP stats in Audio/Video debug --- include/baresip.h | 1 + src/audio.c | 1 + src/stream.c | 2 +- src/video.c | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/baresip.h b/include/baresip.h index 1cc84401f4..213ac62277 100644 --- a/include/baresip.h +++ b/include/baresip.h @@ -1429,6 +1429,7 @@ const char *stream_peer(const struct stream *strm); int stream_bundle_init(struct stream *strm, bool offerer); int stream_debug(struct re_printf *pf, const struct stream *s); void stream_enable_rtp_timeout(struct stream *strm, uint32_t timeout_ms); +void print_rtp_stats(const struct stream *s); /* diff --git a/src/audio.c b/src/audio.c index 70d20eeb0c..6fb315e446 100644 --- a/src/audio.c +++ b/src/audio.c @@ -2175,6 +2175,7 @@ int audio_debug(struct re_printf *pf, const struct audio *a) aurx_print_pipeline, rx); err |= stream_debug(pf, a->strm); + print_rtp_stats(a->strm); return err; } diff --git a/src/stream.c b/src/stream.c index 104259a362..570be7e0aa 100644 --- a/src/stream.c +++ b/src/stream.c @@ -94,7 +94,7 @@ struct stream { }; -static void print_rtp_stats(const struct stream *s) +void print_rtp_stats(const struct stream *s) { uint32_t tx_n_packets = metric_n_packets(s->tx.metric); uint32_t rx_n_packets = metric_n_packets(s->rx.metric); diff --git a/src/video.c b/src/video.c index ae1e803570..d35673a83b 100644 --- a/src/video.c +++ b/src/video.c @@ -1658,6 +1658,7 @@ int video_debug(struct re_printf *pf, const struct video *v) err |= vrx_print_pipeline(pf, vrx); err |= stream_debug(pf, v->strm); + print_rtp_stats(v->strm); return err; } From 23b5dd9069ce501a5b155f77bcdcaa9df2e44b75 Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Wed, 4 Jan 2023 21:33:27 +0100 Subject: [PATCH 09/38] [Removed] multi-threading support in avcodec/decode --- modules/avcodec/decode.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/modules/avcodec/decode.c b/modules/avcodec/decode.c index 0fd8fb4893..fe58d16173 100644 --- a/modules/avcodec/decode.c +++ b/modules/avcodec/decode.c @@ -103,8 +103,6 @@ static enum AVPixelFormat get_hw_format(AVCodecContext *ctx, static int init_decoder(struct viddec_state *st, const char *name) { enum AVCodecID codec_id; - char thread_type[1] = "2"; - char thread_count[8] = "1"; codec_id = avcodec_resolve_codecid(name); if (codec_id == AV_CODEC_ID_NONE) @@ -151,11 +149,6 @@ static int init_decoder(struct viddec_state *st, const char *name) info("avcodec: decode: hardware accel disabled\n"); } - conf_get_str(conf_cur(), "thread_type", thread_type, sizeof(thread_type)); - conf_get_str(conf_cur(), "thread_count", thread_count, sizeof(thread_count)); - st->ctx->thread_type = atoi(thread_type); - st->ctx->thread_count = atoi(thread_count); - if (avcodec_open2(st->ctx, st->codec, NULL) < 0) return ENOENT; From 6a6c07fc7dd6534c09ba49aa9d9edc509ce127dd Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Thu, 5 Jan 2023 15:19:39 +0100 Subject: [PATCH 10/38] [Added] SIP media control --- include/baresip.h | 2 + src/call.c | 122 +++++++++++++++++++++++++++++++++++++++------- src/config.c | 3 ++ src/video.c | 49 ++++++++++++++----- 4 files changed, 146 insertions(+), 30 deletions(-) diff --git a/include/baresip.h b/include/baresip.h index 213ac62277..026c359da0 100644 --- a/include/baresip.h +++ b/include/baresip.h @@ -205,6 +205,7 @@ int call_modify(struct call *call); int call_hold(struct call *call, bool hold); int call_set_video_dir(struct call *call, enum sdp_dir dir); int call_send_digit(struct call *call, char key); +int call_send_pfu(struct call *call); bool call_has_audio(const struct call *call); bool call_has_video(const struct call *call); bool call_early_video_available(const struct call *call); @@ -323,6 +324,7 @@ struct config_sip { enum sip_transp transp; /**< Default outgoing SIP transport protocol */ bool verify_server; /**< Enable SIP TLS verify server */ uint8_t tos; /**< Type-of-Service for SIP */ + bool media_control; /**< Media Control over SIP */ }; /** Call config */ diff --git a/src/call.c b/src/call.c index c5f39861a8..c0b18b2ca8 100644 --- a/src/call.c +++ b/src/call.c @@ -84,8 +84,17 @@ struct call { bool evstop; /**< UA events stopped flag */ }; +/** SIP info requests */ +enum sip_info_req { + DTMF = 0, + PICTURE_FAST_UPDATE, +}; + static int send_invite(struct call *call); +static int send_info(struct sipsess *sess, + const char* content_type, const char* content, + void *arg, const char *fmt, ...); static int send_dtmf_info(struct call *call, char key); @@ -1736,6 +1745,35 @@ int call_send_digit(struct call *call, char key) } +/** + * Send a picture_fast_update request to the peer + * + * @param call Call object + * + * @return 0 if success, otherwise errorcode + */ +int call_send_pfu(struct call *call) +{ + int err = 0; + + if (!call) + return EINVAL; + + err = send_info(call->sess, + "application/media_control+xml", + "" + "" + "" + "" + "", + NULL, NULL); + if (err) { + warning("call: picture_fast_update request failed (%m)\n", err); + } + return err; +} + + /** * Get the User-Agent for the call * @@ -1905,6 +1943,23 @@ static void sipsess_estab_handler(const struct sip_msg *msg, void *arg) call_event_handler(call, CALL_EVENT_ESTABLISHED, call->peer_uri); } +static void call_handle_info_req(struct call *call, const struct sip_msg *req) +{ + struct pl body; + int err; + + pl_set_mbuf(&body, req->mb); + + /* Poor-mans XML parsing */ + if (0 == re_regex(body.p, body.l, "picture_fast_update")) { + debug("call: receive media control: fast_update=%d\n"); + err = video_update(call->video, call->peer_uri); + if (err) { + warning("call: could not update video: %m\n", err); + } + } +} + static void dtmfend_handler(void *arg) { @@ -1916,15 +1971,21 @@ static void dtmfend_handler(void *arg) static void sipsess_send_info_handler(int err, const struct sip_msg *msg, - void *arg) + void *arg) { (void)arg; - if (err) - warning("call: sending DTMF INFO failed (%m)", err); - else if (msg && msg->scode != 200) - warning("call: sending DTMF INFO failed (scode: %d)", - msg->scode); + //switch (req) { + // case DTMF: + if (err) + warning("call: sending DTMF INFO failed (%m)", err); + else if (msg && msg->scode != 200) + warning("call: sending DTMF INFO failed (scode: %d)", + msg->scode); + // break; + // case PICTURE_FAST_UPDATE: + // break; + //} } @@ -1964,6 +2025,11 @@ static void sipsess_info_handler(struct sip *sip, const struct sip_msg *msg, } } } + else if (msg_ctype_cmp(&msg->ctyp, + "application", "media_control+xml")) { + call_handle_info_req(call, msg); + (void)sip_reply(sip, msg, 200, "OK"); + } else { (void)sip_reply(sip, msg, 488, "Not Acceptable Here"); } @@ -2445,25 +2511,24 @@ static int send_invite(struct call *call) } -static int send_dtmf_info(struct call *call, char key) +static int send_info(struct sipsess *sess, + const char* content_type, const char* content, + void *arg, const char *fmt, ...) { struct mbuf *body; + va_list ap; + body = mbuf_alloc(1024); int err; - if ((key < '0' || key > '9') && - (key < 'a' || key > 'd') && - (key != '*') && - (key != '#')) - return EINVAL; - - body = mbuf_alloc(25); - mbuf_printf(body, "Signal=%c\r\nDuration=250\r\n", key); + va_start(ap, fmt); + (void) mbuf_printf(body, content, fmt, ap); + va_end(ap); mbuf_set_pos(body, 0); - err = sipsess_info(call->sess, "application/dtmf-relay", body, - sipsess_send_info_handler, call); + err = sipsess_info(sess, content_type, body, + sipsess_send_info_handler, arg); + if (err) { - warning("call: sipsess_info for DTMF failed (%m)\n", err); goto out; } @@ -2474,6 +2539,27 @@ static int send_dtmf_info(struct call *call, char key) } +static int send_dtmf_info(struct call *call, char key) +{ + int err; + + if ((key < '0' || key > '9') && + (key < 'a' || key > 'd') && + (key != '*') && + (key != '#')) + return EINVAL; + + err = send_info(call->sess, + "application/dtmf-relay", + "Signal=%c\r\nDuration=250\r\n", + call, &key); + if (err) { + warning("call: sipsess_info for DTMF failed (%m)\n", err); + } + return err; +} + + /** * Find the peer capabilites of early video in the remote SDP * diff --git a/src/config.c b/src/config.c index 943b894e19..22b91e637c 100644 --- a/src/config.c +++ b/src/config.c @@ -345,6 +345,9 @@ int config_parse_conf(struct config *cfg, const struct conf *conf) if (0 == conf_get_u32(conf, "sip_tos", &v)) cfg->sip.tos = v; + (void)conf_get_bool(conf, "sip_media_control", + &cfg->sip.media_control); + /* Call */ (void)conf_get_u32(conf, "call_local_timeout", &cfg->call.local_timeout); diff --git a/src/video.c b/src/video.c index d35673a83b..0960232a58 100644 --- a/src/video.c +++ b/src/video.c @@ -607,22 +607,47 @@ static void picup_tmr_handler(void *arg) static void send_fir(struct stream *s, bool pli) { + struct call *cur_call; + struct ua *local_ua ; + char *local_uri; + bool sip_media_control=false; int err; + struct config *cur_conf; - if (pli) { - uint32_t ssrc; + cur_conf = conf_config(); + if (cur_conf) + sip_media_control = cur_conf->sip.media_control; - err = stream_ssrc_rx(s, &ssrc); - if (!err) - err = rtcp_send_pli(stream_rtp_sock(s), ssrc); + if(sip_media_control) { + local_uri = stream_cname(s); + if (local_uri) + local_ua = uag_find_requri(local_uri); + + if (local_ua) + cur_call = ua_call(local_ua); + + if (cur_call) + err = call_send_pfu(cur_call); + + if (err) + warning("video: failed to send picture_fast_update %m\n", err); } - else - err = rtcp_send_fir_rfc5104(stream_rtp_sock(s), rtp_sess_ssrc(stream_rtp_sock(s)), 0); - //err = rtcp_send_fir(stream_rtp_sock(s), - // rtp_sess_ssrc(stream_rtp_sock(s))); - if (err) { - warning("video: failed to send RTCP %s: %m\n", - pli ? "PLI" : "FIR", err); + else { + if (pli) { + uint32_t ssrc; + + err = stream_ssrc_rx(s, &ssrc); + if (!err) + err = rtcp_send_pli(stream_rtp_sock(s), ssrc); + } + else + err = rtcp_send_fir_rfc5104(stream_rtp_sock(s), rtp_sess_ssrc(stream_rtp_sock(s)), 0); + //err = rtcp_send_fir(stream_rtp_sock(s), + // rtp_sess_ssrc(stream_rtp_sock(s))); + if (err) { + warning("video: failed to send RTCP %s: %m\n", + pli ? "PLI" : "FIR", err); + } } } From ba0765c906ef7479d99b1e3b10ea2fe0a169d510 Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Fri, 6 Jan 2023 23:02:59 +0100 Subject: [PATCH 11/38] [Fixed] SIP media control --- include/baresip.h | 1 + src/call.c | 6 +---- src/video.c | 66 +++++++++++++++++++++++++++++------------------ 3 files changed, 43 insertions(+), 30 deletions(-) diff --git a/include/baresip.h b/include/baresip.h index 026c359da0..e5837b2403 100644 --- a/include/baresip.h +++ b/include/baresip.h @@ -1370,6 +1370,7 @@ void video_set_devicename(struct video *v, const char *src, const char *disp); int video_debug(struct re_printf *pf, const struct video *v); struct stream *video_strm(const struct video *v); const struct vidcodec *video_codec(const struct video *vid, bool tx); +void video_encode_refresh(struct video *v); void video_sdp_attr_decode(struct video *v); double video_calc_seconds(uint64_t rtp_ts); diff --git a/src/call.c b/src/call.c index c0b18b2ca8..d932e1c6b0 100644 --- a/src/call.c +++ b/src/call.c @@ -1946,17 +1946,13 @@ static void sipsess_estab_handler(const struct sip_msg *msg, void *arg) static void call_handle_info_req(struct call *call, const struct sip_msg *req) { struct pl body; - int err; pl_set_mbuf(&body, req->mb); /* Poor-mans XML parsing */ if (0 == re_regex(body.p, body.l, "picture_fast_update")) { debug("call: receive media control: fast_update=%d\n"); - err = video_update(call->video, call->peer_uri); - if (err) { - warning("call: could not update video: %m\n", err); - } + video_encode_refresh(call->video); } } diff --git a/src/video.c b/src/video.c index 0960232a58..eb173d8b88 100644 --- a/src/video.c +++ b/src/video.c @@ -611,42 +611,43 @@ static void send_fir(struct stream *s, bool pli) struct ua *local_ua ; char *local_uri; bool sip_media_control=false; - int err; struct config *cur_conf; + int err; - cur_conf = conf_config(); - if (cur_conf) - sip_media_control = cur_conf->sip.media_control; + if (pli) { + uint32_t ssrc; - if(sip_media_control) { - local_uri = stream_cname(s); - if (local_uri) - local_ua = uag_find_requri(local_uri); + err = stream_ssrc_rx(s, &ssrc); + if (!err) + err = rtcp_send_pli(stream_rtp_sock(s), ssrc); + if (err) + warning("video: failed to send PLI %m\n", err); + } + else{ + cur_conf = conf_config(); + if (cur_conf) + sip_media_control = cur_conf->sip.media_control; - if (local_ua) - cur_call = ua_call(local_ua); + if(sip_media_control) { + local_uri = stream_cname(s); + if (local_uri) + local_ua = uag_find_requri(local_uri); - if (cur_call) - err = call_send_pfu(cur_call); + if (local_ua) + cur_call = ua_call(local_ua); - if (err) - warning("video: failed to send picture_fast_update %m\n", err); - } - else { - if (pli) { - uint32_t ssrc; + if (cur_call) + err = call_send_pfu(cur_call); - err = stream_ssrc_rx(s, &ssrc); - if (!err) - err = rtcp_send_pli(stream_rtp_sock(s), ssrc); + if (err) + warning("video: failed to send picture_fast_update %m\n", err); } - else + else { err = rtcp_send_fir_rfc5104(stream_rtp_sock(s), rtp_sess_ssrc(stream_rtp_sock(s)), 0); //err = rtcp_send_fir(stream_rtp_sock(s), // rtp_sess_ssrc(stream_rtp_sock(s))); - if (err) { - warning("video: failed to send RTCP %s: %m\n", - pli ? "PLI" : "FIR", err); + if (err) + warning("video: failed to send FIR %m\n", err); } } } @@ -1769,3 +1770,18 @@ const struct vidcodec *video_codec(const struct video *vid, bool tx) return tx ? vid->vtx.vc : vid->vrx.vc; } + + +void video_encode_refresh(struct video *v) +{ + struct vtx *vtx; + + if (v) + vtx = &v->vtx; + else + return; + + mtx_lock(&vtx->lock_enc); + vtx->picup = true; + mtx_unlock(&vtx->lock_enc); +} \ No newline at end of file From ae091c1e6c90b604632722de6e9c6abdc5d7a175 Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Fri, 6 Jan 2023 23:33:28 +0100 Subject: [PATCH 12/38] [Removed] RTCP FIR from rfc5104 --- src/video.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/video.c b/src/video.c index eb173d8b88..185e8ec705 100644 --- a/src/video.c +++ b/src/video.c @@ -643,9 +643,8 @@ static void send_fir(struct stream *s, bool pli) warning("video: failed to send picture_fast_update %m\n", err); } else { - err = rtcp_send_fir_rfc5104(stream_rtp_sock(s), rtp_sess_ssrc(stream_rtp_sock(s)), 0); - //err = rtcp_send_fir(stream_rtp_sock(s), - // rtp_sess_ssrc(stream_rtp_sock(s))); + err = rtcp_send_fir(stream_rtp_sock(s), + rtp_sess_ssrc(stream_rtp_sock(s))); if (err) warning("video: failed to send FIR %m\n", err); } From b6816131130029d3fd29b75a01d09827ec95c39d Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Mon, 9 Jan 2023 16:15:48 +0100 Subject: [PATCH 13/38] [Fixed] SIP media control --- src/call.c | 50 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/src/call.c b/src/call.c index d932e1c6b0..efdabbf4c7 100644 --- a/src/call.c +++ b/src/call.c @@ -94,8 +94,12 @@ enum sip_info_req { static int send_invite(struct call *call); static int send_info(struct sipsess *sess, const char* content_type, const char* content, + sip_resp_h *resph, void *arg, const char *fmt, ...); static int send_dtmf_info(struct call *call, char key); +static void send_pfu_info_handler(int err, + const struct sip_msg *msg, + void *arg); static const char *state_name(enum call_state st) @@ -1766,6 +1770,7 @@ int call_send_pfu(struct call *call) "" "" "", + send_pfu_info_handler, NULL, NULL); if (err) { warning("call: picture_fast_update request failed (%m)\n", err); @@ -1966,22 +1971,37 @@ static void dtmfend_handler(void *arg) } -static void sipsess_send_info_handler(int err, const struct sip_msg *msg, - void *arg) +static void send_dtmf_info_handler(int err, + const struct sip_msg *msg, + void *arg) { (void)arg; - //switch (req) { - // case DTMF: - if (err) - warning("call: sending DTMF INFO failed (%m)", err); - else if (msg && msg->scode != 200) - warning("call: sending DTMF INFO failed (scode: %d)", - msg->scode); - // break; - // case PICTURE_FAST_UPDATE: - // break; - //} + if (err) + warning("call: sending DTMF INFO failed (%m)", err); + else if (msg && msg->scode != 200) + warning("call: sending DTMF INFO failed (scode: %d)", + msg->scode); +} + + +static void send_pfu_info_handler(int err, + const struct sip_msg *msg, + void *arg) +{ + (void)arg; + struct config *cur_conf; + + if (err) + warning("call: sending PICTURE_FAST_UPDATE INFO failed (%m)", err); + else if (msg && msg->scode != 200) { + warning("call: sending PICTURE_FAST_UPDATE INFO failed (scode: %d)", + msg->scode); + + cur_conf = conf_config(); + if (cur_conf) + cur_conf->sip.media_control = false; + } } @@ -2509,6 +2529,7 @@ static int send_invite(struct call *call) static int send_info(struct sipsess *sess, const char* content_type, const char* content, + sip_resp_h *resph, void *arg, const char *fmt, ...) { struct mbuf *body; @@ -2522,7 +2543,7 @@ static int send_info(struct sipsess *sess, mbuf_set_pos(body, 0); err = sipsess_info(sess, content_type, body, - sipsess_send_info_handler, arg); + resph, arg); if (err) { goto out; @@ -2548,6 +2569,7 @@ static int send_dtmf_info(struct call *call, char key) err = send_info(call->sess, "application/dtmf-relay", "Signal=%c\r\nDuration=250\r\n", + send_dtmf_info_handler, call, &key); if (err) { warning("call: sipsess_info for DTMF failed (%m)\n", err); From 07fbedbf16cfc501095331e9f6b0b2467da04745 Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Fri, 10 Mar 2023 17:02:41 +0100 Subject: [PATCH 14/38] [Added] content parameter for video display --- include/baresip.h | 1 + src/video.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/include/baresip.h b/include/baresip.h index e5837b2403..b1fc9eb53f 100644 --- a/include/baresip.h +++ b/include/baresip.h @@ -1077,6 +1077,7 @@ struct vidisp_st; /** Video Display parameters */ struct vidisp_prm { bool fullscreen; /**< Enable fullscreen display */ + char content[64]; }; typedef void (vidisp_resize_h)(const struct vidsz *size, void *arg); diff --git a/src/video.c b/src/video.c index 185e8ec705..e0caa1ae06 100644 --- a/src/video.c +++ b/src/video.c @@ -158,6 +158,7 @@ struct video { struct vrx vrx; /**< Receive/decoder direction */ struct tmr tmr; /**< Timer for frame-rate estimation */ char *peer; /**< Peer URI */ + char *content; /**< Content type */ bool nack_pli; /**< Send NACK/PLI to peer */ video_err_h *errh; /**< Error handler */ void *arg; /**< Error handler argument */ @@ -356,6 +357,7 @@ static void video_destructor(void *arg) tmr_cancel(&v->tmr); mem_deref(v->strm); mem_deref(v->peer); + mem_deref(v->content); } @@ -1055,6 +1057,7 @@ int video_alloc(struct video **vp, struct list *streaml, if (content) { err |= sdp_media_set_lattr(stream_sdpmedia(v->strm), true, "content", "%s", content); + err |= str_dup(&v->content, content); } if (err) @@ -1127,6 +1130,7 @@ static void vidisp_resize_handler(const struct vidsz *sz, void *arg) static int set_vidisp(struct vrx *vrx) { struct vidisp *vd; + char *content; int err; vrx->vidisp = mem_deref(vrx->vidisp); @@ -1139,6 +1143,8 @@ static int set_vidisp(struct vrx *vrx) if (!vd) return ENOENT; + str_ncpy(&vrx->vidisp_prm.content, vrx->video->content, + sizeof(vrx->video->content)); err = vd->alloch(&vrx->vidisp, vd, &vrx->vidisp_prm, vrx->device, vidisp_resize_handler, vrx); if (err) From 58965995bfb36ae768d79f62758595a5394c92a3 Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Fri, 10 Mar 2023 17:30:33 +0100 Subject: [PATCH 15/38] [Added] display geometry parameters --- modules/x11/x11.c | 61 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 9 deletions(-) diff --git a/modules/x11/x11.c b/modules/x11/x11.c index 2538e8caf6..7ba9573641 100644 --- a/modules/x11/x11.c +++ b/modules/x11/x11.c @@ -45,6 +45,17 @@ struct vidisp_st { Atom XwinDeleted; int button_is_down; Time last_time; + char display[64]; + struct geometry { + struct resolution { + int w; + int h; + } res; + struct position { + int x; + int y; + } pos; + } geom; }; @@ -118,7 +129,8 @@ static int create_window(struct vidisp_st *st, const struct vidsz *sz) XSetWindowAttributes attr; #endif st->win = XCreateSimpleWindow(st->disp, DefaultRootWindow(st->disp), - 0, 0, sz->w, sz->h, 1, 0, 0); + st->geom.pos.x, st->geom.pos.y, + sz->w, sz->h, 0, 0, 0); if (!st->win) { warning("x11: failed to create X window\n"); return ENOMEM; @@ -272,6 +284,9 @@ static int alloc(struct vidisp_st **stp, const struct vidisp *vd, { struct vidisp_st *st; int err = 0; + char cfg_content[32] = "x11_"; + char cfg_geometry[64]; + struct pl x, y, w, h; (void)vd; (void)prm; (void)dev; @@ -284,7 +299,31 @@ static int alloc(struct vidisp_st **stp, const struct vidisp *vd, st->shm.shmaddr = (char *)-1; - st->disp = XOpenDisplay(NULL); + str_ncpy(st->display, "", str_len("")); + st->geom.res.w = st->geom.res.h = 0; + st->geom.pos.x = st->geom.pos.y = 0; + str_ncpy(cfg_content + str_len(cfg_content), + prm->content, str_len(prm->content)+1); + /* Example of expected lines in configuration file: + x11_main :0,1280x720+0+0 + x11_slides :0,1280x720+1280+0 */ + err = conf_get_csv(conf_cur(), cfg_content, + st->display, sizeof(st->display), + cfg_geometry, sizeof(cfg_geometry)); + + err = err | re_regex(cfg_geometry, + str_len(cfg_geometry), + "[0-9]*x[0-9]*\+[0-9]*\+[0-9]*", + &w, &h, &x, &y ); + if (!err) { + st->geom.res.w = pl_u32(&w); + st->geom.res.h = pl_u32(&h); + st->geom.pos.x = pl_u32(&x); + st->geom.pos.y = pl_u32(&y); + } + err = 0; + st->disp = XOpenDisplay(str_len(st->display)==0? + NULL:st->display); if (!st->disp) { warning("x11: could not open X display\n"); err = ENODEV; @@ -307,12 +346,16 @@ static int display(struct vidisp_st *st, const char *title, const struct vidframe *frame, uint64_t timestamp) { struct vidframe frame_rgb; + struct vidsz frame_size; int err = 0; (void)timestamp; if (!st->disp) return ENODEV; + frame_size.w = st->geom.res.w?st->geom.res.w:frame->size.w; + frame_size.h = st->geom.res.h?st->geom.res.h:frame->size.h; + /* * check for window delete - without blocking * the switch handles both the override redirect window @@ -365,29 +408,29 @@ static int display(struct vidisp_st *st, const char *title, } } - if (!vidsz_cmp(&st->size, &frame->size)) { + if (!vidsz_cmp(&st->size, &frame_size)) { char capt[256]; if (st->size.w && st->size.h) { info("x11: reset: %u x %u ---> %u x %u\n", st->size.w, st->size.h, - frame->size.w, frame->size.h); + frame_size.w, frame_size.h); } if (st->internal && !st->win) - err = create_window(st, &frame->size); + err = create_window(st, &frame_size); - err |= x11_reset(st, &frame->size); + err |= x11_reset(st, &frame_size); if (err) return err; if (title) { re_snprintf(capt, sizeof(capt), "%s - %u x %u", - title, frame->size.w, frame->size.h); + title, frame_size.w, frame_size.h); } else { re_snprintf(capt, sizeof(capt), "%u x %u", - frame->size.w, frame->size.h); + frame_size.w, frame_size.h); } XStoreName(st->disp, st->win, capt); @@ -395,7 +438,7 @@ static int display(struct vidisp_st *st, const char *title, /* Convert from YUV420P to RGB */ - vidframe_init_buf(&frame_rgb, st->pixfmt, &frame->size, + vidframe_init_buf(&frame_rgb, st->pixfmt, &frame_size, (uint8_t *)st->shm.shmaddr); vidconv(&frame_rgb, frame, 0); From a2b31256a67657ac096efcff5c9999025c8f870b Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Fri, 10 Mar 2023 19:33:11 +0100 Subject: [PATCH 16/38] [Added] basic BFCP implementation --- CMakeLists.txt | 1 + include/baresip.h | 5 ++++ src/call.c | 71 +++++++++++++++++++++++++++++++++++++++++++++-- src/config.c | 14 +++++++++- src/core.h | 11 ++++++++ 5 files changed, 99 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 274e62fc94..3dfbf71716 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -147,6 +147,7 @@ set(SRCS src/auplay.c src/ausrc.c src/baresip.c + src/bfcp.c src/bundle.c src/call.c src/cmd.c diff --git a/include/baresip.h b/include/baresip.h index b1fc9eb53f..453e3e466c 100644 --- a/include/baresip.h +++ b/include/baresip.h @@ -399,6 +399,10 @@ struct config_net { bool use_getaddrinfo; /**< Use getaddrinfo for A/AAAA records */ }; +/** BFCP **/ +struct config_bfcp { + char proto[16]; /**< BFCP Transport (optional) */ +}; /** Core configuration */ struct config { @@ -413,6 +417,7 @@ struct config { struct config_avt avt; struct config_net net; + struct config_bfcp bfcp; }; int config_parse_conf(struct config *cfg, const struct conf *conf); diff --git a/src/call.c b/src/call.c index efdabbf4c7..8003d659ec 100644 --- a/src/call.c +++ b/src/call.c @@ -37,6 +37,8 @@ struct call { struct list streaml; /**< List of mediastreams (struct stream) */ struct audio *audio; /**< Audio stream */ struct video *video; /**< Video stream */ + struct video *video_bis; /**< Video stream */ + struct bfcp *bfcp; /**< BFCP */ enum call_state state; /**< Call state */ int32_t adelay; /**< Auto answer delay in ms */ char *aluri; /**< Alert-Info URI */ @@ -213,6 +215,19 @@ static void call_stream_start(struct call *call, bool active) warning("call: could not start video: %m\n", err); } } + if (stream_is_ready(video_strm(call->video_bis))) { + err = video_update(call->video_bis, call->peer_uri); + if (err) { + warning("call: could not start video bis: %m\n", err); + } + } + + if (call->bfcp) { + err = bfcp_start(call->bfcp); + if (err) { + warning("call: could not start BFCP: %m\n", err); + } + } if (active) { @@ -242,6 +257,7 @@ static void call_stream_stop(struct call *call) /* Video */ video_stop(call->video); + video_stop(call->video_bis); tmr_cancel(&call->tmr_inv); } @@ -369,6 +385,9 @@ static int update_media(struct call *call) if (call->video) video_sdp_attr_decode(call->video); + if (call->video_bis) + video_sdp_attr_decode(call->video_bis); + /* Update each stream */ FOREACH_STREAM { struct stream *strm = le->data; @@ -392,6 +411,11 @@ static int update_media(struct call *call) else video_stop(call->video); + if (stream_is_ready(video_strm(call->video_bis))) + err |= video_update(call->video_bis, call->peer_uri); + else + video_stop(call->video_bis); + return err; } @@ -431,6 +455,8 @@ static void call_destructor(void *arg) mem_deref(call->diverter_uri); mem_deref(call->audio); mem_deref(call->video); + mem_deref(call->video_bis); + mem_deref(call->bfcp); mem_deref(call->sdp); mem_deref(call->mnats); mem_deref(call->mencs); @@ -522,6 +548,13 @@ static void menc_event_handler(enum menc_event event, warning("call: secure: could not" " start video: %m\n", err); } + stream_set_secure(video_strm(call->video_bis), true); + stream_start_rtcp(video_strm(call->video_bis)); + err = video_update(call->video_bis, call->peer_uri); + if (err) { + warning("call: secure: could not" + " start video: %m\n", err); + } } else { info("call: mediaenc: no match for stream (%s)\n", @@ -582,6 +615,9 @@ static void stream_mnatconn_handler(struct stream *strm, void *arg) case MEDIA_VIDEO: err = video_update(call->video, call->peer_uri); + if (err) { + err = video_update(call->video_bis, call->peer_uri); + } if (err) { warning("call: mnatconn: could not" " start video: %m\n", err); @@ -834,6 +870,27 @@ int call_streams_alloc(struct call *call) video_error_handler, call); if (err) return err; + + err = video_alloc(&call->video_bis, &call->streaml, &strm_prm, + call->cfg, call->sdp, + acc->mnat, call->mnats, + acc->menc, call->mencs, + "slides", + account_vidcodecl(call->acc), + baresip_vidfiltl(), !call->got_offer, + video_error_handler, call); + stream_set_ldir(video_strm(call->video_bis), SDP_RECVONLY); + + if (err) + return err; + + if (str_isset(call->cfg->bfcp.proto)) { + err = bfcp_alloc(&call->bfcp, call->sdp, + call->cfg->bfcp.proto, !call->got_offer, + acc->mnat, call->mnats); + if (err) + return err; + } } FOREACH_STREAM { @@ -1370,6 +1427,9 @@ int call_answer(struct call *call, uint16_t scode, enum vidmode vmode) if (vmode == VIDMODE_OFF) call->video = mem_deref(call->video); + if (vmode == VIDMODE_OFF) + call->video_bis = mem_deref(call->video); + info("call: answering call on line %u from %s with %u\n", call->linenum, call->peer_uri, scode); @@ -1441,7 +1501,8 @@ bool call_has_video(const struct call *call) if (!call) return false; - return sdp_media_has_media(stream_sdpmedia(video_strm(call->video))); + return sdp_media_has_media(stream_sdpmedia(video_strm(call->video))) || + sdp_media_has_media(stream_sdpmedia(video_strm(call->video_bis))) ; } @@ -1682,6 +1743,9 @@ int call_status(struct re_printf *pf, const struct call *call) if (call->video) err |= video_print(pf, call->video); + if (call->video_bis) + err |= video_print(pf, call->video_bis); + /* remove old junk */ err |= re_hprintf(pf, " "); @@ -2197,6 +2261,8 @@ static bool have_common_video_codecs(const struct call *call) struct vidcodec *vc; sc = sdp_media_rcodec(stream_sdpmedia(video_strm(call->video))); + if (!sc) + sc = sdp_media_rcodec(stream_sdpmedia(video_strm(call->video_bis))); if (!sc) return false; @@ -2261,7 +2327,8 @@ int call_accept(struct call *call, struct sipsess_sock *sess_sock, * See RFC 6157 */ if (!valid_addressfamily(call, audio_strm(call->audio)) || - !valid_addressfamily(call, video_strm(call->video))) { + !valid_addressfamily(call, video_strm(call->video)) || + !valid_addressfamily(call, video_strm(call->video_bis))){ sip_treply(NULL, uag_sip(), msg, 488, "Not Acceptable Here"); diff --git a/src/config.c b/src/config.c index 22b91e637c..994987e492 100644 --- a/src/config.c +++ b/src/config.c @@ -462,6 +462,9 @@ int config_parse_conf(struct config *cfg, const struct conf *conf) &cfg->net.use_getaddrinfo); (void)conf_get_str(conf, "net_interface", cfg->net.ifname, sizeof(cfg->net.ifname)); + /* BFCP */ + (void)conf_get_str(conf, "bfcp_proto", cfg->bfcp.proto, + sizeof(cfg->bfcp.proto)); return err; } @@ -543,6 +546,9 @@ int config_print(struct re_printf *pf, const struct config *cfg) "# Network\n" "net_interface\t\t%s\n" "\n" + "# BFCP\n" + "bfcp_proto\t\t%s\n" + "\n" , cfg->sip.local, cfg->sip.cert, cfg->sip.cafile, @@ -591,7 +597,9 @@ int config_print(struct re_printf *pf, const struct config *cfg) cfg->avt.rtp_stats ? "yes" : "no", cfg->avt.rtp_timeout, - cfg->net.ifname + cfg->net.ifname, + + cfg->bfcp.proto ); return err; @@ -802,6 +810,10 @@ static int core_config_template(struct re_printf *pf, const struct config *cfg) cfg->avt.jbuf_del.min, cfg->avt.jbuf_del.max, default_interface_print, NULL); + err |= re_hprintf(pf, + "\n# BFCP\n" + "#bfcp_proto\t\tudp\n"); + return err; } diff --git a/src/core.h b/src/core.h index 1e570cf532..73440c036d 100644 --- a/src/core.h +++ b/src/core.h @@ -105,6 +105,17 @@ int audio_send_digit(struct audio *a, char key); void audio_sdp_attr_decode(struct audio *a); +/* + * BFCP + */ + +struct bfcp; +int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess, + const char *proto, bool offerer, + const struct mnat *mnat, struct mnat_sess *mnat_sess); +int bfcp_start(struct bfcp *bfcp); + + /* * Call Control */ From 7f41c0caca54c3c63435f525dec9e97ad7ff877c Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Wed, 15 Mar 2023 17:00:57 +0100 Subject: [PATCH 17/38] [Added] basic BFCP implementation --- src/bfcp.c | 269 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 269 insertions(+) create mode 100644 src/bfcp.c diff --git a/src/bfcp.c b/src/bfcp.c new file mode 100644 index 0000000000..415987f983 --- /dev/null +++ b/src/bfcp.c @@ -0,0 +1,269 @@ +/** + * @file bfcp.c BFCP client + * + * Copyright (C) 2011 Creytiv.com + */ +#include +#include +#include +#include "core.h" + + +struct bfcp { + struct bfcp_conn *conn; + struct sdp_media *sdpm; + const struct mnat *mnat; /**< Media NAT traversal module */ + struct mnat_media *mnat_st; + bool active; + + /* server */ + uint32_t lconfid; + uint16_t luserid; + + uint16_t lfloorid; + uint16_t lmstrm; +}; + + +static void destructor(void *arg) +{ + struct bfcp *bfcp = arg; + + mem_deref(bfcp->mnat_st); + mem_deref(bfcp->sdpm); + mem_deref(bfcp->conn); +} + +static int stdout_handler(const char *p, size_t size, void *arg) +{ + (void)arg; + + if (1 != fwrite(p, size, 1, stdout)) + return ENOMEM; + + return 0; +} + + +static const char *bfcp_sdp_transp(enum bfcp_transp tp) +{ + switch (tp) { + + case BFCP_UDP: return "UDP/BFCP"; + case BFCP_TCP: return "TCP/BFCP"; + case BFCP_DTLS: return "UDP/TLS/BFCP"; + default: return NULL; + } +} + + +static enum bfcp_transp str2tp(const char *proto) +{ + if (0 == str_casecmp(proto, "udp")) + return BFCP_UDP; + if (0 == str_casecmp(proto, "tcp")) + return BFCP_TCP; + else if (0 == str_casecmp(proto, "dtls")) + return BFCP_DTLS; + else { + warning("unsupported BFCP protocol: %s\n", proto); + return -1; + } +} + + +static void bfcp_resp_handler(int err, const struct bfcp_msg *msg, void *arg) +{ + struct bfcp *bfcp = arg; + (void)bfcp; + + if (err) { + warning("bfcp: error response: %m\n", err); + return; + } + + info("bfcp: received BFCP response: '%s'\n", + bfcp_prim_name(msg->prim)); + + struct re_printf pf; + pf.vph = stdout_handler; + pf.arg = NULL; + bfcp_msg_print(&pf, msg); +} + + +void print_attr(const struct bfcp_attr *attr,void *dummy) +{ + struct re_printf pf; + pf.vph = stdout_handler; + pf.arg = NULL; + bfcp_attr_print(&pf, attr); + info("\n"); +} + + +static void bfcp_msg_handler(const struct bfcp_msg *msg, void *arg) +{ + struct bfcp *bfcp = arg; + + info("bfcp: received BFCP message '%s'\n", bfcp_prim_name(msg->prim)); + + struct re_printf pf; + struct bfcp_attr *attr; + pf.vph = stdout_handler; + pf.arg = NULL; + //bfcp_msg_print(&pf, msg); + + switch (msg->prim) { + + case BFCP_HELLO: + (void)bfcp_reply(bfcp->conn, msg, BFCP_HELLO_ACK, 0); + break; + + case BFCP_FLOOR_REQUEST: + bfcp_msg_attr_apply(msg,print_attr,NULL); + attr = bfcp_msg_attr(msg, BFCP_FLOOR_ID); + uint16_t attr_val = attr->v.u16; + uint16_t floor_request_id = 1; + struct bfcp_reqstatus reqstatus; + reqstatus.status = BFCP_GRANTED; + reqstatus.qpos = 0; + (void)bfcp_reply(bfcp->conn, msg, + BFCP_FLOOR_REQUEST_STATUS, 1, + BFCP_FLOOR_REQ_INFO, 2, &floor_request_id, + BFCP_OVERALL_REQ_STATUS, 1, &floor_request_id, + BFCP_REQUEST_STATUS, 0, &reqstatus, + BFCP_FLOOR_REQ_STATUS, 0, &attr_val); + break; + + default: + (void)bfcp_ereply(bfcp->conn, msg, BFCP_UNKNOWN_PRIM); + break; + } +} + +static void mnat_connected_handler(const struct sa *raddr1, + const struct sa *raddr2, void *arg) +{ + struct bfcp *bfcp = arg; + + info("BFCP mnat '%s' connected: raddr %J %J\n", + bfcp->mnat->id, raddr1, raddr2); +} + +int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess, + const char *proto, bool offerer, + const struct mnat *mnat, struct mnat_sess *mnat_sess) +{ + struct bfcp *bfcp; + struct sa laddr; + enum bfcp_transp transp; + int err; + + if (!bfcpp || !sdp_sess) + return EINVAL; + + transp = str2tp(proto); + + bfcp = mem_zalloc(sizeof(*bfcp), destructor); + if (!bfcp) + return ENOMEM; + + bfcp->active = offerer; + + sa_init(&laddr, AF_INET); + + err = bfcp_listen(&bfcp->conn, transp, &laddr, uag_tls(), + NULL, NULL, bfcp_msg_handler, NULL, bfcp); + if (err) + goto out; + + err = sdp_media_add(&bfcp->sdpm, sdp_sess, "application", + sa_port(&laddr), bfcp_sdp_transp(transp)); + if (err) + goto out; + + err = sdp_format_add(NULL, bfcp->sdpm, false, "*", NULL, + 0, 0, NULL, NULL, NULL, false, NULL); + if (err) + goto out; + + err |= sdp_media_set_lattr(bfcp->sdpm, true, "floorctrl", "c-s"); + err |= sdp_media_set_lattr(bfcp->sdpm, true, "setup", + bfcp->active ? "active" : "actpass"); + + if (bfcp->active) { + err |= sdp_media_set_lattr(bfcp->sdpm, true, + "connection", "new"); + } + else { + bfcp->lconfid = 1000 + (rand_u16() & 0xf); + bfcp->luserid = 1 + (rand_u16() & 0x7); + + err |= sdp_media_set_lattr(bfcp->sdpm, true, "confid", + "%u", bfcp->lconfid); + err |= sdp_media_set_lattr(bfcp->sdpm, true, "userid", + "%u", bfcp->luserid); + + bfcp->lfloorid = 2; + bfcp->lmstrm = 12; + err |= sdp_media_set_lattr(bfcp->sdpm, true, "floorid", + "%u mstrm %u", bfcp->lfloorid, bfcp->lmstrm); + + err |= sdp_media_set_lattr(bfcp->sdpm, true, + "connection", "new"); + } + + if (err) + goto out; + + if (mnat) { + info("bfcp: enabled medianat '%s' on UDP socket\n", mnat->id); + //bfcp->mnat = mnat; + err = mnat->mediah(&bfcp->mnat_st, mnat_sess, + bfcp_sock(bfcp->conn), NULL, bfcp->sdpm, mnat_connected_handler, bfcp); + if (err) + goto out; + } + + info("bfcp: %s BFCP agent protocol '%s' on port %d\n", + bfcp->active ? "Active" : "Passive", + proto, sa_port(&laddr)); + + out: + if (err) + mem_deref(bfcp); + else + *bfcpp = bfcp; + + return err; +} + + +int bfcp_start(struct bfcp *bfcp) +{ + const struct sa *paddr; + uint32_t confid = 0; + uint16_t userid = 0; + int err = 0; + + if (!bfcp) + return EINVAL; + + if (!sdp_media_rport(bfcp->sdpm)) { + info("bfcp channel is disabled\n"); + return 0; + } + + if (bfcp->active) { + + paddr = sdp_media_raddr(bfcp->sdpm); + confid = sdp_media_rattr(bfcp->sdpm, "confid"); + userid = sdp_media_rattr(bfcp->sdpm, "userid"); + + err = bfcp_request(bfcp->conn, paddr, BFCP_VER2, BFCP_HELLO, + confid, userid, bfcp_resp_handler, bfcp, 0); + } + + return err; +} From 8e9fb5c70e4463cf6fb77fb66974e39a340e8ccf Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Mon, 20 Mar 2023 15:18:32 +0100 Subject: [PATCH 18/38] [Added] UA_EVENT_CALL_BFCP --- include/baresip.h | 1 + src/bfcp.c | 13 ++++++++++--- src/call.c | 5 +++-- src/core.h | 1 + src/event.c | 1 + 5 files changed, 16 insertions(+), 5 deletions(-) diff --git a/include/baresip.h b/include/baresip.h index 453e3e466c..56f4d66495 100644 --- a/include/baresip.h +++ b/include/baresip.h @@ -810,6 +810,7 @@ enum ua_event { UA_EVENT_CALL_DTMF_END, UA_EVENT_CALL_RTPESTAB, UA_EVENT_CALL_RTCP, + UA_EVENT_CALL_BFCP, UA_EVENT_CALL_MENC, UA_EVENT_VU_TX, UA_EVENT_VU_RX, diff --git a/src/bfcp.c b/src/bfcp.c index 415987f983..c5a083e8b3 100644 --- a/src/bfcp.c +++ b/src/bfcp.c @@ -10,6 +10,7 @@ struct bfcp { + struct ua *ua; struct bfcp_conn *conn; struct sdp_media *sdpm; const struct mnat *mnat; /**< Media NAT traversal module */ @@ -117,11 +118,12 @@ static void bfcp_msg_handler(const struct bfcp_msg *msg, void *arg) switch (msg->prim) { case BFCP_HELLO: + ua_event(bfcp->ua, UA_EVENT_CALL_BFCP, NULL, "BFCP_HELLO"); (void)bfcp_reply(bfcp->conn, msg, BFCP_HELLO_ACK, 0); break; case BFCP_FLOOR_REQUEST: - bfcp_msg_attr_apply(msg,print_attr,NULL); + ua_event(bfcp->ua, UA_EVENT_CALL_BFCP, NULL, "BFCP_FLOOR_REQUEST"); attr = bfcp_msg_attr(msg, BFCP_FLOOR_ID); uint16_t attr_val = attr->v.u16; uint16_t floor_request_id = 1; @@ -136,6 +138,10 @@ static void bfcp_msg_handler(const struct bfcp_msg *msg, void *arg) BFCP_FLOOR_REQ_STATUS, 0, &attr_val); break; + case BFCP_FLOOR_RELEASE: + ua_event(bfcp->ua, UA_EVENT_CALL_BFCP, NULL, "BFCP_FLOOR_RELEASE"); + break; + default: (void)bfcp_ereply(bfcp->conn, msg, BFCP_UNKNOWN_PRIM); break; @@ -152,6 +158,7 @@ static void mnat_connected_handler(const struct sa *raddr1, } int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess, + struct ua *ua, const char *proto, bool offerer, const struct mnat *mnat, struct mnat_sess *mnat_sess) { @@ -160,7 +167,7 @@ int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess, enum bfcp_transp transp; int err; - if (!bfcpp || !sdp_sess) + if (!bfcpp || !sdp_sess || !ua) return EINVAL; transp = str2tp(proto); @@ -170,6 +177,7 @@ int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess, return ENOMEM; bfcp->active = offerer; + bfcp->ua = ua; sa_init(&laddr, AF_INET); @@ -219,7 +227,6 @@ int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess, if (mnat) { info("bfcp: enabled medianat '%s' on UDP socket\n", mnat->id); - //bfcp->mnat = mnat; err = mnat->mediah(&bfcp->mnat_st, mnat_sess, bfcp_sock(bfcp->conn), NULL, bfcp->sdpm, mnat_connected_handler, bfcp); if (err) diff --git a/src/call.c b/src/call.c index 8003d659ec..747aae61a9 100644 --- a/src/call.c +++ b/src/call.c @@ -886,8 +886,9 @@ int call_streams_alloc(struct call *call) if (str_isset(call->cfg->bfcp.proto)) { err = bfcp_alloc(&call->bfcp, call->sdp, - call->cfg->bfcp.proto, !call->got_offer, - acc->mnat, call->mnats); + call->ua, + call->cfg->bfcp.proto, !call->got_offer, + acc->mnat, call->mnats); if (err) return err; } diff --git a/src/core.h b/src/core.h index 73440c036d..23d3265e02 100644 --- a/src/core.h +++ b/src/core.h @@ -111,6 +111,7 @@ void audio_sdp_attr_decode(struct audio *a); struct bfcp; int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess, + struct ua *ua, const char *proto, bool offerer, const struct mnat *mnat, struct mnat_sess *mnat_sess); int bfcp_start(struct bfcp *bfcp); diff --git a/src/event.c b/src/event.c index 2ca6dfdc70..466869ee93 100644 --- a/src/event.c +++ b/src/event.c @@ -432,6 +432,7 @@ const char *uag_event_str(enum ua_event ev) case UA_EVENT_CALL_DTMF_END: return "CALL_DTMF_END"; case UA_EVENT_CALL_RTPESTAB: return "CALL_RTPESTAB"; case UA_EVENT_CALL_RTCP: return "CALL_RTCP"; + case UA_EVENT_CALL_BFCP: return "CALL_BFCP"; case UA_EVENT_CALL_MENC: return "CALL_MENC"; case UA_EVENT_VU_TX: return "VU_TX_REPORT"; case UA_EVENT_VU_RX: return "VU_RX_REPORT"; From 1eb9d652a733f30bc468cb6b7ecce0b082d667b4 Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Tue, 21 Mar 2023 15:52:43 +0100 Subject: [PATCH 19/38] [Added] bfcp_floorctrl configuration parameter --- include/baresip.h | 3 ++- src/bfcp.c | 18 +++++++++++------- src/call.c | 2 +- src/config.c | 9 +++++++-- src/core.h | 2 +- 5 files changed, 22 insertions(+), 12 deletions(-) diff --git a/include/baresip.h b/include/baresip.h index 56f4d66495..1d44a232f7 100644 --- a/include/baresip.h +++ b/include/baresip.h @@ -401,7 +401,8 @@ struct config_net { /** BFCP **/ struct config_bfcp { - char proto[16]; /**< BFCP Transport (optional) */ + char proto[16]; /**< BFCP Transport */ + char floorctrl[16]; /**< BFCP floor control role */ }; /** Core configuration */ diff --git a/src/bfcp.c b/src/bfcp.c index c5a083e8b3..93d29db1dc 100644 --- a/src/bfcp.c +++ b/src/bfcp.c @@ -13,7 +13,7 @@ struct bfcp { struct ua *ua; struct bfcp_conn *conn; struct sdp_media *sdpm; - const struct mnat *mnat; /**< Media NAT traversal module */ + const struct mnat *mnat; struct mnat_media *mnat_st; bool active; @@ -159,7 +159,7 @@ static void mnat_connected_handler(const struct sa *raddr1, int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess, struct ua *ua, - const char *proto, bool offerer, + const struct config_bfcp *bfcp_cfg, bool offerer, const struct mnat *mnat, struct mnat_sess *mnat_sess) { struct bfcp *bfcp; @@ -170,7 +170,7 @@ int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess, if (!bfcpp || !sdp_sess || !ua) return EINVAL; - transp = str2tp(proto); + transp = str2tp(bfcp_cfg->proto); bfcp = mem_zalloc(sizeof(*bfcp), destructor); if (!bfcp) @@ -196,7 +196,9 @@ int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess, if (err) goto out; - err |= sdp_media_set_lattr(bfcp->sdpm, true, "floorctrl", "c-s"); + err |= sdp_media_set_lattr(bfcp->sdpm, true, "floorctrl", + str_isset(bfcp_cfg->floorctrl)? + bfcp_cfg->floorctrl:"c-s"); err |= sdp_media_set_lattr(bfcp->sdpm, true, "setup", bfcp->active ? "active" : "actpass"); @@ -216,7 +218,8 @@ int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess, bfcp->lfloorid = 2; bfcp->lmstrm = 12; err |= sdp_media_set_lattr(bfcp->sdpm, true, "floorid", - "%u mstrm %u", bfcp->lfloorid, bfcp->lmstrm); + "%u mstrm %u", bfcp->lfloorid, + bfcp->lmstrm); err |= sdp_media_set_lattr(bfcp->sdpm, true, "connection", "new"); @@ -228,14 +231,15 @@ int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess, if (mnat) { info("bfcp: enabled medianat '%s' on UDP socket\n", mnat->id); err = mnat->mediah(&bfcp->mnat_st, mnat_sess, - bfcp_sock(bfcp->conn), NULL, bfcp->sdpm, mnat_connected_handler, bfcp); + bfcp_sock(bfcp->conn), NULL, bfcp->sdpm, + mnat_connected_handler, bfcp); if (err) goto out; } info("bfcp: %s BFCP agent protocol '%s' on port %d\n", bfcp->active ? "Active" : "Passive", - proto, sa_port(&laddr)); + bfcp_cfg->proto, sa_port(&laddr)); out: if (err) diff --git a/src/call.c b/src/call.c index 747aae61a9..ffd01d99f3 100644 --- a/src/call.c +++ b/src/call.c @@ -887,7 +887,7 @@ int call_streams_alloc(struct call *call) if (str_isset(call->cfg->bfcp.proto)) { err = bfcp_alloc(&call->bfcp, call->sdp, call->ua, - call->cfg->bfcp.proto, !call->got_offer, + &call->cfg->bfcp, !call->got_offer, acc->mnat, call->mnats); if (err) return err; diff --git a/src/config.c b/src/config.c index 994987e492..b908b7307e 100644 --- a/src/config.c +++ b/src/config.c @@ -465,6 +465,8 @@ int config_parse_conf(struct config *cfg, const struct conf *conf) /* BFCP */ (void)conf_get_str(conf, "bfcp_proto", cfg->bfcp.proto, sizeof(cfg->bfcp.proto)); + (void)conf_get_str(conf, "bfcp_floorctrl", cfg->bfcp.floorctrl, + sizeof(cfg->bfcp.floorctrl)); return err; } @@ -548,6 +550,7 @@ int config_print(struct re_printf *pf, const struct config *cfg) "\n" "# BFCP\n" "bfcp_proto\t\t%s\n" + "bfcp_floorctrl\t\t%s\n" "\n" , @@ -599,7 +602,8 @@ int config_print(struct re_printf *pf, const struct config *cfg) cfg->net.ifname, - cfg->bfcp.proto + cfg->bfcp.proto, + cfg->bfcp.floorctrl ); return err; @@ -812,7 +816,8 @@ static int core_config_template(struct re_printf *pf, const struct config *cfg) err |= re_hprintf(pf, "\n# BFCP\n" - "#bfcp_proto\t\tudp\n"); + "#bfcp_proto\t\tudp\n" + "#bfcp_floorctrl\t\ts-only\n"); return err; } diff --git a/src/core.h b/src/core.h index 23d3265e02..8065d2f03d 100644 --- a/src/core.h +++ b/src/core.h @@ -112,7 +112,7 @@ void audio_sdp_attr_decode(struct audio *a); struct bfcp; int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess, struct ua *ua, - const char *proto, bool offerer, + const struct config_bfcp *bfcp_cfg, bool offerer, const struct mnat *mnat, struct mnat_sess *mnat_sess); int bfcp_start(struct bfcp *bfcp); From 754f1bbd05c3039b58c2e479bda336470c6e0f19 Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Mon, 3 Apr 2023 15:22:43 +0200 Subject: [PATCH 20/38] [Added] BFCP call flow experiments --- src/bfcp.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 70 insertions(+), 10 deletions(-) diff --git a/src/bfcp.c b/src/bfcp.c index 93d29db1dc..6099a1f778 100644 --- a/src/bfcp.c +++ b/src/bfcp.c @@ -114,12 +114,57 @@ static void bfcp_msg_handler(const struct bfcp_msg *msg, void *arg) pf.vph = stdout_handler; pf.arg = NULL; //bfcp_msg_print(&pf, msg); + struct bfcp_supprim supprim; + struct bfcp_supattr supattr; + enum bfcp_prim prim[] = { BFCP_FLOOR_REQUEST, + BFCP_FLOOR_RELEASE, + BFCP_FLOOR_REQUEST_QUERY, + BFCP_FLOOR_REQUEST_STATUS, + BFCP_USER_QUERY, + BFCP_USER_STATUS, + BFCP_FLOOR_QUERY, + BFCP_FLOOR_STATUS, + BFCP_CHAIR_ACTION, + BFCP_CHAIR_ACTION_ACK, + BFCP_HELLO, + BFCP_HELLO_ACK, + BFCP_ERROR, + BFCP_FLOOR_REQ_STATUS_ACK, + BFCP_FLOOR_STATUS_ACK, + BFCP_GOODBYE, + BFCP_GOODBYE_ACK }; + + enum bfcp_attrib attrib[] = { BFCP_BENEFICIARY_ID, + BFCP_FLOOR_ID, + BFCP_FLOOR_REQUEST_ID, + BFCP_PRIORITY, + BFCP_REQUEST_STATUS, + BFCP_ERROR_CODE, + BFCP_ERROR_INFO, + BFCP_PART_PROV_INFO, + BFCP_STATUS_INFO, + BFCP_SUPPORTED_ATTRS , + BFCP_SUPPORTED_PRIMS, + BFCP_USER_DISP_NAME, + BFCP_USER_URI , + BFCP_BENEFICIARY_INFO, + BFCP_FLOOR_REQ_INFO, + BFCP_REQUESTED_BY_INFO, + BFCP_FLOOR_REQ_STATUS, + BFCP_OVERALL_REQ_STATUS }; switch (msg->prim) { case BFCP_HELLO: + supprim.primv = prim; + supprim.primc = sizeof(prim)/sizeof(prim[0]); + supattr.attrv = attrib; + supattr.attrc = sizeof(attrib)/sizeof(attrib[0]); ua_event(bfcp->ua, UA_EVENT_CALL_BFCP, NULL, "BFCP_HELLO"); - (void)bfcp_reply(bfcp->conn, msg, BFCP_HELLO_ACK, 0); + (void)bfcp_reply(bfcp->conn, msg, + BFCP_HELLO_ACK, 2, + BFCP_SUPPORTED_ATTRS, 0, &supattr, + BFCP_SUPPORTED_PRIMS, 0, &supprim); break; case BFCP_FLOOR_REQUEST: @@ -180,6 +225,7 @@ int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess, bfcp->ua = ua; sa_init(&laddr, AF_INET); + //sa_set_port(&laddr, 5050); err = bfcp_listen(&bfcp->conn, transp, &laddr, uag_tls(), NULL, NULL, bfcp_msg_handler, NULL, bfcp); @@ -202,10 +248,13 @@ int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess, err |= sdp_media_set_lattr(bfcp->sdpm, true, "setup", bfcp->active ? "active" : "actpass"); +#if 0 if (bfcp->active) { err |= sdp_media_set_lattr(bfcp->sdpm, true, "connection", "new"); } +#endif + else { bfcp->lconfid = 1000 + (rand_u16() & 0xf); bfcp->luserid = 1 + (rand_u16() & 0x7); @@ -215,8 +264,8 @@ int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess, err |= sdp_media_set_lattr(bfcp->sdpm, true, "userid", "%u", bfcp->luserid); - bfcp->lfloorid = 2; - bfcp->lmstrm = 12; + bfcp->lfloorid = 1; + bfcp->lmstrm = 3; err |= sdp_media_set_lattr(bfcp->sdpm, true, "floorid", "%u mstrm %u", bfcp->lfloorid, bfcp->lmstrm); @@ -257,6 +306,7 @@ int bfcp_start(struct bfcp *bfcp) uint32_t confid = 0; uint16_t userid = 0; int err = 0; + char *floorctrl; if (!bfcp) return EINVAL; @@ -266,15 +316,25 @@ int bfcp_start(struct bfcp *bfcp) return 0; } - if (bfcp->active) { + floorctrl = sdp_media_rattr(bfcp->sdpm, "floorctrl"); - paddr = sdp_media_raddr(bfcp->sdpm); - confid = sdp_media_rattr(bfcp->sdpm, "confid"); - userid = sdp_media_rattr(bfcp->sdpm, "userid"); + if (floorctrl ) + if (str_str(floorctrl, "s")) { - err = bfcp_request(bfcp->conn, paddr, BFCP_VER2, BFCP_HELLO, - confid, userid, bfcp_resp_handler, bfcp, 0); - } + paddr = sdp_media_raddr(bfcp->sdpm); + confid = atoi(sdp_media_rattr(bfcp->sdpm, "confid")); + if(sdp_media_rattr(bfcp->sdpm, "confid")) + confid = atoi(sdp_media_rattr(bfcp->sdpm, "confid")); + + userid = atoi(sdp_media_rattr(bfcp->sdpm, "userid")); + if(sdp_media_rattr(bfcp->sdpm, "userid")) + userid = atoi(sdp_media_rattr(bfcp->sdpm, "userid")); + + uint16_t floor_id = 1; + err = bfcp_request(bfcp->conn, paddr, BFCP_VER1, BFCP_HELLO, + confid, userid, bfcp_resp_handler, bfcp, 1, + BFCP_FLOOR_ID, 0, &floor_id); + } return err; } From 4a94b9b26f68671b978bc862a503518d977e6d3e Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Mon, 3 Apr 2023 15:40:35 +0200 Subject: [PATCH 21/38] [Fixed] BFCP call flow experiments --- src/bfcp.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/bfcp.c b/src/bfcp.c index 6099a1f778..9360d21b4b 100644 --- a/src/bfcp.c +++ b/src/bfcp.c @@ -248,13 +248,10 @@ int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess, err |= sdp_media_set_lattr(bfcp->sdpm, true, "setup", bfcp->active ? "active" : "actpass"); -#if 0 - if (bfcp->active) { + if (/*bfcp->active*/false) { err |= sdp_media_set_lattr(bfcp->sdpm, true, "connection", "new"); } -#endif - else { bfcp->lconfid = 1000 + (rand_u16() & 0xf); bfcp->luserid = 1 + (rand_u16() & 0x7); From 9e8371767242e925fc4cac4c9b2bfec5a6044a2f Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Mon, 3 Apr 2023 16:33:03 +0200 Subject: [PATCH 22/38] [Fixed] BFCP call flow experiments --- src/bfcp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bfcp.c b/src/bfcp.c index 9360d21b4b..f6eaf1cc64 100644 --- a/src/bfcp.c +++ b/src/bfcp.c @@ -319,11 +319,11 @@ int bfcp_start(struct bfcp *bfcp) if (str_str(floorctrl, "s")) { paddr = sdp_media_raddr(bfcp->sdpm); - confid = atoi(sdp_media_rattr(bfcp->sdpm, "confid")); + confid = 1; if(sdp_media_rattr(bfcp->sdpm, "confid")) confid = atoi(sdp_media_rattr(bfcp->sdpm, "confid")); - userid = atoi(sdp_media_rattr(bfcp->sdpm, "userid")); + userid = 1; if(sdp_media_rattr(bfcp->sdpm, "userid")) userid = atoi(sdp_media_rattr(bfcp->sdpm, "userid")); From e568ef04fdbd9e492eb8a3b83d651980a3c17534 Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Thu, 6 Apr 2023 14:45:30 +0200 Subject: [PATCH 23/38] [Added] video fmtp append --- modules/avcodec/sdp.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/avcodec/sdp.c b/modules/avcodec/sdp.c index 7ac676ee19..7f15c82dbf 100644 --- a/modules/avcodec/sdp.c +++ b/modules/avcodec/sdp.c @@ -39,6 +39,7 @@ int avcodec_h264_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, uint8_t profile_idc = 0x42; /* baseline profile */ uint8_t profile_iop = 0xe0; uint8_t h264_level_idc = 0x1f; + char append[64] = ""; (void)offer; if (!mb || !fmt || !vc) @@ -46,6 +47,8 @@ int avcodec_h264_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, conf_get_str(conf_cur(), "avcodec_profile_level_id", profile_level_id, sizeof(profile_level_id)); + conf_get_str(conf_cur(), "video_fmtp_append", + append, sizeof(append)); if (str_isset(profile_level_id)) { struct pl prof; @@ -67,10 +70,11 @@ int avcodec_h264_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, out: return mbuf_printf(mb, "a=fmtp:%s" " %s" - ";profile-level-id=%02x%02x%02x" + ";profile-level-id=%02x%02x%02x%s" "\r\n", fmt->id, vc->variant, - profile_idc, profile_iop, h264_level_idc); + profile_idc, profile_iop, h264_level_idc, + append); } From a7ef276ebb8c4dfe478df4b525bd1edc8d213fe3 Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Thu, 27 Apr 2023 17:00:52 +0200 Subject: [PATCH 24/38] [Fixed] slides video stream management --- include/baresip.h | 1 + src/call.c | 60 +++++++++++++++++++++++++++++++++++++++++++---- src/event.c | 9 ++++--- src/stream.c | 9 +++---- 4 files changed, 67 insertions(+), 12 deletions(-) diff --git a/include/baresip.h b/include/baresip.h index 1d44a232f7..1d1d7ad29b 100644 --- a/include/baresip.h +++ b/include/baresip.h @@ -231,6 +231,7 @@ const char *call_alerturi(const struct call *call); const char *call_diverteruri(const struct call *call); struct audio *call_audio(const struct call *call); struct video *call_video(const struct call *call); +struct video *call_video_bis(const struct call *call); struct list *call_streaml(const struct call *call); struct ua *call_get_ua(const struct call *call); bool call_is_onhold(const struct call *call); diff --git a/src/call.c b/src/call.c index ffd01d99f3..807a582de3 100644 --- a/src/call.c +++ b/src/call.c @@ -36,8 +36,8 @@ struct call { struct call *xcall; /**< Cross ref Transfer call */ struct list streaml; /**< List of mediastreams (struct stream) */ struct audio *audio; /**< Audio stream */ - struct video *video; /**< Video stream */ - struct video *video_bis; /**< Video stream */ + struct video *video; /**< Video main stream */ + struct video *video_bis; /**< Video slides stream */ struct bfcp *bfcp; /**< BFCP */ enum call_state state; /**< Call state */ int32_t adelay; /**< Auto answer delay in ms */ @@ -631,8 +631,19 @@ static void stream_mnatconn_handler(struct stream *strm, void *arg) static void stream_rtpestab_handler(struct stream *strm, void *arg) { struct call *call = arg; + char* content= NULL; + struct sdp_media *m ; MAGIC_CHECK(call); + m = stream_sdpmedia(strm); + content = sdp_media_rattr_apply(m, "content" , NULL, NULL); + + if(0==str_cmp(content, "slides")){ + stream_enable_rtp_timeout(video_strm(call->video_bis), 1000); + video_start_display(call->video_bis, call->peer_uri); + return; + } + ua_event(call->ua, UA_EVENT_CALL_RTPESTAB, call, "%s", sdp_media_name(stream_sdpmedia(strm))); } @@ -651,8 +662,24 @@ static void stream_rtcp_handler(struct stream *strm, if (call->config_avt.rtp_stats) call_set_xrtpstat(call); - ua_event(call->ua, UA_EVENT_CALL_RTCP, call, - "%s", sdp_media_name(stream_sdpmedia(strm))); + struct sdp_media *m ; + struct le *le; + int err; + char *content = NULL; + + m = stream_sdpmedia(strm); + content = sdp_media_rattr_apply(m, "content" , NULL, NULL); + + if( str_cmp(sdp_media_name(stream_sdpmedia(strm)), + "video") == 0) { + ua_event(call->ua, UA_EVENT_CALL_RTCP, call, + "%s-%s", sdp_media_name(stream_sdpmedia(strm)), + content?content:"unknown"); + } + else{ + ua_event(call->ua, UA_EVENT_CALL_RTCP, call, + "%s", sdp_media_name(stream_sdpmedia(strm))); + } break; case RTCP_APP: @@ -666,8 +693,18 @@ static void stream_rtcp_handler(struct stream *strm, static void stream_error_handler(struct stream *strm, int err, void *arg) { struct call *call = arg; + char* content= NULL; + struct sdp_media *m ; MAGIC_CHECK(call); + m = stream_sdpmedia(strm); + content = sdp_media_rattr_apply(m, "content" , NULL, NULL); + + if(0==str_cmp(content, "slides")){ + video_stop_display(call->video_bis); + return; + } + info("call: error in \"%s\" rtp stream (%m)\n", sdp_media_name(stream_sdpmedia(strm)), err); @@ -2715,7 +2752,7 @@ struct audio *call_audio(const struct call *call) /** - * Get the video object for the current call + * Get the main video object for the current call * * @param call Call object * @@ -2727,6 +2764,19 @@ struct video *call_video(const struct call *call) } +/** + * Get the slides video object for the current call + * + * @param call Call object + * + * @return Video object + */ +struct video *call_video_bis(const struct call *call) +{ + return call ? call->video_bis : NULL; +} + + /** * Get the list of media streams for the current call * diff --git a/src/event.c b/src/event.c index 466869ee93..34c88dd02c 100644 --- a/src/event.c +++ b/src/event.c @@ -229,9 +229,12 @@ int event_encode_dict(struct odict *od, struct ua *ua, enum ua_event ev, if (0 == str_casecmp(prm, "audio")) strm = audio_strm(call_audio(call)); - else if (0 == str_casecmp(prm, "video")) - strm = video_strm(call_video(call)); - + else if (NULL != strcasestr(prm, "video")){ + if (NULL != strcasestr(prm, "main")) + strm = video_strm(call_video(call)); + if (NULL != strcasestr(prm, "slides")) + strm = video_strm(call_video_bis(call)); + } err = add_rtcp_stats(od, stream_rtcp_stats(strm)); if (err) goto out; diff --git a/src/stream.c b/src/stream.c index 570be7e0aa..fa08f8b39f 100644 --- a/src/stream.c +++ b/src/stream.c @@ -206,7 +206,8 @@ static void stream_close(struct stream *strm, int err) stream_error_h *errorh = strm->errorh; strm->terminated = true; - strm->errorh = NULL; + //strm->errorh = NULL; + strm->rx.rtp_estab = false; jbuf_flush(strm->rx.jbuf); if (errorh) @@ -232,7 +233,7 @@ static void check_rtp_handler(void *arg) /* We are in sendrecv mode, check when the last RTP packet * was received. */ - if (sdp_media_dir(strm->sdp) == SDP_SENDRECV) { + if (sdp_media_dir(strm->sdp) & SDP_RECVONLY) { diff_ms = (int)(now - strm->rx.ts_last); @@ -1156,8 +1157,8 @@ void stream_enable_rtp_timeout(struct stream *strm, uint32_t timeout_ms) if (!strm) return; - if (!sdp_media_has_media(stream_sdpmedia(strm))) - return; + //if (!sdp_media_has_media(stream_sdpmedia(strm))) + // return; strm->rx.rtp_timeout = timeout_ms; From a91b6b4726be13c9d49bf026c4159e1c0e98807b Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Thu, 27 Apr 2023 17:43:18 +0200 Subject: [PATCH 25/38] [Removed] UA_EVENT_CALL_BFCP --- include/baresip.h | 1 - src/bfcp.c | 14 +++++--------- src/call.c | 1 - src/core.h | 1 - src/event.c | 1 - 5 files changed, 5 insertions(+), 13 deletions(-) diff --git a/include/baresip.h b/include/baresip.h index 1d1d7ad29b..2e383feb02 100644 --- a/include/baresip.h +++ b/include/baresip.h @@ -812,7 +812,6 @@ enum ua_event { UA_EVENT_CALL_DTMF_END, UA_EVENT_CALL_RTPESTAB, UA_EVENT_CALL_RTCP, - UA_EVENT_CALL_BFCP, UA_EVENT_CALL_MENC, UA_EVENT_VU_TX, UA_EVENT_VU_RX, diff --git a/src/bfcp.c b/src/bfcp.c index f6eaf1cc64..be4ca40377 100644 --- a/src/bfcp.c +++ b/src/bfcp.c @@ -10,7 +10,6 @@ struct bfcp { - struct ua *ua; struct bfcp_conn *conn; struct sdp_media *sdpm; const struct mnat *mnat; @@ -160,7 +159,6 @@ static void bfcp_msg_handler(const struct bfcp_msg *msg, void *arg) supprim.primc = sizeof(prim)/sizeof(prim[0]); supattr.attrv = attrib; supattr.attrc = sizeof(attrib)/sizeof(attrib[0]); - ua_event(bfcp->ua, UA_EVENT_CALL_BFCP, NULL, "BFCP_HELLO"); (void)bfcp_reply(bfcp->conn, msg, BFCP_HELLO_ACK, 2, BFCP_SUPPORTED_ATTRS, 0, &supattr, @@ -168,7 +166,6 @@ static void bfcp_msg_handler(const struct bfcp_msg *msg, void *arg) break; case BFCP_FLOOR_REQUEST: - ua_event(bfcp->ua, UA_EVENT_CALL_BFCP, NULL, "BFCP_FLOOR_REQUEST"); attr = bfcp_msg_attr(msg, BFCP_FLOOR_ID); uint16_t attr_val = attr->v.u16; uint16_t floor_request_id = 1; @@ -184,7 +181,9 @@ static void bfcp_msg_handler(const struct bfcp_msg *msg, void *arg) break; case BFCP_FLOOR_RELEASE: - ua_event(bfcp->ua, UA_EVENT_CALL_BFCP, NULL, "BFCP_FLOOR_RELEASE"); + break; + + case BFCP_HELLO_ACK: break; default: @@ -203,7 +202,6 @@ static void mnat_connected_handler(const struct sa *raddr1, } int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess, - struct ua *ua, const struct config_bfcp *bfcp_cfg, bool offerer, const struct mnat *mnat, struct mnat_sess *mnat_sess) { @@ -212,7 +210,7 @@ int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess, enum bfcp_transp transp; int err; - if (!bfcpp || !sdp_sess || !ua) + if (!bfcpp || !sdp_sess) return EINVAL; transp = str2tp(bfcp_cfg->proto); @@ -222,10 +220,8 @@ int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess, return ENOMEM; bfcp->active = offerer; - bfcp->ua = ua; sa_init(&laddr, AF_INET); - //sa_set_port(&laddr, 5050); err = bfcp_listen(&bfcp->conn, transp, &laddr, uag_tls(), NULL, NULL, bfcp_msg_handler, NULL, bfcp); @@ -248,7 +244,7 @@ int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess, err |= sdp_media_set_lattr(bfcp->sdpm, true, "setup", bfcp->active ? "active" : "actpass"); - if (/*bfcp->active*/false) { + if (bfcp->active) { err |= sdp_media_set_lattr(bfcp->sdpm, true, "connection", "new"); } diff --git a/src/call.c b/src/call.c index 807a582de3..2db191e96d 100644 --- a/src/call.c +++ b/src/call.c @@ -923,7 +923,6 @@ int call_streams_alloc(struct call *call) if (str_isset(call->cfg->bfcp.proto)) { err = bfcp_alloc(&call->bfcp, call->sdp, - call->ua, &call->cfg->bfcp, !call->got_offer, acc->mnat, call->mnats); if (err) diff --git a/src/core.h b/src/core.h index 8065d2f03d..9b2825c97f 100644 --- a/src/core.h +++ b/src/core.h @@ -111,7 +111,6 @@ void audio_sdp_attr_decode(struct audio *a); struct bfcp; int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess, - struct ua *ua, const struct config_bfcp *bfcp_cfg, bool offerer, const struct mnat *mnat, struct mnat_sess *mnat_sess); int bfcp_start(struct bfcp *bfcp); diff --git a/src/event.c b/src/event.c index 34c88dd02c..922dbdcd80 100644 --- a/src/event.c +++ b/src/event.c @@ -435,7 +435,6 @@ const char *uag_event_str(enum ua_event ev) case UA_EVENT_CALL_DTMF_END: return "CALL_DTMF_END"; case UA_EVENT_CALL_RTPESTAB: return "CALL_RTPESTAB"; case UA_EVENT_CALL_RTCP: return "CALL_RTCP"; - case UA_EVENT_CALL_BFCP: return "CALL_BFCP"; case UA_EVENT_CALL_MENC: return "CALL_MENC"; case UA_EVENT_VU_TX: return "VU_TX_REPORT"; case UA_EVENT_VU_RX: return "VU_RX_REPORT"; From 228e4bcb0e60528906dd1f63ef0463a174fb84f9 Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Thu, 27 Apr 2023 18:57:46 +0200 Subject: [PATCH 26/38] [Added] UA_EVENT_CALL_VIDEO_DISP --- include/baresip.h | 1 + src/call.c | 2 ++ src/stream.c | 1 + 3 files changed, 4 insertions(+) diff --git a/include/baresip.h b/include/baresip.h index 2e383feb02..19f72d68e1 100644 --- a/include/baresip.h +++ b/include/baresip.h @@ -812,6 +812,7 @@ enum ua_event { UA_EVENT_CALL_DTMF_END, UA_EVENT_CALL_RTPESTAB, UA_EVENT_CALL_RTCP, + UA_EVENT_CALL_VIDEO_DISP, UA_EVENT_CALL_MENC, UA_EVENT_VU_TX, UA_EVENT_VU_RX, diff --git a/src/call.c b/src/call.c index 2db191e96d..6e7ec7de11 100644 --- a/src/call.c +++ b/src/call.c @@ -641,6 +641,7 @@ static void stream_rtpestab_handler(struct stream *strm, void *arg) if(0==str_cmp(content, "slides")){ stream_enable_rtp_timeout(video_strm(call->video_bis), 1000); video_start_display(call->video_bis, call->peer_uri); + ua_event(call->ua, UA_EVENT_CALL_VIDEO_DISP, NULL, "VIDEO_SLIDES_START"); return; } @@ -702,6 +703,7 @@ static void stream_error_handler(struct stream *strm, int err, void *arg) if(0==str_cmp(content, "slides")){ video_stop_display(call->video_bis); + ua_event(call->ua, UA_EVENT_CALL_VIDEO_DISP, NULL, "VIDEO_SLIDES_STOP"); return; } diff --git a/src/stream.c b/src/stream.c index fa08f8b39f..0abf481c88 100644 --- a/src/stream.c +++ b/src/stream.c @@ -253,6 +253,7 @@ static void check_rtp_handler(void *arg) sdp_media_name(strm->sdp), diff_ms); stream_close(strm, ETIMEDOUT); + tmr_cancel(&strm->rx.tmr_rtp); } } else { From e6093d2233c4137a557ee385d71671116f0cea85 Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Thu, 11 May 2023 18:56:55 +0200 Subject: [PATCH 27/38] [Fixed] UA_EVENT_CALL_VIDEO_DISP --- src/event.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/event.c b/src/event.c index 922dbdcd80..91cfc6a5d5 100644 --- a/src/event.c +++ b/src/event.c @@ -435,6 +435,7 @@ const char *uag_event_str(enum ua_event ev) case UA_EVENT_CALL_DTMF_END: return "CALL_DTMF_END"; case UA_EVENT_CALL_RTPESTAB: return "CALL_RTPESTAB"; case UA_EVENT_CALL_RTCP: return "CALL_RTCP"; + case UA_EVENT_CALL_VIDEO_DISP: return "VIDEO_DISP"; case UA_EVENT_CALL_MENC: return "CALL_MENC"; case UA_EVENT_VU_TX: return "VU_TX_REPORT"; case UA_EVENT_VU_RX: return "VU_RX_REPORT"; From 10c70312f435aeefd82ba3a0f8f29fb9da7cc4e4 Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Fri, 26 May 2023 18:02:40 +0200 Subject: [PATCH 28/38] [Added] video slides configuration --- include/baresip.h | 2 ++ modules/menu/static_menu.c | 15 +++++---- src/bfcp.c | 47 +++++++++++++++++--------- src/call.c | 23 ++++++------- src/config.c | 68 +++++++++++++++++++++++++++++++++++++- src/stream.c | 2 +- src/video.c | 8 +++-- 7 files changed, 126 insertions(+), 39 deletions(-) diff --git a/include/baresip.h b/include/baresip.h index 19f72d68e1..810ff68682 100644 --- a/include/baresip.h +++ b/include/baresip.h @@ -416,6 +416,8 @@ struct config { struct config_audio audio; struct config_video video; + struct config_video slides; + struct config_avt avt; struct config_net net; diff --git a/modules/menu/static_menu.c b/modules/menu/static_menu.c index 44ca3cf11f..944bdc6854 100644 --- a/modules/menu/static_menu.c +++ b/modules/menu/static_menu.c @@ -1299,7 +1299,7 @@ static int switch_video_source(struct re_printf *pf, void *arg) { const struct cmd_arg *carg = arg; struct pl pl_driver, pl_device; - struct config_video *vidcfg; + struct config_video *vidcfg, *slidescfg; struct config *cfg; struct video *v; const struct vidsrc *vs; @@ -1344,10 +1344,8 @@ static int switch_video_source(struct re_printf *pf, void *arg) return EINVAL; } - vidcfg = &cfg->video; - - str_ncpy(vidcfg->src_mod, driver, sizeof(vidcfg->src_mod)); - str_ncpy(vidcfg->src_dev, device, sizeof(vidcfg->src_dev)); + vidcfg= &cfg->video; + slidescfg = &cfg->slides; for (leu = list_head(uag_list()); leu; leu = leu->next) { struct ua *ua = leu->data; @@ -1356,8 +1354,11 @@ static int switch_video_source(struct re_printf *pf, void *arg) struct call *call = le->data; v = call_video(call); - - err = video_set_source(v, driver, device); + err = video_set_source(v, vidcfg->src_mod, + vidcfg->src_dev); + v = call_video_bis(call); + err |= video_set_source(v, slidescfg->src_mod, + slidescfg->src_dev); if (err) { (void)re_hprintf(pf, "failed to set video-source" diff --git a/src/bfcp.c b/src/bfcp.c index be4ca40377..f56a833733 100644 --- a/src/bfcp.c +++ b/src/bfcp.c @@ -15,6 +15,7 @@ struct bfcp { const struct mnat *mnat; struct mnat_media *mnat_st; bool active; + struct tmr tmr_hello; /* server */ uint32_t lconfid; @@ -29,6 +30,8 @@ static void destructor(void *arg) { struct bfcp *bfcp = arg; + tmr_cancel(&bfcp->tmr_hello); + mem_deref(bfcp->mnat_st); mem_deref(bfcp->sdpm); mem_deref(bfcp->conn); @@ -222,6 +225,7 @@ int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess, bfcp->active = offerer; sa_init(&laddr, AF_INET); + tmr_init(&bfcp->tmr_hello); err = bfcp_listen(&bfcp->conn, transp, &laddr, uag_tls(), NULL, NULL, bfcp_msg_handler, NULL, bfcp); @@ -279,6 +283,7 @@ int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess, goto out; } + info("bfcp: %s BFCP agent protocol '%s' on port %d\n", bfcp->active ? "Active" : "Passive", bfcp_cfg->proto, sa_port(&laddr)); @@ -292,13 +297,36 @@ int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess, return err; } - -int bfcp_start(struct bfcp *bfcp) +int bfcp_send_hello(struct bfcp *bfcp) { const struct sa *paddr; uint32_t confid = 0; uint16_t userid = 0; int err = 0; + + tmr_start(&bfcp->tmr_hello, 10000,bfcp_send_hello, bfcp); + + paddr = sdp_media_raddr(bfcp->sdpm); + confid = 1; + if(sdp_media_rattr(bfcp->sdpm, "confid")) + confid = atoi(sdp_media_rattr(bfcp->sdpm, "confid")); + + userid = 1; + if(sdp_media_rattr(bfcp->sdpm, "userid")) + userid = atoi(sdp_media_rattr(bfcp->sdpm, "userid")); + + uint16_t floor_id = 1; + err = bfcp_request(bfcp->conn, paddr, BFCP_VER1, BFCP_HELLO, + confid, userid, bfcp_resp_handler, bfcp, 1, + BFCP_FLOOR_ID, 0, &floor_id); + + return err; + +} + +int bfcp_start(struct bfcp *bfcp) +{ + int err = 0; char *floorctrl; if (!bfcp) @@ -313,20 +341,7 @@ int bfcp_start(struct bfcp *bfcp) if (floorctrl ) if (str_str(floorctrl, "s")) { - - paddr = sdp_media_raddr(bfcp->sdpm); - confid = 1; - if(sdp_media_rattr(bfcp->sdpm, "confid")) - confid = atoi(sdp_media_rattr(bfcp->sdpm, "confid")); - - userid = 1; - if(sdp_media_rattr(bfcp->sdpm, "userid")) - userid = atoi(sdp_media_rattr(bfcp->sdpm, "userid")); - - uint16_t floor_id = 1; - err = bfcp_request(bfcp->conn, paddr, BFCP_VER1, BFCP_HELLO, - confid, userid, bfcp_resp_handler, bfcp, 1, - BFCP_FLOOR_ID, 0, &floor_id); + bfcp_send_hello(bfcp); } return err; diff --git a/src/call.c b/src/call.c index 6e7ec7de11..514844b64b 100644 --- a/src/call.c +++ b/src/call.c @@ -910,20 +910,19 @@ int call_streams_alloc(struct call *call) if (err) return err; - err = video_alloc(&call->video_bis, &call->streaml, &strm_prm, - call->cfg, call->sdp, - acc->mnat, call->mnats, - acc->menc, call->mencs, - "slides", - account_vidcodecl(call->acc), - baresip_vidfiltl(), !call->got_offer, - video_error_handler, call); - stream_set_ldir(video_strm(call->video_bis), SDP_RECVONLY); + if (str_isset(call->cfg->bfcp.proto)) { + err = video_alloc(&call->video_bis, &call->streaml, &strm_prm, + call->cfg, call->sdp, + acc->mnat, call->mnats, + acc->menc, call->mencs, + "slides", + account_vidcodecl(call->acc), + baresip_vidfiltl(), !call->got_offer, + video_error_handler, call); - if (err) - return err; + if (err) + return err; - if (str_isset(call->cfg->bfcp.proto)) { err = bfcp_alloc(&call->bfcp, call->sdp, &call->cfg->bfcp, !call->got_offer, acc->mnat, call->mnats); diff --git a/src/config.c b/src/config.c index b908b7307e..9de5ac8274 100644 --- a/src/config.c +++ b/src/config.c @@ -68,7 +68,18 @@ static struct config core_config = { 101 }, - /** Video */ + /** Video main */ + { + "", "", + "", "", + 640, 480, + 1000000, + 30, + true, + VID_FMT_YUV420P, + }, + + /** Video slides */ { "", "", "", "", @@ -427,6 +438,28 @@ int config_parse_conf(struct config *cfg, const struct conf *conf) conf_get_vidfmt(conf, "videnc_format", &cfg->video.enc_fmt); + /* Slides */ + (void)conf_get_csv(conf, "slides_source", + cfg->slides.src_mod, + sizeof(cfg->slides.src_mod), + cfg->slides.src_dev, + sizeof(cfg->slides.src_dev)); + (void)conf_get_csv(conf, "slides_display", + cfg->slides.disp_mod, + sizeof(cfg->slides.disp_mod), + cfg->slides.disp_dev, + sizeof(cfg->slides.disp_dev)); + if (0 == conf_get_vidsz(conf, "slides_size", &size)) { + cfg->slides.width = size.w; + cfg->slides.height = size.h; + } + (void)conf_get_u32(conf, "slides_bitrate", &cfg->slides.bitrate); + (void)conf_get_float(conf, "slides_fps", &cfg->slides.fps); + (void)conf_get_bool(conf, "slides_fullscreen", + &cfg->slides.fullscreen); + + conf_get_vidfmt(conf, "slidenc_format", &cfg->slides.enc_fmt); + /* AVT - Audio/Video Transport */ if (0 == conf_get_u32(conf, "rtp_tos", &v)) cfg->avt.rtp_tos = v; @@ -534,6 +567,16 @@ int config_print(struct re_printf *pf, const struct config *cfg) "video_fullscreen\t%s\n" "videnc_format\t\t%s\n" "\n" + "# Slides\n" + "slides_source\t\t%s,%s\n" + "#slides_source\t\tavformat,rtmp://127.0.0.1/app/foo\n" + "slides_display\t\t%s,%s\n" + "slides_size\t\t\"%ux%u\"\n" + "slides_bitrate\t\t%u\n" + "slides_fps\t\t%.2f\n" + "slides_fullscreen\t%s\n" + "slidenc_format\t\t%s\n" + "\n" "# AVT\n" "rtp_tos\t\t\t%u\n" "rtp_video_tos\t\t%u\n" @@ -590,6 +633,13 @@ int config_print(struct re_printf *pf, const struct config *cfg) cfg->video.fullscreen ? "yes" : "no", vidfmt_name(cfg->video.enc_fmt), + cfg->slides.src_mod, cfg->slides.src_dev, + cfg->slides.disp_mod, cfg->slides.disp_dev, + cfg->slides.width, cfg->slides.height, + cfg->slides.bitrate, cfg->slides.fps, + cfg->slides.fullscreen ? "yes" : "no", + vidfmt_name(cfg->slides.enc_fmt), + cfg->avt.rtp_tos, cfg->avt.rtpv_tos, range_print, &cfg->avt.rtp_ports, @@ -788,6 +838,22 @@ static int core_config_template(struct re_printf *pf, const struct config *cfg) cfg->video.bitrate, cfg->video.fps, vidfmt_name(cfg->video.enc_fmt)); + err |= re_hprintf(pf, + "\n# Slides\n" + "#slides_source\t\t%s\n" + "#slides_display\t\t%s\n" + "slides_size\t\t%dx%d\n" + "slides_bitrate\t\t%u\n" + "slides_fps\t\t%.2f\n" + "slides_fullscreen\tno\n" + "slides_format\t\t%s\n" + , + default_video_device(), + default_video_display(), + cfg->slides.width, cfg->slides.height, + cfg->slides.bitrate, cfg->slides.fps, + vidfmt_name(cfg->slides.enc_fmt)); + err |= re_hprintf(pf, "\n# AVT - Audio/Video Transport\n" "rtp_tos\t\t\t184\n" diff --git a/src/stream.c b/src/stream.c index 0abf481c88..35dd6beae6 100644 --- a/src/stream.c +++ b/src/stream.c @@ -205,7 +205,7 @@ static void stream_close(struct stream *strm, int err) { stream_error_h *errorh = strm->errorh; - strm->terminated = true; + //strm->terminated = true; //strm->errorh = NULL; strm->rx.rtp_estab = false; jbuf_flush(strm->rx.jbuf); diff --git a/src/video.c b/src/video.c index e0caa1ae06..6d443acd0b 100644 --- a/src/video.c +++ b/src/video.c @@ -1023,7 +1023,11 @@ int video_alloc(struct video **vp, struct list *streaml, MAGIC_INIT(v); - v->cfg = cfg->video; + if (NULL != strcasestr(content, "slides")) + v->cfg = cfg->slides; + else + v->cfg = cfg->video; + tmr_init(&v->tmr); err = stream_alloc(&v->strm, streaml, stream_prm, @@ -1473,7 +1477,7 @@ int video_encoder_set(struct video *v, struct vidcodec *vc, prm.bitrate = v->cfg.bitrate; prm.pktsize = 1280; - prm.fps = get_fps(v); + prm.fps = max(1.00, get_fps(v)); prm.max_fs = -1; info("Set video encoder: %s %s (%u bit/s, %.2f fps)\n", From c540262f49d50283b923e922f8f225fc00890e60 Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Wed, 31 May 2023 16:58:55 +0200 Subject: [PATCH 29/38] [Added] media_stream parameter to picture_fast_update requests --- include/baresip.h | 3 ++- src/call.c | 22 ++++++++++++---------- src/video.c | 24 +++++++++++++++++------- 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/include/baresip.h b/include/baresip.h index 810ff68682..0de785cfe8 100644 --- a/include/baresip.h +++ b/include/baresip.h @@ -205,7 +205,8 @@ int call_modify(struct call *call); int call_hold(struct call *call, bool hold); int call_set_video_dir(struct call *call, enum sdp_dir dir); int call_send_digit(struct call *call, char key); -int call_send_pfu(struct call *call); +int call_send_pfu(struct call *call, const char* content, + const char* label); bool call_has_audio(const struct call *call); bool call_has_video(const struct call *call); bool call_early_video_available(const struct call *call); diff --git a/src/call.c b/src/call.c index 514844b64b..1b8ea514de 100644 --- a/src/call.c +++ b/src/call.c @@ -632,11 +632,9 @@ static void stream_rtpestab_handler(struct stream *strm, void *arg) { struct call *call = arg; char* content= NULL; - struct sdp_media *m ; MAGIC_CHECK(call); - m = stream_sdpmedia(strm); - content = sdp_media_rattr_apply(m, "content" , NULL, NULL); + content = sdp_media_rattr(stream_sdpmedia(strm), "content"); if(0==str_cmp(content, "slides")){ stream_enable_rtp_timeout(video_strm(call->video_bis), 1000); @@ -668,8 +666,7 @@ static void stream_rtcp_handler(struct stream *strm, int err; char *content = NULL; - m = stream_sdpmedia(strm); - content = sdp_media_rattr_apply(m, "content" , NULL, NULL); + content = sdp_media_rattr(stream_sdpmedia(strm), "content"); if( str_cmp(sdp_media_name(stream_sdpmedia(strm)), "video") == 0) { @@ -695,11 +692,9 @@ static void stream_error_handler(struct stream *strm, int err, void *arg) { struct call *call = arg; char* content= NULL; - struct sdp_media *m ; MAGIC_CHECK(call); - m = stream_sdpmedia(strm); - content = sdp_media_rattr_apply(m, "content" , NULL, NULL); + content = sdp_media_rattr(stream_sdpmedia(strm), "content"); if(0==str_cmp(content, "slides")){ video_stop_display(call->video_bis); @@ -1858,22 +1853,29 @@ int call_send_digit(struct call *call, char key) * * @return 0 if success, otherwise errorcode */ -int call_send_pfu(struct call *call) +int call_send_pfu(struct call *call, const char* content, const char* label) { + char media_strm[128] = ""; int err = 0; if (!call) return EINVAL; + if(0==str_cmp(content, "slides")){ + re_snprintf(media_strm, sizeof(media_strm), + "%s", label); + } + err = send_info(call->sess, "application/media_control+xml", "" "" "" + "%s" "" "", send_pfu_info_handler, - NULL, NULL); + NULL, media_strm); if (err) { warning("call: picture_fast_update request failed (%m)\n", err); } diff --git a/src/video.c b/src/video.c index 6d443acd0b..7f544214ee 100644 --- a/src/video.c +++ b/src/video.c @@ -611,7 +611,8 @@ static void send_fir(struct stream *s, bool pli) { struct call *cur_call; struct ua *local_ua ; - char *local_uri; + char *local_uri, *label; + char* content= NULL; bool sip_media_control=false; struct config *cur_conf; int err; @@ -638,17 +639,26 @@ static void send_fir(struct stream *s, bool pli) if (local_ua) cur_call = ua_call(local_ua); - if (cur_call) - err = call_send_pfu(cur_call); + if (cur_call){ + content = sdp_media_rattr(stream_sdpmedia(s), + "content"); + label = sdp_media_rattr(stream_sdpmedia(s), + "label"); + err = call_send_pfu(cur_call, content, + label); + } if (err) - warning("video: failed to send picture_fast_update %m\n", err); + warning("video: failed to send " + "picture_fast_update %m\n", err); } else { - err = rtcp_send_fir(stream_rtp_sock(s), - rtp_sess_ssrc(stream_rtp_sock(s))); + err = rtcp_send_fir( + stream_rtp_sock(s), + rtp_sess_ssrc(stream_rtp_sock(s))); if (err) - warning("video: failed to send FIR %m\n", err); + warning("video: failed to send FIR %m\n", + err); } } } From a5c9d71ebaafcb6280f6332beb0a628f8f6dff73 Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Wed, 31 May 2023 18:25:57 +0200 Subject: [PATCH 30/38] [Fixed] 'video_bis' to 'slides' renaming --- include/baresip.h | 2 +- modules/menu/static_menu.c | 2 +- src/call.c | 74 ++++++++++++++++++++------------------ src/event.c | 2 +- 4 files changed, 42 insertions(+), 38 deletions(-) diff --git a/include/baresip.h b/include/baresip.h index 0de785cfe8..d19dbc70fd 100644 --- a/include/baresip.h +++ b/include/baresip.h @@ -232,7 +232,7 @@ const char *call_alerturi(const struct call *call); const char *call_diverteruri(const struct call *call); struct audio *call_audio(const struct call *call); struct video *call_video(const struct call *call); -struct video *call_video_bis(const struct call *call); +struct video *call_slides(const struct call *call); struct list *call_streaml(const struct call *call); struct ua *call_get_ua(const struct call *call); bool call_is_onhold(const struct call *call); diff --git a/modules/menu/static_menu.c b/modules/menu/static_menu.c index 944bdc6854..517e4935ad 100644 --- a/modules/menu/static_menu.c +++ b/modules/menu/static_menu.c @@ -1356,7 +1356,7 @@ static int switch_video_source(struct re_printf *pf, void *arg) v = call_video(call); err = video_set_source(v, vidcfg->src_mod, vidcfg->src_dev); - v = call_video_bis(call); + v = call_slides(call); err |= video_set_source(v, slidescfg->src_mod, slidescfg->src_dev); if (err) { diff --git a/src/call.c b/src/call.c index 1b8ea514de..f96ca82eef 100644 --- a/src/call.c +++ b/src/call.c @@ -37,7 +37,7 @@ struct call { struct list streaml; /**< List of mediastreams (struct stream) */ struct audio *audio; /**< Audio stream */ struct video *video; /**< Video main stream */ - struct video *video_bis; /**< Video slides stream */ + struct video *slides; /**< Video slides stream */ struct bfcp *bfcp; /**< BFCP */ enum call_state state; /**< Call state */ int32_t adelay; /**< Auto answer delay in ms */ @@ -215,18 +215,19 @@ static void call_stream_start(struct call *call, bool active) warning("call: could not start video: %m\n", err); } } - if (stream_is_ready(video_strm(call->video_bis))) { - err = video_update(call->video_bis, call->peer_uri); - if (err) { - warning("call: could not start video bis: %m\n", err); - } - } if (call->bfcp) { err = bfcp_start(call->bfcp); if (err) { warning("call: could not start BFCP: %m\n", err); } + if (stream_is_ready(video_strm(call->slides))) { + err = video_update(call->slides, call->peer_uri); + if (err) { + warning("call: could not start slides: %m\n", + err); + } + } } if (active) { @@ -257,7 +258,7 @@ static void call_stream_stop(struct call *call) /* Video */ video_stop(call->video); - video_stop(call->video_bis); + video_stop(call->slides); tmr_cancel(&call->tmr_inv); } @@ -385,8 +386,8 @@ static int update_media(struct call *call) if (call->video) video_sdp_attr_decode(call->video); - if (call->video_bis) - video_sdp_attr_decode(call->video_bis); + if (call->slides) + video_sdp_attr_decode(call->slides); /* Update each stream */ FOREACH_STREAM { @@ -411,10 +412,10 @@ static int update_media(struct call *call) else video_stop(call->video); - if (stream_is_ready(video_strm(call->video_bis))) - err |= video_update(call->video_bis, call->peer_uri); + if (stream_is_ready(video_strm(call->slides))) + err |= video_update(call->slides, call->peer_uri); else - video_stop(call->video_bis); + video_stop(call->slides); return err; } @@ -455,7 +456,7 @@ static void call_destructor(void *arg) mem_deref(call->diverter_uri); mem_deref(call->audio); mem_deref(call->video); - mem_deref(call->video_bis); + mem_deref(call->slides); mem_deref(call->bfcp); mem_deref(call->sdp); mem_deref(call->mnats); @@ -548,9 +549,9 @@ static void menc_event_handler(enum menc_event event, warning("call: secure: could not" " start video: %m\n", err); } - stream_set_secure(video_strm(call->video_bis), true); - stream_start_rtcp(video_strm(call->video_bis)); - err = video_update(call->video_bis, call->peer_uri); + stream_set_secure(video_strm(call->slides), true); + stream_start_rtcp(video_strm(call->slides)); + err = video_update(call->slides, call->peer_uri); if (err) { warning("call: secure: could not" " start video: %m\n", err); @@ -616,7 +617,8 @@ static void stream_mnatconn_handler(struct stream *strm, void *arg) case MEDIA_VIDEO: err = video_update(call->video, call->peer_uri); if (err) { - err = video_update(call->video_bis, call->peer_uri); + err = video_update(call->slides, + call->peer_uri); } if (err) { warning("call: mnatconn: could not" @@ -637,9 +639,10 @@ static void stream_rtpestab_handler(struct stream *strm, void *arg) content = sdp_media_rattr(stream_sdpmedia(strm), "content"); if(0==str_cmp(content, "slides")){ - stream_enable_rtp_timeout(video_strm(call->video_bis), 1000); - video_start_display(call->video_bis, call->peer_uri); - ua_event(call->ua, UA_EVENT_CALL_VIDEO_DISP, NULL, "VIDEO_SLIDES_START"); + stream_enable_rtp_timeout(video_strm(call->slides), 1000); + video_start_display(call->slides, call->peer_uri); + ua_event(call->ua, UA_EVENT_CALL_VIDEO_DISP, NULL, + "VIDEO_SLIDES_START"); return; } @@ -697,7 +700,7 @@ static void stream_error_handler(struct stream *strm, int err, void *arg) content = sdp_media_rattr(stream_sdpmedia(strm), "content"); if(0==str_cmp(content, "slides")){ - video_stop_display(call->video_bis); + video_stop_display(call->slides); ua_event(call->ua, UA_EVENT_CALL_VIDEO_DISP, NULL, "VIDEO_SLIDES_STOP"); return; } @@ -906,13 +909,15 @@ int call_streams_alloc(struct call *call) return err; if (str_isset(call->cfg->bfcp.proto)) { - err = video_alloc(&call->video_bis, &call->streaml, &strm_prm, + err = video_alloc(&call->slides, &call->streaml, + &strm_prm, call->cfg, call->sdp, acc->mnat, call->mnats, acc->menc, call->mencs, "slides", account_vidcodecl(call->acc), - baresip_vidfiltl(), !call->got_offer, + baresip_vidfiltl(), + !call->got_offer, video_error_handler, call); if (err) @@ -1457,11 +1462,10 @@ int call_answer(struct call *call, uint16_t scode, enum vidmode vmode) return 0; } - if (vmode == VIDMODE_OFF) + if (vmode == VIDMODE_OFF){ call->video = mem_deref(call->video); - - if (vmode == VIDMODE_OFF) - call->video_bis = mem_deref(call->video); + call->slides = mem_deref(call->slides); + } info("call: answering call on line %u from %s with %u\n", call->linenum, call->peer_uri, scode); @@ -1535,7 +1539,7 @@ bool call_has_video(const struct call *call) return false; return sdp_media_has_media(stream_sdpmedia(video_strm(call->video))) || - sdp_media_has_media(stream_sdpmedia(video_strm(call->video_bis))) ; + sdp_media_has_media(stream_sdpmedia(video_strm(call->slides))) ; } @@ -1776,8 +1780,8 @@ int call_status(struct re_printf *pf, const struct call *call) if (call->video) err |= video_print(pf, call->video); - if (call->video_bis) - err |= video_print(pf, call->video_bis); + if (call->slides) + err |= video_print(pf, call->slides); /* remove old junk */ err |= re_hprintf(pf, " "); @@ -2302,7 +2306,7 @@ static bool have_common_video_codecs(const struct call *call) sc = sdp_media_rcodec(stream_sdpmedia(video_strm(call->video))); if (!sc) - sc = sdp_media_rcodec(stream_sdpmedia(video_strm(call->video_bis))); + sc = sdp_media_rcodec(stream_sdpmedia(video_strm(call->slides))); if (!sc) return false; @@ -2368,7 +2372,7 @@ int call_accept(struct call *call, struct sipsess_sock *sess_sock, */ if (!valid_addressfamily(call, audio_strm(call->audio)) || !valid_addressfamily(call, video_strm(call->video)) || - !valid_addressfamily(call, video_strm(call->video_bis))){ + !valid_addressfamily(call, video_strm(call->slides))){ sip_treply(NULL, uag_sip(), msg, 488, "Not Acceptable Here"); @@ -2773,9 +2777,9 @@ struct video *call_video(const struct call *call) * * @return Video object */ -struct video *call_video_bis(const struct call *call) +struct video *call_slides(const struct call *call) { - return call ? call->video_bis : NULL; + return call ? call->slides : NULL; } diff --git a/src/event.c b/src/event.c index 91cfc6a5d5..43216f0bc2 100644 --- a/src/event.c +++ b/src/event.c @@ -233,7 +233,7 @@ int event_encode_dict(struct odict *od, struct ua *ua, enum ua_event ev, if (NULL != strcasestr(prm, "main")) strm = video_strm(call_video(call)); if (NULL != strcasestr(prm, "slides")) - strm = video_strm(call_video_bis(call)); + strm = video_strm(call_slides(call)); } err = add_rtcp_stats(od, stream_rtcp_stats(strm)); if (err) From 1e5478967583e5b974e97154b857e4433a6c5dfc Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Thu, 1 Jun 2023 18:41:35 +0200 Subject: [PATCH 31/38] [Added] specific 'check slides stream' logic --- src/call.c | 37 ++++++++++++++++++++++++++----------- src/core.h | 2 ++ src/stream.c | 20 +++++++++++++++----- 3 files changed, 43 insertions(+), 16 deletions(-) diff --git a/src/call.c b/src/call.c index f96ca82eef..eee4ca0fb7 100644 --- a/src/call.c +++ b/src/call.c @@ -54,6 +54,7 @@ struct call { struct tmr tmr_dtmf; /**< Timer for incoming DTMF events */ struct tmr tmr_answ; /**< Timer for delayed answer */ struct tmr tmr_reinv; /**< Timer for outgoing re-INVITES */ + struct tmr tmr_slides; /**< Timer for received slides stream */ time_t time_start; /**< Time when call started */ time_t time_conn; /**< Time when call initiated */ time_t time_stop; /**< Time when call stopped */ @@ -261,6 +262,7 @@ static void call_stream_stop(struct call *call) video_stop(call->slides); tmr_cancel(&call->tmr_inv); + tmr_cancel(&call->tmr_slides); } @@ -630,6 +632,27 @@ static void stream_mnatconn_handler(struct stream *strm, void *arg) } +static void check_slides_stream(struct call *call) +{ + uint64_t rx_ts_last; + const uint64_t now = tmr_jiffies(); + int diff_ms; + + tmr_start(&call->tmr_slides, 1000, check_slides_stream, call); + + rx_ts_last = stream_rx_ts_last(video_strm(call->slides)); + if(rx_ts_last){ + diff_ms = (int)(now - rx_ts_last); + if (diff_ms > 1000){ + video_stop_display(call->slides); + ua_event(call->ua, UA_EVENT_CALL_VIDEO_DISP, NULL, + "VIDEO_SLIDES_STOP"); + video_start_display(call->slides, call->peer_uri); + } + } +} + + static void stream_rtpestab_handler(struct stream *strm, void *arg) { struct call *call = arg; @@ -639,8 +662,7 @@ static void stream_rtpestab_handler(struct stream *strm, void *arg) content = sdp_media_rattr(stream_sdpmedia(strm), "content"); if(0==str_cmp(content, "slides")){ - stream_enable_rtp_timeout(video_strm(call->slides), 1000); - video_start_display(call->slides, call->peer_uri); + tmr_start(&call->tmr_slides, 1000, check_slides_stream, call); ua_event(call->ua, UA_EVENT_CALL_VIDEO_DISP, NULL, "VIDEO_SLIDES_START"); return; @@ -694,17 +716,8 @@ static void stream_rtcp_handler(struct stream *strm, static void stream_error_handler(struct stream *strm, int err, void *arg) { struct call *call = arg; - char* content= NULL; MAGIC_CHECK(call); - content = sdp_media_rattr(stream_sdpmedia(strm), "content"); - - if(0==str_cmp(content, "slides")){ - video_stop_display(call->slides); - ua_event(call->ua, UA_EVENT_CALL_VIDEO_DISP, NULL, "VIDEO_SLIDES_STOP"); - return; - } - info("call: error in \"%s\" rtp stream (%m)\n", sdp_media_name(stream_sdpmedia(strm)), err); @@ -919,6 +932,7 @@ int call_streams_alloc(struct call *call) baresip_vidfiltl(), !call->got_offer, video_error_handler, call); + stream_enable_rtp_timeout(video_strm(call->slides), 0); if (err) return err; @@ -1037,6 +1051,7 @@ int call_alloc(struct call **callp, const struct config *cfg, struct list *lst, tmr_init(&call->tmr_inv); tmr_init(&call->tmr_answ); tmr_init(&call->tmr_reinv); + tmr_init(&call->tmr_slides); call->cfg = cfg; call->acc = mem_ref(acc); diff --git a/src/core.h b/src/core.h index 9b2825c97f..b909283336 100644 --- a/src/core.h +++ b/src/core.h @@ -299,6 +299,8 @@ struct rtp_sock *stream_rtp_sock(const struct stream *strm); const struct sa *stream_raddr(const struct stream *strm); const char *stream_mid(const struct stream *strm); uint8_t stream_generate_extmap_id(struct stream *strm); +uint64_t stream_rx_ts_last(const struct stream *strm); + /* Send */ void stream_update_encoder(struct stream *s, int pt_enc); diff --git a/src/stream.c b/src/stream.c index 35dd6beae6..9579a25f28 100644 --- a/src/stream.c +++ b/src/stream.c @@ -205,8 +205,8 @@ static void stream_close(struct stream *strm, int err) { stream_error_h *errorh = strm->errorh; - //strm->terminated = true; - //strm->errorh = NULL; + strm->terminated = true; + strm->errorh = NULL; strm->rx.rtp_estab = false; jbuf_flush(strm->rx.jbuf); @@ -253,7 +253,6 @@ static void check_rtp_handler(void *arg) sdp_media_name(strm->sdp), diff_ms); stream_close(strm, ETIMEDOUT); - tmr_cancel(&strm->rx.tmr_rtp); } } else { @@ -1158,8 +1157,8 @@ void stream_enable_rtp_timeout(struct stream *strm, uint32_t timeout_ms) if (!strm) return; - //if (!sdp_media_has_media(stream_sdpmedia(strm))) - // return; + if (!sdp_media_has_media(stream_sdpmedia(strm))) + return; strm->rx.rtp_timeout = timeout_ms; @@ -1592,6 +1591,17 @@ const struct sa *stream_raddr(const struct stream *strm) } +uint64_t stream_rx_ts_last(const struct stream *strm) +{ + if (!strm) + return 0; + if (!strm->rx.ts_last) + return 0; + + return strm->rx.ts_last; +} + + enum media_type stream_type(const struct stream *strm) { return strm ? strm->type : (enum media_type)-1; From 068c013fd2c06f4e9e66159e056723da89197d1c Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Tue, 27 Jun 2023 10:51:22 +0200 Subject: [PATCH 32/38] [Added] feedback waiting for Picture Fast Update --- src/call.c | 18 ++++++++++++------ src/video.c | 24 +++++++++++++----------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/call.c b/src/call.c index eee4ca0fb7..ae6cf2e222 100644 --- a/src/call.c +++ b/src/call.c @@ -63,6 +63,7 @@ struct call { bool got_offer; /**< Got SDP Offer from Peer */ bool on_hold; /**< True if call is on hold (local) */ bool early_confirmed; /**< Early media confirmed by PRACK */ + bool pfu_waiting; /**< Waiting for PFU feedback */ struct mnat_sess *mnats; /**< Media NAT session */ bool mnat_wait; /**< Waiting for MNAT to establish */ struct menc_sess *mencs; /**< Media encryption session state */ @@ -1063,6 +1064,7 @@ int call_alloc(struct call **callp, const struct config *cfg, struct list *lst, call->estadir = SDP_SENDRECV; call->estvdir = SDP_SENDRECV; call->use_rtp = prm->use_rtp; + call->pfu_waiting = false; call_decode_sip_autoanswer(call, msg); call_decode_diverter(call, msg); @@ -1880,6 +1882,9 @@ int call_send_pfu(struct call *call, const char* content, const char* label) if (!call) return EINVAL; + if (call->pfu_waiting) + return 1; + if(0==str_cmp(content, "slides")){ re_snprintf(media_strm, sizeof(media_strm), "%s", label); @@ -1894,10 +1899,13 @@ int call_send_pfu(struct call *call, const char* content, const char* label) "" "", send_pfu_info_handler, - NULL, media_strm); + call, media_strm); if (err) { warning("call: picture_fast_update request failed (%m)\n", err); } + + call->pfu_waiting = true; + return err; } @@ -2112,7 +2120,7 @@ static void send_pfu_info_handler(int err, const struct sip_msg *msg, void *arg) { - (void)arg; + struct call *call = arg; struct config *cur_conf; if (err) @@ -2120,11 +2128,9 @@ static void send_pfu_info_handler(int err, else if (msg && msg->scode != 200) { warning("call: sending PICTURE_FAST_UPDATE INFO failed (scode: %d)", msg->scode); - - cur_conf = conf_config(); - if (cur_conf) - cur_conf->sip.media_control = false; } + else + call->pfu_waiting = false; } diff --git a/src/video.c b/src/video.c index 7f544214ee..22d1047a4a 100644 --- a/src/video.c +++ b/src/video.c @@ -648,18 +648,20 @@ static void send_fir(struct stream *s, bool pli) label); } - if (err) - warning("video: failed to send " - "picture_fast_update %m\n", err); - } - else { - err = rtcp_send_fir( - stream_rtp_sock(s), - rtp_sess_ssrc(stream_rtp_sock(s))); - if (err) - warning("video: failed to send FIR %m\n", - err); + if (err){ + info("video: failed to send " + "picture_fast_update\n"); + } + else + return; } + /* Try to send RTCP FIR at last*/ + err = rtcp_send_fir( + stream_rtp_sock(s), + rtp_sess_ssrc(stream_rtp_sock(s))); + if (err) + warning("video: failed to send FIR %m\n", + err); } } From a7116f5a24ccc91f9d3a2c3f2f1fec5cde8a941c Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Tue, 27 Jun 2023 17:18:05 +0200 Subject: [PATCH 33/38] [Fixed] logic of Picture Fast Update requests --- src/call.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/call.c b/src/call.c index ae6cf2e222..b587e6a29f 100644 --- a/src/call.c +++ b/src/call.c @@ -63,7 +63,7 @@ struct call { bool got_offer; /**< Got SDP Offer from Peer */ bool on_hold; /**< True if call is on hold (local) */ bool early_confirmed; /**< Early media confirmed by PRACK */ - bool pfu_waiting; /**< Waiting for PFU feedback */ + bool pfu_disabled; /**< PFU requests disabled */ struct mnat_sess *mnats; /**< Media NAT session */ bool mnat_wait; /**< Waiting for MNAT to establish */ struct menc_sess *mencs; /**< Media encryption session state */ @@ -1064,7 +1064,7 @@ int call_alloc(struct call **callp, const struct config *cfg, struct list *lst, call->estadir = SDP_SENDRECV; call->estvdir = SDP_SENDRECV; call->use_rtp = prm->use_rtp; - call->pfu_waiting = false; + call->pfu_disabled = false; call_decode_sip_autoanswer(call, msg); call_decode_diverter(call, msg); @@ -1882,7 +1882,7 @@ int call_send_pfu(struct call *call, const char* content, const char* label) if (!call) return EINVAL; - if (call->pfu_waiting) + if (call->pfu_disabled) return 1; if(0==str_cmp(content, "slides")){ @@ -1904,7 +1904,7 @@ int call_send_pfu(struct call *call, const char* content, const char* label) warning("call: picture_fast_update request failed (%m)\n", err); } - call->pfu_waiting = true; + call->pfu_disabled = true; return err; } @@ -2129,8 +2129,9 @@ static void send_pfu_info_handler(int err, warning("call: sending PICTURE_FAST_UPDATE INFO failed (scode: %d)", msg->scode); } - else - call->pfu_waiting = false; + + if (msg->scode == 200 || msg->scode == 408) + call->pfu_disabled = false; } From 5a35c35c18fef8986ac03814517faa9fed2ddfce Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Wed, 28 Jun 2023 17:16:28 +0200 Subject: [PATCH 34/38] [Fixed] slides video stream management --- src/call.c | 12 +++++++++--- src/stream.c | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/call.c b/src/call.c index b587e6a29f..459bd3b88a 100644 --- a/src/call.c +++ b/src/call.c @@ -64,6 +64,7 @@ struct call { bool on_hold; /**< True if call is on hold (local) */ bool early_confirmed; /**< Early media confirmed by PRACK */ bool pfu_disabled; /**< PFU requests disabled */ + bool slides_displayed; /**< Ture if slides are being displayed */ struct mnat_sess *mnats; /**< Media NAT session */ bool mnat_wait; /**< Waiting for MNAT to establish */ struct menc_sess *mencs; /**< Media encryption session state */ @@ -644,12 +645,18 @@ static void check_slides_stream(struct call *call) rx_ts_last = stream_rx_ts_last(video_strm(call->slides)); if(rx_ts_last){ diff_ms = (int)(now - rx_ts_last); - if (diff_ms > 1000){ + if (diff_ms > 1000 && call->slides_displayed){ video_stop_display(call->slides); + call->slides_displayed = false; ua_event(call->ua, UA_EVENT_CALL_VIDEO_DISP, NULL, "VIDEO_SLIDES_STOP"); video_start_display(call->slides, call->peer_uri); } + if (diff_ms < 1000 && !call->slides_displayed){ + call->slides_displayed = true; + ua_event(call->ua, UA_EVENT_CALL_VIDEO_DISP, NULL, + "VIDEO_SLIDES_START"); + } } } @@ -664,8 +671,6 @@ static void stream_rtpestab_handler(struct stream *strm, void *arg) if(0==str_cmp(content, "slides")){ tmr_start(&call->tmr_slides, 1000, check_slides_stream, call); - ua_event(call->ua, UA_EVENT_CALL_VIDEO_DISP, NULL, - "VIDEO_SLIDES_START"); return; } @@ -1065,6 +1070,7 @@ int call_alloc(struct call **callp, const struct config *cfg, struct list *lst, call->estvdir = SDP_SENDRECV; call->use_rtp = prm->use_rtp; call->pfu_disabled = false; + call->slides_displayed = false; call_decode_sip_autoanswer(call, msg); call_decode_diverter(call, msg); diff --git a/src/stream.c b/src/stream.c index 9579a25f28..a56e4a5499 100644 --- a/src/stream.c +++ b/src/stream.c @@ -480,7 +480,7 @@ static void rtcp_handler(const struct sa *src, struct rtcp_msg *msg, void *arg) MAGIC_CHECK(s); - s->rx.ts_last = tmr_jiffies(); + //s->rx.ts_last = tmr_jiffies(); switch (msg->hdr.pt) { From b33c2f1d248743e12365acdcc93044e0761781fb Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Thu, 29 Jun 2023 13:50:25 +0200 Subject: [PATCH 35/38] [Fixed] RTP timeout for video slides stream --- src/call.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/call.c b/src/call.c index 459bd3b88a..119dc96234 100644 --- a/src/call.c +++ b/src/call.c @@ -938,7 +938,6 @@ int call_streams_alloc(struct call *call) baresip_vidfiltl(), !call->got_offer, video_error_handler, call); - stream_enable_rtp_timeout(video_strm(call->slides), 0); if (err) return err; @@ -2052,6 +2051,7 @@ static void set_established_mdir(void *arg) static void sipsess_estab_handler(const struct sip_msg *msg, void *arg) { struct call *call = arg; + char * content = NULL; (void)msg; MAGIC_CHECK(call); @@ -2069,7 +2069,9 @@ static void sipsess_estab_handler(const struct sip_msg *msg, void *arg) FOREACH_STREAM { struct stream *strm = le->data; - stream_enable_rtp_timeout(strm, call->rtp_timeout_ms); + content = sdp_media_rattr(stream_sdpmedia(strm), "content"); + if(0!=str_cmp(content, "slides")) + stream_enable_rtp_timeout(strm, call->rtp_timeout_ms); } } From a9037c38cf54821049d729d449c49998a07485e7 Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Wed, 13 Sep 2023 16:02:40 +0200 Subject: [PATCH 36/38] [Added] BFCP primitives handling --- src/bfcp.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/bfcp.c b/src/bfcp.c index f56a833733..b47bb48127 100644 --- a/src/bfcp.c +++ b/src/bfcp.c @@ -184,9 +184,13 @@ static void bfcp_msg_handler(const struct bfcp_msg *msg, void *arg) break; case BFCP_FLOOR_RELEASE: - break; - case BFCP_HELLO_ACK: + case BFCP_FLOOR_REQUEST_STATUS: + case BFCP_FLOOR_REQ_STATUS_ACK: + case BFCP_FLOOR_STATUS: + case BFCP_FLOOR_STATUS_ACK: + case BFCP_GOODBYE: + case BFCP_GOODBYE_ACK: break; default: From 2a0bbe52f6a202fedd52da036c3142f717f0db28 Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Mon, 4 Dec 2023 17:37:20 +0100 Subject: [PATCH 37/38] [Fixed] BFCP primitives handling --- src/bfcp.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/bfcp.c b/src/bfcp.c index b47bb48127..a38b17225e 100644 --- a/src/bfcp.c +++ b/src/bfcp.c @@ -122,19 +122,11 @@ static void bfcp_msg_handler(const struct bfcp_msg *msg, void *arg) BFCP_FLOOR_RELEASE, BFCP_FLOOR_REQUEST_QUERY, BFCP_FLOOR_REQUEST_STATUS, - BFCP_USER_QUERY, - BFCP_USER_STATUS, - BFCP_FLOOR_QUERY, - BFCP_FLOOR_STATUS, - BFCP_CHAIR_ACTION, - BFCP_CHAIR_ACTION_ACK, BFCP_HELLO, BFCP_HELLO_ACK, - BFCP_ERROR, - BFCP_FLOOR_REQ_STATUS_ACK, - BFCP_FLOOR_STATUS_ACK, BFCP_GOODBYE, - BFCP_GOODBYE_ACK }; + BFCP_GOODBYE_ACK, + BFCP_ERROR }; enum bfcp_attrib attrib[] = { BFCP_BENEFICIARY_ID, BFCP_FLOOR_ID, @@ -185,10 +177,6 @@ static void bfcp_msg_handler(const struct bfcp_msg *msg, void *arg) case BFCP_FLOOR_RELEASE: case BFCP_HELLO_ACK: - case BFCP_FLOOR_REQUEST_STATUS: - case BFCP_FLOOR_REQ_STATUS_ACK: - case BFCP_FLOOR_STATUS: - case BFCP_FLOOR_STATUS_ACK: case BFCP_GOODBYE: case BFCP_GOODBYE_ACK: break; From 362590fa1c9ce0fed767c4e85e384951551deb89 Mon Sep 17 00:00:00 2001 From: Nicolas Tizon Date: Tue, 16 Jan 2024 15:00:15 +0100 Subject: [PATCH 38/38] [Added] preferred SRTP ciphering algorithm as configuration parameter --- modules/srtp/srtp.c | 6 +++++- src/config.c | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/modules/srtp/srtp.c b/modules/srtp/srtp.c index 2c03149247..739158ee24 100644 --- a/modules/srtp/srtp.c +++ b/modules/srtp/srtp.c @@ -56,7 +56,7 @@ static const char aes_cm_128_hmac_sha1_80[] = "AES_CM_128_HMAC_SHA1_80"; static const char aes_128_gcm[] = "AEAD_AES_128_GCM"; static const char aes_256_gcm[] = "AEAD_AES_256_GCM"; -static const char *preferred_suite = aes_cm_128_hmac_sha1_80; +static const char *default_suite = aes_cm_128_hmac_sha1_80; static void destructor(void *arg) @@ -377,6 +377,7 @@ static int media_alloc(struct menc_media **stp, struct menc_sess *sess, int layer = 10; /* above zero */ int err = 0; bool mux = (rtpsock == rtcpsock); + char preferred_suite[64] = ""; (void)sess; (void)rtp; (void)raddr_rtp; @@ -422,6 +423,9 @@ static int media_alloc(struct menc_media **stp, struct menc_sess *sess, goto out; /* set our preferred crypto-suite */ + str_ncpy(preferred_suite, default_suite, sizeof(default_suite)); + conf_get_str(conf_cur(), "preferred_crypto_suite", + preferred_suite, sizeof(preferred_suite)); err |= str_dup(&st->crypto_suite, preferred_suite); if (err) goto out; diff --git a/src/config.c b/src/config.c index 9de5ac8274..ab63c914b2 100644 --- a/src/config.c +++ b/src/config.c @@ -1167,6 +1167,10 @@ int config_write_template(const char *file, const struct config *cfg) (void)re_fprintf(f, "# Module parameters\n"); (void)re_fprintf(f, "\n"); + (void)re_fprintf(f, "# SRTP parameters\n"); + (void)re_fprintf(f, "#preferred_crypto_suite\tAES_CM_128_HMAC_SHA1_80\n"); + (void)re_fprintf(f, "\n"); + (void)re_fprintf(f, "# DTLS SRTP parameters\n"); (void)re_fprintf(f, "#dtls_srtp_use_ec\tprime256v1\n"); (void)re_fprintf(f, "\n");