[vlc-commits] rtp: build SDP parser in
Rémi Denis-Courmont
git at videolan.org
Wed Apr 22 21:29:26 CEST 2020
vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Wed Apr 22 21:44:17 2020 +0300| [22b0c51169f0b720afeacbcc74cd7d3855d2fd37] | committer: Rémi Denis-Courmont
rtp: build SDP parser in
This is very incomplete as yet, mostly functionally equivalent to the
parser in the SAP SD.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=22b0c51169f0b720afeacbcc74cd7d3855d2fd37
---
modules/access/rtp/rtp.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 170 insertions(+), 2 deletions(-)
diff --git a/modules/access/rtp/rtp.c b/modules/access/rtp/rtp.c
index a84f4a87cf..85aa754753 100644
--- a/modules/access/rtp/rtp.c
+++ b/modules/access/rtp/rtp.c
@@ -38,6 +38,7 @@
# include <gcrypt.h>
# include <vlc_gcrypt.h>
#endif
+#include "sdp.h"
/*
* TODO: so much stuff
@@ -157,10 +158,173 @@ static void Close (vlc_object_t *obj)
free (p_sys);
}
+static int OpenSDP(vlc_object_t *obj)
+{
+ demux_t *demux = (demux_t *)obj;
+ uint64_t size;
+ const unsigned char *peek;
+
+ assert(demux->out != NULL);
+
+ if (vlc_stream_Peek(demux->s, &peek, 3) < 3 || memcmp(peek, "v=0", 3))
+ return VLC_EGENERIC; /* not an SDP */
+
+ if (vlc_stream_GetSize(demux->s, &size))
+ size = 65536;
+ else if (size > 65536) {
+ msg_Err(obj, "SDP description too large: %zu bytes", size);
+ return VLC_EGENERIC;
+ }
+
+ /* We must peek so that fallback to another plugin works. */
+ ssize_t sdplen = vlc_stream_Peek(demux->s, &peek, size);
+ if (sdplen < 0)
+ return sdplen;
+
+ struct vlc_sdp *sdp = vlc_sdp_parse((const char *)peek, sdplen);
+ if (sdp == NULL) {
+ msg_Err(obj, "SDP description parse error");
+ return VLC_EGENERIC;
+ }
+
+ struct vlc_sdp_media *media = sdp->media;
+ if (media == NULL || media->next != NULL) {
+ msg_Dbg(obj, "only one SDP m= line supported");
+ goto error;
+ }
+
+ /* Check payload type (FIXME: handle multiple, match w/ a=rtpmap) */
+ unsigned char pt = atoi(media->format);
+ if (pt >= 64 || !(UINT64_C(0x300005d09) & (UINT64_C(1) << pt))) {
+ msg_Dbg(obj, "unsupported payload format(s) %s", media->format);
+ goto error;
+ }
+
+ if (vlc_sdp_media_attr_value(media, "control") != NULL
+ || vlc_sdp_attr_value(sdp, "control") != NULL) {
+ msg_Dbg(obj, "RTSP not supported");
+ goto error;
+ }
+
+ struct vlc_sdp_conn *conn = media->conns;
+ if (conn != NULL && conn->next != NULL) {
+ msg_Dbg(obj, "only one SDP c= line supported");
+ goto error;
+ }
+
+ if (conn == NULL)
+ conn = sdp->conn;
+ if (conn == NULL) {
+ msg_Err(obj, "missing SDP c= line");
+ goto error;
+ }
+
+ /* Determine destination port numbers */
+ unsigned int rtp_port, rtcp_port;
+
+ if (!vlc_sdp_media_attr_present(media, "rtcp-mux")) {
+ const char *rtcp = vlc_sdp_media_attr_value(media, "rtcp");
+
+ if (rtcp != NULL) {
+ /* Explicit RTCP port */
+ char *end;
+ unsigned long x = strtoul(rtcp, &end, 10);
+
+ if (*end || x == 0 || x > 65535) {
+ msg_Err(obj, "invalid RTCP port specification %s", rtcp);
+ goto error;
+ }
+
+ rtp_port = media->port;
+ rtcp_port = x;
+ } else {
+ /* Implicit RTCP port (next odd) */
+ rtp_port = (media->port + 1) & ~1;
+ rtcp_port = media->port | 1;
+ }
+ } else {
+ /* RTCP muxed on same port RTP */
+ rtp_port = media->port;
+ rtcp_port = 0;
+ }
+
+ /* TODO: support other protocols */
+ if (strcmp(media->proto, "RTP/AVP") != 0) {
+ msg_Dbg(obj, "unsupported protocol %s", media->proto);
+ goto error;
+ }
+
+ /* Determine source address */
+ char srcbuf[256], *src = NULL;
+ const char *sfilter = vlc_sdp_media_attr_value(media, "source-filter");
+ if (sfilter == NULL)
+ sfilter = vlc_sdp_attr_value(sdp, "source-filter");
+ /* FIXME: handle multiple source-filter attributes, match destination,
+ * check IP version */
+ if (sfilter != NULL
+ && sscanf(sfilter, " incl IN IP%*1[46] %*s %255s", srcbuf) == 1)
+ src = srcbuf;
+
+ /* FIXME: enforce address family */
+ int fd = net_OpenDgram(obj, conn->addr, rtp_port, src, 0, IPPROTO_UDP);
+ if (fd == -1)
+ goto error;
+
+ int rtcp_fd = -1;
+ if (rtcp_port > 0) {
+ rtcp_fd = net_OpenDgram(obj, conn->addr, rtcp_port, src, 0,
+ IPPROTO_UDP);
+ if (rtcp_fd == -1)
+ goto error;
+ }
+
+ vlc_sdp_free(sdp);
+
+ demux_sys_t *sys = malloc(sizeof (*sys));
+ if (sys == NULL)
+ {
+ net_Close(fd);
+ if (rtcp_fd != -1)
+ net_Close(rtcp_fd);
+ return VLC_EGENERIC;
+ }
+
+ sys->chained_demux = NULL;
+#ifdef HAVE_SRTP
+ sys->srtp = NULL;
+#endif
+ sys->fd = fd;
+ sys->rtcp_fd = rtcp_fd;
+ sys->max_src = var_InheritInteger(obj, "rtp-max-src");
+ sys->timeout = vlc_tick_from_sec(var_InheritInteger(obj, "rtp-timeout"));
+ sys->max_dropout = var_InheritInteger(obj, "rtp-max-dropout");
+ sys->max_misorder = var_InheritInteger(obj, "rtp-max-misorder");
+ sys->thread_ready = false;
+ sys->autodetect = true;
+
+ demux->pf_demux = NULL;
+ demux->pf_control = Control;
+ demux->p_sys = sys;
+
+ sys->session = rtp_session_create(demux);
+ if (sys->session == NULL)
+ goto error;
+
+ if (vlc_clone(&sys->thread, rtp_dgram_thread, demux,
+ VLC_THREAD_PRIORITY_INPUT))
+ goto error;
+ sys->thread_ready = true;
+ return VLC_SUCCESS;
+
+error:
+ Close (obj);
+ return VLC_EGENERIC;
+}
+
/**
* Probes and initializes.
*/
-static int Open (vlc_object_t *obj)
+static int OpenURL(vlc_object_t *obj)
{
demux_t *demux = (demux_t *)obj;
int tp; /* transport protocol */
@@ -370,8 +534,12 @@ vlc_module_begin()
set_description(N_("Real-Time Protocol (RTP) input"))
set_category(CAT_INPUT)
set_subcategory(SUBCAT_INPUT_DEMUX)
+ set_capability("demux", 55)
+ set_callbacks(OpenSDP, Close)
+
+ add_submodule()
set_capability("access", 0)
- set_callbacks(Open, Close)
+ set_callbacks(OpenURL, Close)
add_integer("rtcp-port", 0, RTCP_PORT_TEXT,
RTCP_PORT_LONGTEXT, false)
More information about the vlc-commits
mailing list