Changeset 9cb2370c5cde359db8d9dc9630f41da11007a639
- Timestamp:
- 19/02/07 20:24:14 (2 years ago)
- git-parent:
- Files:
-
- modules/access_output/udp.c (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
modules/access_output/udp.c
rcd72047 r9cb2370 26 26 * Preamble 27 27 *****************************************************************************/ 28 #include <vlc/vlc.h> 29 28 30 #include <stdlib.h> 29 31 #include <sys/types.h> … … 32 34 #include <errno.h> 33 35 #include <fcntl.h> 34 35 #include <vlc/vlc.h> 36 #include <assert.h> 37 36 38 #include <vlc_sout.h> 37 39 #include <vlc_block.h> … … 170 172 block_fifo_t *p_empty_blocks; 171 173 174 uint32_t sent_pkts; 175 uint32_t sent_bytes; 176 size_t rtcp_size; 177 int rtcp_handle; 178 uint8_t rtcp_data[28 + 8 + (2 * 257)]; 179 172 180 } sout_access_thread_t; 173 181 … … 190 198 #define RTP_HEADER_LENGTH 12 191 199 200 static int OpenRTCP (sout_access_out_t *obj); 201 static void SendRTCP (sout_access_thread_t *obj, uint32_t timestamp); 202 static void CloseRTCP (sout_access_thread_t *obj); 203 192 204 /***************************************************************************** 193 205 * Open: open the file 194 206 *****************************************************************************/ 207 /* FIXME: lots of leaks in error handling here! */ 195 208 static int Open( vlc_object_t *p_this ) 196 209 { … … 317 330 p_sys->i_mtu = var_CreateGetInteger( p_this, "mtu" ); 318 331 319 if( vlc_thread_create( p_sys->p_thread, "sout write thread", ThreadWrite,320 VLC_THREAD_PRIORITY_HIGHEST, VLC_FALSE ) )321 {322 msg_Err( p_access->p_sout, "cannot spawn sout access thread" );323 vlc_object_destroy( p_sys->p_thread );324 return VLC_EGENERIC;325 }326 327 332 srand( (uint32_t)mdate()); 328 333 p_sys->p_buffer = NULL; 329 334 p_sys->i_sequence_number = rand()&0xffff; 330 335 p_sys->i_ssrc = rand()&0xffffffff; 336 337 if (p_sys->b_rtpts && OpenRTCP (p_access)) 338 { 339 msg_Err (p_access, "cannot initialize RTCP sender"); 340 return VLC_EGENERIC; 341 } 342 343 if( vlc_thread_create( p_sys->p_thread, "sout write thread", ThreadWrite, 344 VLC_THREAD_PRIORITY_HIGHEST, VLC_FALSE ) ) 345 { 346 msg_Err( p_access->p_sout, "cannot spawn sout access thread" ); 347 vlc_object_destroy( p_sys->p_thread ); 348 return VLC_EGENERIC; 349 } 331 350 332 351 var_Get( p_access, SOUT_CFG_PREFIX "raw", &val ); … … 371 390 372 391 net_Close( p_sys->p_thread->i_handle ); 392 CloseRTCP (p_sys->p_thread); 373 393 374 394 vlc_object_detach( p_sys->p_thread ); … … 518 538 else 519 539 { 520 p_buffer = block_FifoGet(p_sys->p_thread->p_empty_blocks ); 540 p_buffer = block_FifoGet(p_sys->p_thread->p_empty_blocks ); 521 541 p_buffer->i_flags = 0; 522 542 p_buffer = block_Realloc( p_buffer, 0, p_sys->i_mtu ); … … 534 554 p_buffer->p_buffer[1] = 0x21; // mpeg2-ts 535 555 536 SetW LE( p_buffer->p_buffer + 2, p_sys->i_sequence_number );556 SetWBE( p_buffer->p_buffer + 2, p_sys->i_sequence_number ); 537 557 p_sys->i_sequence_number++; 538 SetDW LE( p_buffer->p_buffer + 4, i_timestamp );539 SetDW LE( p_buffer->p_buffer + 8, p_sys->i_ssrc );558 SetDWBE( p_buffer->p_buffer + 4, i_timestamp ); 559 SetDWBE( p_buffer->p_buffer + 8, p_sys->i_ssrc ); 540 560 541 561 p_buffer->i_buffer = RTP_HEADER_LENGTH; … … 558 578 # define strerror( x ) winsock_strerror( strerror_buf ) 559 579 #endif 580 size_t rtcp_counter = 0; 560 581 561 582 while( !p_thread->b_die ) … … 606 627 i_to_send = p_thread->i_group; 607 628 } 608 if( send( p_thread->i_handle, p_pk->p_buffer, p_pk->i_buffer, 0 ) 609 == -1 ) 629 ssize_t val = send( p_thread->i_handle, p_pk->p_buffer, 630 p_pk->i_buffer, 0 ); 631 if (val == -1) 610 632 { 611 633 msg_Warn( p_thread, "send error: %s", strerror(errno) ); 634 } 635 else 636 { 637 p_thread->sent_pkts++; 638 p_thread->sent_bytes += val; 639 rtcp_counter += val; 612 640 } 613 641 … … 626 654 } 627 655 #endif 656 657 if (p_thread->rtcp_handle != -1) 658 { 659 /* FIXME: this is a very incorrect simplistic RTCP timer */ 660 if ((rtcp_counter / 80) >= p_thread->rtcp_size) 661 { 662 SendRTCP (p_thread, p_pk->i_dts * 9 / 100); 663 rtcp_counter = 0; 664 } 665 } 628 666 629 667 block_FifoPut( p_thread->p_empty_blocks, p_pk ); … … 665 703 return NULL; 666 704 } 705 706 707 /* 708 * NOTE on RTCP implementation: 709 * - there is a single sender (us), no conferencing here! => n = sender = 1, 710 * - as such we need not bother to include Receiver Reports, 711 * - in unicast case, there is a single receiver => members = 1 + 1 = 2, 712 * and obviously n > 25% of members, 713 * - in multicast case, we do not want to maintain the number of receivers 714 * and we assume it is big (i.e. than 3) because that's what broadcasting is 715 * all about, 716 * - it is assumed we_sent = true (could be wrong), since we are THE sender, 717 * - we always send SR + SDES, while running, 718 * - FIXME: we do not implement separate rate limiting for SDES, 719 * - FIXME: we should send BYE when stopping, 720 * - we do not implement any profile-specific extensions for the time being. 721 */ 722 static int OpenRTCP (sout_access_out_t *obj) 723 { 724 sout_access_out_sys_t *p_sys = obj->p_sys; 725 uint8_t *ptr; 726 int fd; 727 728 char src[NI_MAXNUMERICHOST], dst[NI_MAXNUMERICHOST]; 729 int sport, dport; 730 731 fd = obj->p_sys->p_thread->i_handle; 732 if (net_GetSockAddress (fd, src, &sport) 733 || net_GetPeerAddress (fd, dst, &dport)) 734 return VLC_EGENERIC; 735 736 sport++; 737 dport++; 738 /* FIXME: should we use UDP for non-UDP protos? */ 739 fd = net_OpenDgram (obj, src, sport, dst, dport, AF_UNSPEC, IPPROTO_UDP); 740 if (fd == -1) 741 return VLC_EGENERIC; 742 743 obj->p_sys->p_thread->rtcp_handle = fd; 744 745 ptr = (uint8_t *)strchr (src, '%'); 746 if (ptr != NULL) 747 *ptr = '\0'; /* remove scope ID frop IPv6 addresses */ 748 749 ptr = obj->p_sys->p_thread->rtcp_data; 750 751 /* Sender report */ 752 ptr[0] = 2 << 6; /* V = 2, P = RC = 0 */ 753 ptr[1] = 200; /* payload type: Sender Report */ 754 SetWBE (ptr + 2, 6); /* length = 6 (7 double words) */ 755 SetDWBE (ptr + 4, p_sys->i_ssrc); 756 ptr += 28; 757 /* timestamps and counter are handled later */ 758 759 /* Source description */ 760 uint8_t *sdes = ptr; 761 ptr[0] = (2 << 6) | 1; /* V = 2, P = 0, SC = 1 */ 762 ptr[1] = 202; /* payload type: Source Description */ 763 uint8_t *lenptr = ptr + 2; 764 SetDWBE (ptr + 4, p_sys->i_ssrc); 765 ptr += 8; 766 767 ptr[0] = 1; /* CNAME - mandatory */ 768 assert (NI_MAXNUMERICHOST <= 256); 769 ptr[1] = strlen (src); 770 memcpy (ptr + 2, src, ptr[1]); 771 ptr += ptr[1] + 2; 772 773 static const char tool[] = PACKAGE_STRING; 774 ptr[0] = 6; /* TOOL */ 775 ptr[1] = (sizeof (tool) > 256) ? 255 : (sizeof (tool) - 1); 776 memcpy (ptr + 2, tool, ptr[1]); 777 ptr += ptr[1] + 2; 778 779 while ((ptr - sdes) & 3) /* 32-bits padding */ 780 *ptr++ = 0; 781 SetWBE (lenptr, ptr - sdes); 782 783 obj->p_sys->p_thread->rtcp_size = ptr - obj->p_sys->p_thread->rtcp_data; 784 return VLC_SUCCESS; 785 } 786 787 static void CloseRTCP (sout_access_thread_t *obj) 788 { 789 /* TODO: send RTCP BYE */ 790 if (obj->rtcp_handle != -1) 791 net_Close (obj->rtcp_handle); 792 } 793 794 static void SendRTCP (sout_access_thread_t *obj, uint32_t timestamp) 795 { 796 uint8_t *ptr = obj->rtcp_data; 797 SetQWBE (ptr + 8, NTPtime64 ()); 798 SetDWBE (ptr + 16, timestamp); 799 SetDWBE (ptr + 20, obj->sent_pkts); 800 SetDWBE (ptr + 24, obj->sent_bytes); 801 802 send (obj->rtcp_handle, ptr, obj->rtcp_size, 0); 803 }
