]> git.sesse.net Git - vlc/blob - modules/access_output/udp.c
access_out_udp: remove "raw" mode that is not used anymore
[vlc] / modules / access_output / udp.c
1 /*****************************************************************************
2  * udp.c
3  *****************************************************************************
4  * Copyright (C) 2001-2007 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *          Eric Petit <titer@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <vlc/vlc.h>
29
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <assert.h>
35
36 #include <vlc_sout.h>
37 #include <vlc_block.h>
38
39 #ifdef HAVE_UNISTD_H
40 #   include <unistd.h>
41 #endif
42
43 #ifdef WIN32
44 #   include <winsock2.h>
45 #   include <ws2tcpip.h>
46 #else
47 #   include <sys/socket.h>
48 #endif
49
50 #include <vlc_network.h>
51
52 #if defined (HAVE_NETINET_UDPLITE_H)
53 # include <netinet/udplite.h>
54 #elif defined (__linux__)
55 # define UDPLITE_SEND_CSCOV     10
56 # define UDPLITE_RECV_CSCOV     11
57 #endif
58
59 #ifndef IPPROTO_UDPLITE
60 # define IPPROTO_UDPLITE 136 /* from IANA */
61 #endif
62 #ifndef SOL_UDPLITE
63 # define SOL_UDPLITE IPPROTO_UDPLITE
64 #endif
65
66 #define MAX_EMPTY_BLOCKS 200
67
68 #if defined(WIN32) || defined(UNDER_CE)
69 # define WINSOCK_STRERROR_SIZE 20
70 static const char *winsock_strerror( char *buf )
71 {
72     snprintf( buf, WINSOCK_STRERROR_SIZE, "Winsock error %d",
73               WSAGetLastError( ) );
74     buf[WINSOCK_STRERROR_SIZE - 1] = '\0';
75     return buf;
76 }
77 #endif
78
79 /*****************************************************************************
80  * Module descriptor
81  *****************************************************************************/
82 static int  Open ( vlc_object_t * );
83 static void Close( vlc_object_t * );
84
85 #define SOUT_CFG_PREFIX "sout-udp-"
86
87 #define CACHING_TEXT N_("Caching value (ms)")
88 #define CACHING_LONGTEXT N_( \
89     "Default caching value for outbound UDP streams. This " \
90     "value should be set in milliseconds." )
91
92 #define GROUP_TEXT N_("Group packets")
93 #define GROUP_LONGTEXT N_("Packets can be sent one by one at the right time " \
94                           "or by groups. You can choose the number " \
95                           "of packets that will be sent at a time. It " \
96                           "helps reducing the scheduling load on " \
97                           "heavily-loaded systems." )
98 #define RTCP_TEXT N_("RTCP Sender Report")
99 #define RTCP_LONGTEXT N_("Send RTCP Sender Report packets")
100 #define RTCP_PORT_TEXT N_("RTCP destination port number")
101 #define RTCP_PORT_LONGTEXT N_("Sends RTCP packets to this port (0 = auto)")
102 #define AUTO_MCAST_TEXT N_("Automatic multicast streaming")
103 #define AUTO_MCAST_LONGTEXT N_("Allocates an outbound multicast address " \
104                                "automatically.")
105 #define UDPLITE_TEXT N_("UDP-Lite")
106 #define UDPLITE_LONGTEXT N_("Use UDP-Lite/IP instead of normal UDP/IP")
107 #define CSCOV_TEXT N_("Checksum coverage")
108 #define CSCOV_LONGTEXT N_("Payload bytes covered by layer-4 checksum")
109
110 vlc_module_begin();
111     set_description( _("UDP stream output") );
112     set_shortname( "UDP" );
113     set_category( CAT_SOUT );
114     set_subcategory( SUBCAT_SOUT_ACO );
115     add_integer( SOUT_CFG_PREFIX "caching", DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
116     add_integer( SOUT_CFG_PREFIX "group", 1, NULL, GROUP_TEXT, GROUP_LONGTEXT,
117                                  VLC_TRUE );
118     add_obsolete_integer( SOUT_CFG_PREFIX "late" );
119     add_obsolete_bool( SOUT_CFG_PREFIX "raw" );
120     add_bool( SOUT_CFG_PREFIX "rtcp",  VLC_FALSE, NULL, RTCP_TEXT, RTCP_LONGTEXT,
121                                  VLC_TRUE );
122     add_integer( SOUT_CFG_PREFIX "rtcp-port",  0, NULL, RTCP_PORT_TEXT,
123                  RTCP_PORT_LONGTEXT, VLC_TRUE );
124     add_bool( SOUT_CFG_PREFIX "auto-mcast", VLC_FALSE, NULL, AUTO_MCAST_TEXT,
125               AUTO_MCAST_LONGTEXT, VLC_TRUE );
126     add_bool( SOUT_CFG_PREFIX "udplite", VLC_FALSE, NULL, UDPLITE_TEXT, UDPLITE_LONGTEXT, VLC_TRUE );
127     add_integer( SOUT_CFG_PREFIX "cscov", 12, NULL, CSCOV_TEXT, CSCOV_LONGTEXT, VLC_TRUE );
128
129     set_capability( "sout access", 100 );
130     add_shortcut( "udp" );
131     set_callbacks( Open, Close );
132 vlc_module_end();
133
134 /*****************************************************************************
135  * Exported prototypes
136  *****************************************************************************/
137
138 static const char *const ppsz_sout_options[] = {
139     "auto-mcast",
140     "caching",
141     "group",
142     "rtcp",
143     "rtcp-port",
144     "lite",
145     "cscov",
146     NULL
147 };
148
149 /* Options handled by the libvlc network core */
150 static const char *const ppsz_core_options[] = {
151     "dscp",
152     "ttl",
153     "miface",
154     "miface-addr",
155     NULL
156 };
157
158 static int  Write   ( sout_access_out_t *, block_t * );
159 static int  Seek    ( sout_access_out_t *, off_t  );
160
161 static void ThreadWrite( vlc_object_t * );
162 static block_t *NewUDPPacket( sout_access_out_t *, mtime_t );
163 static const char *MakeRandMulticast (int family, char *buf, size_t buflen);
164
165 typedef struct rtcp_sender_t
166 {
167     size_t   length;  /* RTCP packet length */
168     uint8_t  payload[28 + 8 + (2 * 257)];
169     int      handle;  /* RTCP socket handler */
170
171     uint32_t packets; /* RTP packets sent */
172     uint32_t bytes;   /* RTP bytes sent */
173     unsigned counter; /* RTP packets sent since last RTCP packet */
174 } rtcp_sender_t;
175
176 typedef struct sout_access_thread_t
177 {
178     VLC_COMMON_MEMBERS
179
180     sout_instance_t *p_sout;
181
182     block_fifo_t *p_fifo;
183
184     int         i_handle;
185
186     int64_t     i_caching;
187     int         i_group;
188
189     block_fifo_t *p_empty_blocks;
190
191     rtcp_sender_t rtcp;
192 } sout_access_thread_t;
193
194 struct sout_access_out_sys_t
195 {
196     int                 i_mtu;
197     vlc_bool_t          b_mtu_warning;
198
199     block_t             *p_buffer;
200
201     sout_access_thread_t *p_thread;
202
203 };
204
205 #define DEFAULT_PORT 1234
206 #define RTP_HEADER_LENGTH 12
207
208 static int OpenRTCP (vlc_object_t *obj, rtcp_sender_t *rtcp, int rtp_fd,
209                      int proto, uint16_t dport);
210 static void SendRTCP (rtcp_sender_t *obj, const block_t *rtp);
211 static void CloseRTCP (rtcp_sender_t *obj);
212
213 /*****************************************************************************
214  * Open: open the file
215  *****************************************************************************/
216 static int Open( vlc_object_t *p_this )
217 {
218     sout_access_out_t       *p_access = (sout_access_out_t*)p_this;
219     sout_access_out_sys_t   *p_sys;
220
221     char                *psz_dst_addr = NULL;
222     int                 i_dst_port, i_rtcp_port = 0, proto = IPPROTO_UDP;
223     const char          *protoname = "UDP";
224
225     int                 i_handle;
226
227     config_ChainParse( p_access, SOUT_CFG_PREFIX,
228                        ppsz_sout_options, p_access->p_cfg );
229     config_ChainParse( p_access, "",
230                        ppsz_core_options, p_access->p_cfg );
231
232     if (var_Create (p_access, "dst-port", VLC_VAR_INTEGER)
233      || var_Create (p_access, "src-port", VLC_VAR_INTEGER)
234      || var_Create (p_access, "dst-addr", VLC_VAR_STRING)
235      || var_Create (p_access, "src-addr", VLC_VAR_STRING))
236     {
237         return VLC_ENOMEM;
238     }
239
240     if( !( p_sys = calloc ( 1, sizeof( sout_access_out_sys_t ) ) ) )
241     {
242         msg_Err( p_access, "not enough memory" );
243         return VLC_ENOMEM;
244     }
245     p_access->p_sys = p_sys;
246
247     if (var_GetBool (p_access, SOUT_CFG_PREFIX"lite"))
248     {
249         protoname = "UDP-Lite";
250         proto = IPPROTO_UDPLITE;
251     }
252
253     i_dst_port = DEFAULT_PORT;
254     if (var_GetBool (p_access, SOUT_CFG_PREFIX"auto-mcast"))
255     {
256         char buf[INET6_ADDRSTRLEN];
257         if (MakeRandMulticast (AF_INET, buf, sizeof (buf)) != NULL)
258             psz_dst_addr = strdup (buf);
259     }
260     else
261     {
262         char *psz_parser = psz_dst_addr = strdup( p_access->psz_path );
263
264         if (psz_parser[0] == '[')
265             psz_parser = strchr (psz_parser, ']');
266
267         psz_parser = strchr (psz_parser ?: psz_dst_addr, ':');
268         if (psz_parser != NULL)
269         {
270             *psz_parser++ = '\0';
271             i_dst_port = atoi (psz_parser);
272         }
273     }
274
275     if (var_GetBool (p_access, SOUT_CFG_PREFIX"rtcp"))
276     {
277         /* This is really only for the RTP sout plugin.
278          * Doing RTCP for non RTP packet is NOT a good idea. */
279         i_rtcp_port = var_GetInteger (p_access, SOUT_CFG_PREFIX"rtcp-port");
280         if (i_rtcp_port == 0)
281             i_rtcp_port = i_dst_port + 1;
282     }
283
284     p_sys->p_thread =
285         vlc_object_create( p_access, sizeof( sout_access_thread_t ) );
286     if( !p_sys->p_thread )
287     {
288         msg_Err( p_access, "out of memory" );
289         free (p_sys);
290         free (psz_dst_addr);
291         return VLC_ENOMEM;
292     }
293
294     vlc_object_attach( p_sys->p_thread, p_access );
295     p_sys->p_thread->p_sout = p_access->p_sout;
296     p_sys->p_thread->b_die  = 0;
297     p_sys->p_thread->b_error= 0;
298     p_sys->p_thread->p_fifo = block_FifoNew( p_access );
299     p_sys->p_thread->p_empty_blocks = block_FifoNew( p_access );
300
301     i_handle = net_ConnectDgram( p_this, psz_dst_addr, i_dst_port, -1, proto );
302     free (psz_dst_addr);
303
304     if( i_handle == -1 )
305     {
306          msg_Err( p_access, "failed to create %s socket", protoname );
307          vlc_object_destroy (p_sys->p_thread);
308          free (p_sys);
309          return VLC_EGENERIC;
310     }
311     else
312     {
313         char addr[NI_MAXNUMERICHOST];
314         int port;
315
316         if (net_GetSockAddress (i_handle, addr, &port) == 0)
317         {
318             msg_Dbg (p_access, "source: %s port %d", addr, port);
319             var_SetString (p_access, "src-addr", addr);
320             var_SetInteger (p_access, "src-port", port);
321         }
322
323         if (net_GetPeerAddress (i_handle, addr, &port) == 0)
324         {
325             msg_Dbg (p_access, "destination: %s port %d", addr, port);
326             var_SetString (p_access, "dst-addr", addr);
327             var_SetInteger (p_access, "dst-port", port);
328         }
329     }
330     p_sys->p_thread->i_handle = i_handle;
331     shutdown( i_handle, SHUT_RD );
332
333     int cscov = var_GetInteger (p_access, SOUT_CFG_PREFIX"cscov");
334     if (cscov)
335     {
336         switch (proto)
337         {
338 #ifdef UDPLITE_SEND_CSCOV
339             case IPPROTO_UDPLITE:
340                 cscov += 8;
341                 setsockopt (i_handle, SOL_UDPLITE, UDPLITE_SEND_CSCOV,
342                             &(int){ cscov }, sizeof (cscov));
343                 break;
344 #endif
345 #ifdef DCCP_SOCKOPT_RECV_CSCOV
346             /* FIXME: ^^is this the right name ? */
347             /* FIXME: is this inherited by accept() ? */
348             case IPPROTO_DCCP:
349                 cscov = ((cscov + 3) >> 2) + 1;
350                 if (cscov > 15)
351                     break; /* out of DCCP cscov range */
352                 setsockopt (i_handle, SOL_DCCP, DCCP_SOCKOPT_RECV_CSCOV,
353                             &(int){ cscov }, sizeof (cscov));
354                 break;
355 #endif
356         }
357     }
358
359     p_sys->p_thread->i_caching =
360         (int64_t)1000 * var_GetInteger( p_access, SOUT_CFG_PREFIX "caching");
361     p_sys->p_thread->i_group =
362         var_GetInteger( p_access, SOUT_CFG_PREFIX "group" );
363
364     p_sys->i_mtu = var_CreateGetInteger( p_this, "mtu" );
365     p_sys->p_buffer = NULL;
366
367     if (i_rtcp_port && OpenRTCP (VLC_OBJECT (p_access), &p_sys->p_thread->rtcp,
368                                  i_handle, proto, i_rtcp_port))
369     {
370         msg_Err (p_access, "cannot initialize RTCP sender");
371         net_Close (i_handle);
372         vlc_object_destroy (p_sys->p_thread);
373         free (p_sys);
374         return VLC_EGENERIC;
375     }
376
377     if( vlc_thread_create( p_sys->p_thread, "sout write thread", ThreadWrite,
378                            VLC_THREAD_PRIORITY_HIGHEST, VLC_FALSE ) )
379     {
380         msg_Err( p_access->p_sout, "cannot spawn sout access thread" );
381         net_Close (i_handle);
382         vlc_object_destroy( p_sys->p_thread );
383         free (p_sys);
384         return VLC_EGENERIC;
385     }
386
387     p_access->pf_write = Write;
388     p_access->pf_seek = Seek;
389
390     /* update p_sout->i_out_pace_nocontrol */
391     p_access->p_sout->i_out_pace_nocontrol++;
392
393     return VLC_SUCCESS;
394 }
395
396 /*****************************************************************************
397  * Close: close the target
398  *****************************************************************************/
399 static void Close( vlc_object_t * p_this )
400 {
401     sout_access_out_t     *p_access = (sout_access_out_t*)p_this;
402     sout_access_out_sys_t *p_sys = p_access->p_sys;
403     int i;
404
405     vlc_object_kill( p_sys->p_thread );
406     for( i = 0; i < 10; i++ )
407     {
408         block_t *p_dummy = block_New( p_access, p_sys->i_mtu );
409         p_dummy->i_dts = 0;
410         p_dummy->i_pts = 0;
411         p_dummy->i_length = 0;
412         memset( p_dummy->p_buffer, 0, p_dummy->i_buffer );
413         block_FifoPut( p_sys->p_thread->p_fifo, p_dummy );
414     }
415     vlc_thread_join( p_sys->p_thread );
416
417     block_FifoRelease( p_sys->p_thread->p_fifo );
418     block_FifoRelease( p_sys->p_thread->p_empty_blocks );
419
420     if( p_sys->p_buffer ) block_Release( p_sys->p_buffer );
421
422     net_Close( p_sys->p_thread->i_handle );
423     CloseRTCP (&p_sys->p_thread->rtcp);
424
425     vlc_object_detach( p_sys->p_thread );
426     vlc_object_destroy( p_sys->p_thread );
427     /* update p_sout->i_out_pace_nocontrol */
428     p_access->p_sout->i_out_pace_nocontrol--;
429
430     msg_Dbg( p_access, "UDP access output closed" );
431     free( p_sys );
432 }
433
434 /*****************************************************************************
435  * Write: standard write on a file descriptor.
436  *****************************************************************************/
437 static int Write( sout_access_out_t *p_access, block_t *p_buffer )
438 {
439     sout_access_out_sys_t *p_sys = p_access->p_sys;
440     int i_len = 0;
441
442     while( p_buffer )
443     {
444         block_t *p_next;
445         int i_packets = 0;
446         mtime_t now = mdate();
447
448         if( !p_sys->b_mtu_warning && p_buffer->i_buffer > p_sys->i_mtu )
449         {
450             msg_Warn( p_access, "packet size > MTU, you should probably "
451                       "increase the MTU" );
452             p_sys->b_mtu_warning = VLC_TRUE;
453         }
454
455         /* Check if there is enough space in the buffer */
456         if( p_sys->p_buffer &&
457             p_sys->p_buffer->i_buffer + p_buffer->i_buffer > p_sys->i_mtu )
458         {
459             if( p_sys->p_buffer->i_dts + p_sys->p_thread->i_caching < now )
460             {
461                 msg_Dbg( p_access, "late packet for UDP input (" I64Fd ")",
462                          now - p_sys->p_buffer->i_dts
463                           - p_sys->p_thread->i_caching );
464             }
465             block_FifoPut( p_sys->p_thread->p_fifo, p_sys->p_buffer );
466             p_sys->p_buffer = NULL;
467         }
468
469         i_len += p_buffer->i_buffer;
470         while( p_buffer->i_buffer )
471         {
472             int i_payload_size = p_sys->i_mtu;
473
474             int i_write = __MIN( p_buffer->i_buffer, i_payload_size );
475
476             i_packets++;
477
478             if( !p_sys->p_buffer )
479             {
480                 p_sys->p_buffer = NewUDPPacket( p_access, p_buffer->i_dts );
481                 if( !p_sys->p_buffer ) break;
482             }
483
484             memcpy( p_sys->p_buffer->p_buffer + p_sys->p_buffer->i_buffer,
485                     p_buffer->p_buffer, i_write );
486
487             p_sys->p_buffer->i_buffer += i_write;
488             p_buffer->p_buffer += i_write;
489             p_buffer->i_buffer -= i_write;
490             if ( p_buffer->i_flags & BLOCK_FLAG_CLOCK )
491             {
492                 if ( p_sys->p_buffer->i_flags & BLOCK_FLAG_CLOCK )
493                     msg_Warn( p_access, "putting two PCRs at once" );
494                 p_sys->p_buffer->i_flags |= BLOCK_FLAG_CLOCK;
495             }
496
497             if( p_sys->p_buffer->i_buffer == p_sys->i_mtu || i_packets > 1 )
498             {
499                 /* Flush */
500                 if( p_sys->p_buffer->i_dts + p_sys->p_thread->i_caching < now )
501                 {
502                     msg_Dbg( p_access, "late packet for udp input (" I64Fd ")",
503                              mdate() - p_sys->p_buffer->i_dts
504                               - p_sys->p_thread->i_caching );
505                 }
506                 block_FifoPut( p_sys->p_thread->p_fifo, p_sys->p_buffer );
507                 p_sys->p_buffer = NULL;
508             }
509         }
510
511         p_next = p_buffer->p_next;
512         block_Release( p_buffer );
513         p_buffer = p_next;
514     }
515
516     return( p_sys->p_thread->b_error ? -1 : i_len );
517 }
518
519 /*****************************************************************************
520  * Seek: seek to a specific location in a file
521  *****************************************************************************/
522 static int Seek( sout_access_out_t *p_access, off_t i_pos )
523 {
524     msg_Err( p_access, "UDP sout access cannot seek" );
525     return -1;
526 }
527
528 /*****************************************************************************
529  * NewUDPPacket: allocate a new UDP packet of size p_sys->i_mtu
530  *****************************************************************************/
531 static block_t *NewUDPPacket( sout_access_out_t *p_access, mtime_t i_dts)
532 {
533     sout_access_out_sys_t *p_sys = p_access->p_sys;
534     block_t *p_buffer;
535
536     while ( p_sys->p_thread->p_empty_blocks->i_depth > MAX_EMPTY_BLOCKS )
537     {
538         p_buffer = block_FifoGet( p_sys->p_thread->p_empty_blocks );
539         block_Release( p_buffer );
540     }
541
542     if( p_sys->p_thread->p_empty_blocks->i_depth == 0 )
543     {
544         p_buffer = block_New( p_access->p_sout, p_sys->i_mtu );
545     }
546     else
547     {
548         p_buffer = block_FifoGet(p_sys->p_thread->p_empty_blocks );
549         p_buffer->i_flags = 0;
550         p_buffer = block_Realloc( p_buffer, 0, p_sys->i_mtu );
551     }
552
553     p_buffer->i_dts = i_dts;
554     p_buffer->i_buffer = 0;
555
556     return p_buffer;
557 }
558
559 /*****************************************************************************
560  * ThreadWrite: Write a packet on the network at the good time.
561  *****************************************************************************/
562 static void ThreadWrite( vlc_object_t *p_this )
563 {
564     sout_access_thread_t *p_thread = (sout_access_thread_t*)p_this;
565     mtime_t              i_date_last = -1;
566     mtime_t              i_to_send = p_thread->i_group;
567     int                  i_dropped_packets = 0;
568 #if defined(WIN32) || defined(UNDER_CE)
569     char strerror_buf[WINSOCK_STRERROR_SIZE];
570 # define strerror( x ) winsock_strerror( strerror_buf )
571 #endif
572
573     while( !p_thread->b_die )
574     {
575         block_t *p_pk;
576         mtime_t       i_date, i_sent;
577 #if 0
578         if( (i++ % 1000)==0 ) {
579           int i = 0;
580           int j = 0;
581           block_t *p_tmp = p_thread->p_empty_blocks->p_first;
582           while( p_tmp ) { p_tmp = p_tmp->p_next; i++;}
583           p_tmp = p_thread->p_fifo->p_first;
584           while( p_tmp ) { p_tmp = p_tmp->p_next; j++;}
585           msg_Dbg( p_thread, "fifo depth: %d/%d, empty blocks: %d/%d",
586                    p_thread->p_fifo->i_depth, j,p_thread->p_empty_blocks->i_depth,i );
587         }
588 #endif
589         p_pk = block_FifoGet( p_thread->p_fifo );
590
591         i_date = p_thread->i_caching + p_pk->i_dts;
592         if( i_date_last > 0 )
593         {
594             if( i_date - i_date_last > 2000000 )
595             {
596                 if( !i_dropped_packets )
597                     msg_Dbg( p_thread, "mmh, hole ("I64Fd" > 2s) -> drop",
598                              i_date - i_date_last );
599
600                 block_FifoPut( p_thread->p_empty_blocks, p_pk );
601
602                 i_date_last = i_date;
603                 i_dropped_packets++;
604                 continue;
605             }
606             else if( i_date - i_date_last < -1000 )
607             {
608                 if( !i_dropped_packets )
609                     msg_Dbg( p_thread, "mmh, packets in the past ("I64Fd")",
610                              i_date_last - i_date );
611             }
612         }
613
614         i_to_send--;
615         if( !i_to_send || (p_pk->i_flags & BLOCK_FLAG_CLOCK) )
616         {
617             mwait( i_date );
618             i_to_send = p_thread->i_group;
619         }
620         ssize_t val = send( p_thread->i_handle, p_pk->p_buffer,
621                             p_pk->i_buffer, 0 );
622         if (val == -1)
623         {
624             msg_Warn( p_thread, "send error: %s", strerror(errno) );
625         }
626
627         if( i_dropped_packets )
628         {
629             msg_Dbg( p_thread, "dropped %i packets", i_dropped_packets );
630             i_dropped_packets = 0;
631         }
632
633 #if 1
634         i_sent = mdate();
635         if ( i_sent > i_date + 20000 )
636         {
637             msg_Dbg( p_thread, "packet has been sent too late (" I64Fd ")",
638                      i_sent - i_date );
639         }
640 #endif
641
642         SendRTCP (&p_thread->rtcp, p_pk);
643
644         block_FifoPut( p_thread->p_empty_blocks, p_pk );
645
646         i_date_last = i_date;
647     }
648 }
649
650
651 static const char *MakeRandMulticast (int family, char *buf, size_t buflen)
652 {
653     uint32_t rand = (getpid() & 0xffff)
654                   | (uint32_t)(((mdate () >> 10) & 0xffff) << 16);
655
656     switch (family)
657     {
658 #ifdef AF_INET6
659         case AF_INET6:
660         {
661             struct in6_addr addr;
662             memcpy (&addr, "\xff\x38\x00\x00" "\x00\x00\x00\x00"
663                            "\x00\x00\x00\x00", 12);
664             rand |= 0x80000000;
665             memcpy (addr.s6_addr + 12, &(uint32_t){ htonl (rand) }, 4);
666             return inet_ntop (family, &addr, buf, buflen);
667         }
668 #endif
669
670         case AF_INET:
671         {
672             struct in_addr addr;
673             addr.s_addr = htonl ((rand & 0xffffff) | 0xe8000000);
674             return inet_ntop (family, &addr, buf, buflen);
675         }
676     }
677 #ifdef EAFNOSUPPORT
678     errno = EAFNOSUPPORT;
679 #endif
680     return NULL;
681 }
682
683
684 /*
685  * NOTE on RTCP implementation:
686  * - there is a single sender (us), no conferencing here! => n = sender = 1,
687  * - as such we need not bother to include Receiver Reports,
688  * - in unicast case, there is a single receiver => members = 1 + 1 = 2,
689  *   and obviously n > 25% of members,
690  * - in multicast case, we do not want to maintain the number of receivers
691  *   and we assume it is big (i.e. than 3) because that's what broadcasting is
692  *   all about,
693  * - it is assumed we_sent = true (could be wrong), since we are THE sender,
694  * - we always send SR + SDES, while running,
695  * - FIXME: we do not implement separate rate limiting for SDES,
696  * - we do not implement any profile-specific extensions for the time being.
697  */
698 static int OpenRTCP (vlc_object_t *obj, rtcp_sender_t *rtcp, int rtp_fd,
699                      int proto, uint16_t dport)
700 {
701     uint8_t *ptr;
702     int fd;
703
704     char src[NI_MAXNUMERICHOST], dst[NI_MAXNUMERICHOST];
705     int sport;
706
707     rtcp->bytes = rtcp->packets = rtcp->counter = 0;
708
709     if (net_GetSockAddress (rtp_fd, src, &sport)
710      || net_GetPeerAddress (rtp_fd, dst, NULL))
711         return VLC_EGENERIC;
712
713     sport++;
714     fd = net_OpenDgram (obj, src, sport, dst, dport, AF_UNSPEC, proto);
715     if (fd == -1)
716         return VLC_EGENERIC;
717
718     rtcp->handle = fd;
719
720     ptr = (uint8_t *)strchr (src, '%');
721     if (ptr != NULL)
722         *ptr = '\0'; /* remove scope ID frop IPv6 addresses */
723
724     ptr = rtcp->payload;
725
726     /* Sender report */
727     ptr[0] = 2 << 6; /* V = 2, P = RC = 0 */
728     ptr[1] = 200; /* payload type: Sender Report */
729     SetWBE (ptr + 2, 6); /* length = 6 (7 double words) */
730     memset (ptr + 4, 0, 4); /* SSRC unknown yet */
731     SetQWBE (ptr + 8, NTPtime64 ());
732     memset (ptr + 16, 0, 12); /* timestamp and counters */
733     ptr += 28;
734
735     /* Source description */
736     uint8_t *sdes = ptr;
737     ptr[0] = (2 << 6) | 1; /* V = 2, P = 0, SC = 1 */
738     ptr[1] = 202; /* payload type: Source Description */
739     uint8_t *lenptr = ptr + 2;
740     memset (ptr + 4, 0, 4); /* SSRC unknown yet */
741     ptr += 8;
742
743     ptr[0] = 1; /* CNAME - mandatory */
744     assert (NI_MAXNUMERICHOST <= 256);
745     ptr[1] = strlen (src);
746     memcpy (ptr + 2, src, ptr[1]);
747     ptr += ptr[1] + 2;
748
749     static const char tool[] = PACKAGE_STRING;
750     ptr[0] = 6; /* TOOL */
751     ptr[1] = (sizeof (tool) > 256) ? 255 : (sizeof (tool) - 1);
752     memcpy (ptr + 2, tool, ptr[1]);
753     ptr += ptr[1] + 2;
754
755     while ((ptr - sdes) & 3) /* 32-bits padding */
756         *ptr++ = 0;
757     SetWBE (lenptr, ptr - sdes);
758
759     rtcp->length = ptr - rtcp->payload;
760     return VLC_SUCCESS;
761 }
762
763 static void CloseRTCP (rtcp_sender_t *rtcp)
764 {
765     if (rtcp->handle == -1)
766         return;
767
768     uint8_t *ptr = rtcp->payload;
769     /* Bye */
770     ptr[0] = (2 << 6) | 1; /* V = 2, P = 0, SC = 1 */
771     ptr[1] = 203; /* payload type: Bye */
772     SetWBE (ptr + 2, 1);
773     /* SSRC is already there :) */
774
775     /* We are THE sender, so we are more important than anybody else, so
776      * we can afford not to check bandwidth constraints here. */
777     send (rtcp->handle, rtcp->payload, 8, 0);
778     net_Close (rtcp->handle);
779 }
780
781 static void SendRTCP (rtcp_sender_t *rtcp, const block_t *rtp)
782 {
783     uint8_t *ptr = rtcp->payload;
784
785     if ((rtcp->handle == -1) /* RTCP sender off */
786      || (rtp->i_buffer < 12)) /* too short RTP packet */
787         return;
788
789     /* Updates statistics */
790     rtcp->packets++;
791     rtcp->bytes += rtp->i_buffer;
792     rtcp->counter += rtp->i_buffer;
793
794     /* 1.25% rate limit */
795     if ((rtcp->counter / 80) < rtcp->length)
796         return;
797
798     uint32_t last = GetDWBE (ptr + 8); // last RTCP SR send time
799     uint64_t now64 = NTPtime64 ();
800     if ((now64 >> 32) < (last + 5))
801         return; // no more than one SR every 5 seconds
802
803     memcpy (ptr + 4, rtp->p_buffer + 8, 4); /* SR SSRC */
804     SetQWBE (ptr + 8, now64);
805     memcpy (ptr + 16, rtp->p_buffer + 4, 4); /* RTP timestamp */
806     SetDWBE (ptr + 20, rtcp->packets);
807     SetDWBE (ptr + 24, rtcp->bytes);
808     memcpy (ptr + 28 + 4, rtp->p_buffer + 8, 4); /* SDES SSRC */
809
810     if (send (rtcp->handle, ptr, rtcp->length, 0) == (ssize_t)rtcp->length)
811         rtcp->counter = 0;
812 }