From 4fbef394254c54febe47e96ad72395b710dabbe5 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Thu, 28 Aug 2025 11:10:08 -0400 Subject: [PATCH] MT#63317 add rtpext printing abstraction Change-Id: I50b4bc3feef4445ccd87f4296504ec196bb8083a --- daemon/codec.c | 13 +++++------ daemon/media_player.c | 1 + daemon/media_socket.c | 50 +++++++++++++++++++++++++++++++++++++++--- include/media_socket.h | 10 +++++++++ 4 files changed, 63 insertions(+), 11 deletions(-) diff --git a/daemon/codec.c b/daemon/codec.c index 863138d98..63aac8a2d 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -2460,17 +2460,13 @@ void codec_output_rtp(struct media_packet *mp, struct codec_scheduler *csch, rh->timestamp = htonl(ts); rh->ssrc = htonl(ssrc_out->h.ssrc); - if (mp->extensions.len) { - rh->v_p_x_cc |= 0x10; - char *exts = buf + sizeof(*rh); - memcpy(exts, mp->extensions.s, mp->extensions.len); - } + size_t ext_len = mp->sink.rtpext->print(rh, buf + sizeof(*rh), mp); // add to output queue struct codec_packet *p = g_new0(__typeof(*p), 1); p->link.data = p; p->s.s = buf; - p->s.len = payload_len + sizeof(struct rtp_header) + mp->extensions.len; + p->s.len = payload_len + sizeof(struct rtp_header) + ext_len; payload_tracker_add(&ssrc_out->tracker, handler->dest_pt.payload_type); p->free_func = bufferpool_unref; p->ttq_entry.source = handler; @@ -4541,11 +4537,12 @@ void packet_encoded_packetize(AVPacket *pkt, struct codec_ssrc_handler *ch, stru // figure out how big of a buffer we need size_t payload_len = MAX(MAX(pkt->size, ch->bytes_per_packet), sizeof(struct telephone_event_payload)); - size_t payload_ext_len = payload_len + mp->extensions.len; + size_t ext_len = mp->sink.rtpext->length(mp); + size_t payload_ext_len = payload_len + ext_len; size_t pkt_len = sizeof(struct rtp_header) + payload_ext_len + RTP_BUFFER_TAIL_ROOM; // prepare our buffers char *buf = bufferpool_alloc(media_bufferpool, pkt_len); - char *payload = buf + sizeof(struct rtp_header) + mp->extensions.len; + char *payload = buf + sizeof(struct rtp_header) + ext_len; // tell our packetizer how much we want str inout = STR_LEN(payload, payload_len); // and request a packet diff --git a/daemon/media_player.c b/daemon/media_player.c index 4b17f56f6..21bbc72a1 100644 --- a/daemon/media_player.c +++ b/daemon/media_player.c @@ -789,6 +789,7 @@ static void media_player_cache_packet(struct media_player_cache_entry *entry, ch struct media_packet packet = { .rtp = &rtp, .cache_entry = entry, + .sink = { .rtpext = &rtpext_printer_copy }, }; packet.raw = STR_LEN(buf, len); packet.payload = packet.raw; diff --git a/daemon/media_socket.c b/daemon/media_socket.c index ff31dce40..d4dffee46 100644 --- a/daemon/media_socket.c +++ b/daemon/media_socket.c @@ -2053,6 +2053,31 @@ void unkernelize(struct packet_stream *ps, const char *reason) { } + +static size_t rtpext_printer_copy_length(const struct media_packet *mp) { + if (mp->rtcp) + return 0; + return mp->extensions.len; +} +static size_t rtpext_printer_copy_print(struct rtp_header *rh, void *dst, const struct media_packet *mp) { + if (!mp->extensions.len) + return 0; + if (mp->rtcp) + return 0; + + rh->v_p_x_cc |= 0x10; + memcpy(dst, mp->extensions.s, mp->extensions.len); + + return mp->extensions.len; +} + +const struct rtpext_printer rtpext_printer_copy = { + .length = rtpext_printer_copy_length, + .print = rtpext_printer_copy_print, +}; + + + // `out_media` can be NULL XXX streamline this to remove this exception const struct streamhandler *determine_handler(const struct transport_protocol *in_proto, struct call_media *out_media, bool must_recrypt) @@ -2087,8 +2112,18 @@ err: } +__attribute__((nonnull(1))) +static void __determine_rtpext_handler(struct call_media *in, struct call_media *out, struct sink_handler *sh) { + if (!sh || !out) + return; + + sh->rtpext = &rtpext_printer_copy; +} + + // sh->sink must be set void sink_handler_set_generic(struct sink_handler *sh) { + sh->rtpext = &rtpext_printer_copy; sh->handler = determine_handler(&transport_protocols[PROTO_RTP_AVP], sh->sink->media, true); } @@ -2106,8 +2141,11 @@ const struct streamhandler *determine_sink_handler(struct packet_stream *in, str if (MEDIA_ISSET(in->media, PASSTHRU)) goto noop; - in_proto = in->media->protocol; - out_proto = out ? out->media->protocol : NULL; + __auto_type media_in = in->media; + __auto_type media_out = out ? out->media : NULL; + + in_proto = media_in->protocol; + out_proto = media_out ? media_out->protocol : NULL; if (!in_proto) goto err; @@ -2135,14 +2173,20 @@ const struct streamhandler *determine_sink_handler(struct packet_stream *in, str ret = determine_handler(in_proto, out ? out->media : NULL, must_recrypt); if (sh) sh->handler = ret; + + __determine_rtpext_handler(media_in, media_out, sh); + return ret; err: ilog(LOG_WARNING, "Unknown transport protocol encountered"); noop: ret = &__sh_noop; - if (sh) + if (sh) { sh->handler = ret; + sh->rtpext = &rtpext_printer_copy; + } + return ret; } diff --git a/include/media_socket.h b/include/media_socket.h index 771cf902b..0a2e9c206 100644 --- a/include/media_socket.h +++ b/include/media_socket.h @@ -254,6 +254,11 @@ struct sink_attrs { bool egress:1; }; +struct rtpext_printer { + size_t (*length)(const struct media_packet *); + size_t (*print)(struct rtp_header *, void *dst, const struct media_packet *); +}; + /** * During actual packet handling and forwarding, * only the sink_handler objects (and the packet_stream objects they are related to) are used. @@ -263,8 +268,13 @@ struct sink_handler { const struct streamhandler *handler; int kernel_output_idx; struct sink_attrs attrs; + const struct rtpext_printer *rtpext; }; + +extern const struct rtpext_printer rtpext_printer_copy; // also acts as a dummy printer + + TYPED_GQUEUE(extmap_data, struct rtp_extension_data); struct media_packet {