]> git.sesse.net Git - vlc/blobdiff - modules/stream_out/rtcp.c
playlist: Don't allow pl_Release(p_playlist) and pl_Yield(p_playlist).
[vlc] / modules / stream_out / rtcp.c
index b5ed1c3e938ad6394bad1a12720a743996ec5e26..cbc3dade8a96374c56197623868f763a28f7ae0b 100644 (file)
  * Preamble
  *****************************************************************************/
 
-#include <vlc/vlc.h>
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
 #include <vlc_block.h>
 
 #include <vlc_network.h>
-
-
-#include <vlc_url.h>
 #include <vlc_sout.h>
 #include "rtp.h"
 
+#include <assert.h>
+
 /*
  * NOTE on RTCP implementation:
  * - there is a single sender (us), no conferencing here! => n = sender = 1,
@@ -50,7 +53,7 @@
 struct rtcp_sender_t
 {
     size_t   length;  /* RTCP packet length */
-    uint8_t  payload[28 + 8 + (2 * 257)];
+    uint8_t  payload[28 + 8 + (2 * 257) + 8];
     int      handle;  /* RTCP socket handler */
 
     uint32_t packets; /* RTP packets sent */
@@ -59,21 +62,45 @@ struct rtcp_sender_t
 };
 
 
-rtcp_sender_t *OpenRTCP (vlc_object_t *obj, int rtp_fd,
-                         int proto, uint16_t dport)
+rtcp_sender_t *OpenRTCP (vlc_object_t *obj, int rtp_fd, int proto,
+                         bool mux)
 {
     rtcp_sender_t *rtcp;
     uint8_t *ptr;
-    char src[NI_MAXNUMERICHOST], dst[NI_MAXNUMERICHOST];
-    int sport;
     int fd;
+    char src[NI_MAXNUMERICHOST];
+    int sport;
 
-    if (net_GetSockAddress (rtp_fd, src, &sport)
-     || net_GetPeerAddress (rtp_fd, dst, NULL))
+    if (net_GetSockAddress (rtp_fd, src, &sport))
         return NULL;
 
-    sport++;
-    fd = net_OpenDgram (obj, src, sport, dst, dport, AF_UNSPEC, proto);
+    if (mux)
+    {
+        /* RTP/RTCP mux: duplicate the socket */
+#ifndef WIN32
+        fd = dup (rtp_fd);
+#else
+        WSAPROTOCOL_INFO info;
+        WSADuplicateSocket (rtp_fd, GetCurrentProcessId (), &info);
+        fd = WSASocket (info.iAddressFamily, info.iSocketType, info.iProtocol,
+                        &info, 0, 0);
+#endif
+    }
+    else
+    {
+        /* RTCP on a separate port */
+        char dst[NI_MAXNUMERICHOST];
+        int dport;
+
+        if (net_GetPeerAddress (rtp_fd, dst, &dport))
+            return NULL;
+
+        sport++;
+        dport++;
+
+        fd = net_OpenDgram (obj, src, sport, dst, dport, AF_UNSPEC, proto);
+    }
+
     if (fd == -1)
         return NULL;
 
@@ -124,10 +151,10 @@ rtcp_sender_t *OpenRTCP (vlc_object_t *obj, int rtp_fd,
 
     while ((ptr - sdes) & 3) /* 32-bits padding */
         *ptr++ = 0;
-    SetWBE (lenptr, ptr - sdes);
+    SetWBE (lenptr, (ptr - sdes - 1) >> 2);
 
     rtcp->length = ptr - rtcp->payload;
-    return VLC_SUCCESS;
+    return rtcp;
 }
 
 
@@ -137,16 +164,22 @@ void CloseRTCP (rtcp_sender_t *rtcp)
         return;
 
     uint8_t *ptr = rtcp->payload;
+    uint64_t now64 = NTPtime64 ();
+    SetQWBE (ptr + 8, now64); /* Update the Sender Report timestamp */
+
     /* Bye */
+    ptr += rtcp->length;
     ptr[0] = (2 << 6) | 1; /* V = 2, P = 0, SC = 1 */
     ptr[1] = 203; /* payload type: Bye */
     SetWBE (ptr + 2, 1);
-    /* SSRC is already there :) */
+    memcpy (ptr + 4, rtcp->payload + 4, 4); /* Copy SSRC from Sender Report */
+    rtcp->length += 8;
 
     /* We are THE sender, so we are more important than anybody else, so
      * we can afford not to check bandwidth constraints here. */
-    send (rtcp->handle, rtcp->payload, 8, 0);
+    send (rtcp->handle, rtcp->payload, rtcp->length, 0);
     net_Close (rtcp->handle);
+    free (rtcp);
 }