Changeset 9cb2370c5cde359db8d9dc9630f41da11007a639

Show
Ignore:
Timestamp:
19/02/07 20:24:14 (2 years ago)
Author:
Rémi Denis-Courmont <rem@videolan.org>
git-committer:
Rémi Denis-Courmont <rem@videolan.org> 1171913054 +0000
git-parent:

[c16439ab29327e0624818d26fbaabfbe890dd72e]

git-author:
Rémi Denis-Courmont <rem@videolan.org> 1171913054 +0000
Message:

Simplistic RTCP sender for access output
Still needs fixing

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • modules/access_output/udp.c

    rcd72047 r9cb2370  
    2626 * Preamble 
    2727 *****************************************************************************/ 
     28#include <vlc/vlc.h> 
     29 
    2830#include <stdlib.h> 
    2931#include <sys/types.h> 
     
    3234#include <errno.h> 
    3335#include <fcntl.h> 
    34  
    35 #include <vlc/vlc.h> 
     36#include <assert.h> 
     37 
    3638#include <vlc_sout.h> 
    3739#include <vlc_block.h> 
     
    170172    block_fifo_t *p_empty_blocks; 
    171173 
     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 
    172180} sout_access_thread_t; 
    173181 
     
    190198#define RTP_HEADER_LENGTH 12 
    191199 
     200static int OpenRTCP (sout_access_out_t *obj); 
     201static void SendRTCP (sout_access_thread_t *obj, uint32_t timestamp); 
     202static void CloseRTCP (sout_access_thread_t *obj); 
     203 
    192204/***************************************************************************** 
    193205 * Open: open the file 
    194206 *****************************************************************************/ 
     207/* FIXME: lots of leaks in error handling here! */ 
    195208static int Open( vlc_object_t *p_this ) 
    196209{ 
     
    317330    p_sys->i_mtu = var_CreateGetInteger( p_this, "mtu" ); 
    318331 
    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  
    327332    srand( (uint32_t)mdate()); 
    328333    p_sys->p_buffer          = NULL; 
    329334    p_sys->i_sequence_number = rand()&0xffff; 
    330335    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    } 
    331350 
    332351    var_Get( p_access, SOUT_CFG_PREFIX "raw", &val ); 
     
    371390 
    372391    net_Close( p_sys->p_thread->i_handle ); 
     392    CloseRTCP (p_sys->p_thread); 
    373393 
    374394    vlc_object_detach( p_sys->p_thread ); 
     
    518538    else 
    519539    { 
    520         p_buffer = block_FifoGet(p_sys->p_thread->p_empty_blocks );        
     540        p_buffer = block_FifoGet(p_sys->p_thread->p_empty_blocks ); 
    521541        p_buffer->i_flags = 0; 
    522542        p_buffer = block_Realloc( p_buffer, 0, p_sys->i_mtu ); 
     
    534554        p_buffer->p_buffer[1] = 0x21; // mpeg2-ts 
    535555 
    536         SetWLE( p_buffer->p_buffer + 2, p_sys->i_sequence_number ); 
     556        SetWBE( p_buffer->p_buffer + 2, p_sys->i_sequence_number ); 
    537557        p_sys->i_sequence_number++; 
    538         SetDWLE( p_buffer->p_buffer + 4, i_timestamp ); 
    539         SetDWLE( 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 ); 
    540560 
    541561        p_buffer->i_buffer = RTP_HEADER_LENGTH; 
     
    558578# define strerror( x ) winsock_strerror( strerror_buf ) 
    559579#endif 
     580    size_t rtcp_counter = 0; 
    560581 
    561582    while( !p_thread->b_die ) 
     
    606627            i_to_send = p_thread->i_group; 
    607628        } 
    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) 
    610632        { 
    611633            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; 
    612640        } 
    613641 
     
    626654        } 
    627655#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        } 
    628666 
    629667        block_FifoPut( p_thread->p_empty_blocks, p_pk ); 
     
    665703    return NULL; 
    666704} 
     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 */ 
     722static 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 
     787static 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 
     794static 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}